O Vscode exibe o inglês por padrão, como fazê-lo exibir o chinês por padrão? Depois de rastrear seu código por um período de tempo, aqui está um resumo.
A implementação mais simples do aplicativo front-end multilíngue tradicional pode ser gerenciada por um conjunto de sistema de gerenciamento de fluxo de dados responsivo para hospedar direitos autorais multilíngues. Ao alternar idiomas, a interface será renderizada novamente de acordo com os direitos autorais por meio da alteração do fluxo de dados. No entanto, devido à complexidade da arquitetura do VS Code, é necessário ter uma solução multilíngue compatível com a janela de renderização Electron (Chromium) e o processo Node.js.
Diferente da função de troca de idioma na página da Web, o vscode não implementa um sistema de gerenciamento de fluxo de dados responsivo. A troca de idioma do vscode é realizada baixando o plug-in do pacote de idioma necessário e o valor padrão do ambiente de desenvolvimento é o inglês. Em seguida, volte para obter o texto do idioma no pacote de idioma correspondente. Baixei o plug-in do pacote de idioma chinês com antecedência e o coloquei no código.
entrada geral
src/main.js
é acionado após o evento pronto do aplicativo
async function onReady() {
...
const [, nlsConfig] = await Promise.all([mkdirpIgnoreError(codeCachePath), resolveNlsConfiguration()]);
startup(codeCachePath, nlsConfig);
...
}
function startup(codeCachePath, nlsConfig) {
...
require('./bootstrap-amd').load('vs/code/electron-main/main', () => {
perf.mark('code/didLoadMainBundle');
});
}
Então
const metaDataFile = path.join(__dirname, 'nls.metadata.json');
const locale = getUserDefinedLocale(argvConfig);
if (locale) {
// zn-ch
const {
getNLSConfiguration } = require('./vs/base/node/languagePacks');
nlsConfigurationPromise = getNLSConfiguration(product.commit, userDataPath, metaDataFile, locale);
}
Vejamos nls.metadata.json
primeiro o arquivo.Este arquivo não existe no código-fonte, mas é gerado dinamicamente após o empacotamento.
Conteúdo geral do arquivo:
{
"keys": {
"vs/platform/terminal/node/ptyHostMain": [
"ptyHost"
],
...
},
"messages": {
"vs/platform/terminal/node/ptyHostMain": [
"Pty Host"
],
"vs/code/electron-main/main": [
"Main",
"Another instance of {0} is already running as administrator.",
"Please close the other instance and try again.",
"Another instance of {0} is running but not responding",
"Please close all other instances and try again.",
"Warning: The --status argument can only be used if {0} is already running. Please run it again after {0} has started.",
"Unable to write program user data.",
"{0}\n\nPlease make sure the following directories are writeable:\n\n{1}",
"&&Close"
],
"vs/code/electron-sandbox/processExplorer/processExplorerMain": [
"Process Name",
"CPU (%)",
"PID",
"Memory (MB)",
"Kill Process",
"Force Kill Process",
"Copy",
"Copy All",
"Debug"
],
...
},
"bundles": {
"vs/workbench/workbench.desktop.main": [
"vs/base/browser/ui/actionbar/actionViewItems",
"vs/base/browser/ui/button/button",
"vs/base/browser/ui/dialog/dialog",
...
]
...
}
}
Outra função importante é mencionada aqui localize
,
a função localize leva a src/vs/nls.js, porque o código original do código compilado não é mais visível . O palpite é encontrar a chave correspondente por meio do json e retornar o valor correspondente.
'title': localize('windowConfigurationTitle', "Window"),
- keys é o valor da chave da função localizar
- mensagens é o valor da função localizar
- bundles são todos arquivos
definição de formato de arquivo nls.metadata.json
build/azure-pipelines/upload-nlsmetadata.ts
interface NlsMetadata {
keys: {
[module: string]: string };
messages: {
[module: string]: string };
bundles: {
[bundle: string]: string[] };
}
const json: NlsMetadata = {
keys: {
},
messages: {
},
bundles: {
main: []
}
};
for (const module of modules) {
json.messages[module] = parsedJson[module].messages;
json.keys[module] = parsedJson[module].keys;
json.bundles.main.push(module);
}
parsedJson = json;
Nós os fundimos em um objeto e o efeito sai
{
'vs/workbench/electron-sandbox/desktop.contribution': {
"newTab": "New Window Tab"
}
....
}
Aqui eu baixei o plug-in do pacote de idioma chinês com antecedência e coloquei no código, vamos dar uma olhada no formato dentro
extensions/chinese-language-pack/translations/main.i18n.json
{
"vs/workbench/electron-sandbox/desktop.contribution": {
...
"newTab": "新建窗口标签页",
...
}
}
Descobriu que esta é a estrutura do arquivo do pacote de idiomas.
O Vscode analisa todos os arquivos que contêm chamadas multilíngues no tempo de compilação e gera esse arquivo nls.metadata.json.
A ordem na qual a função localize é chamada determina a ordem na qual o conteúdo de nls.metadata.json é organizado
// vs/path/to/code.ts
import * as nls from 'vs/nls';
const value = nls.localize('key1', 'Message1');
const value2 = nls.localize('key2', 'Message2');
// 在生成的 nls.matada.json 中应该是
{
"keys": {
"vs/path/to/code": [
"key1",
"key2"
]
},
"messages": {
"vs/path/to/code": [
"Message1",
"Message2"
]
}
}
Normalmente, depois de baixarmos o pacote chinês vscode, ele não terá efeito imediato, mas a janela precisa ser recarregada. Nesse momento, o arquivo languagepacks.json será gerado no diretório raiz do código. Eu também coloquei isso em antecedência antes de embalar.
Seu conteúdo geral:
{
"zh-cn": {
"hash": "1a7316c624e1dd66d26cf581ee0fb4ca",
"extensions": [
{
"extensionIdentifier": {
"id": "ms-ceintl.chinese-language-pack",
"uuid": "e4ee7751-6514-4731-9cdb-7580ffa9e70b"
},
"version": "1.66.3"
}
],
"translations": {
"vscode": "extensions/chinese-language-pack/translations/main.i18n.json",
...
},
}
}
Ok, vamos voltar para main.js
A localidade foi alterada para zn-ch, vamos ver os valores aqui https://source.chromium.org/chromium/chromium/src/+/main:ui/base/l10n/l10n_util.cc
...
"uz", // Uzbek
"vi", // Vietnamese
"wa", // Walloon
"wo", // Wolof
"xh", // Xhosa
"yi", // Yiddish
"yo", // Yoruba
"zh", // Chinese
"zh-CN", // Chinese (China)
"zh-HK", // Chinese (Hong Kong)
"zh-TW", // Chinese (Taiwan)
"zu", // Zulu
Vamos para o arquivo src/vs/base/node/languagePacks.js, aqui reescrevi dois lugares
function getLanguagePackConfigurations(userDataPath) {
// languagepacks.json复制到自己安装包,在自己安装包里面加载
/**
* @author lichangwei
* @todo 多语言处理
* @date 2022-10-27
*/
// const configFile = path.join(userDataPath, 'languagepacks.json');
/**
* mac : /Users/liuchongyang/site/vscode/.build/electron/律动.app/Contents/MacOS/Electron
* wins: D:\site\xinchengkeji\vscode-new\.build\electron\律动.exe
*/
// console.log(11111, app.getPath('exe'))
const isWindows = (process.platform === 'win32');
const isDarwin = (process.platform === 'darwin');
let appPath = '';
if (isDarwin) {
appPath = path.dirname(path.dirname(app.getPath('exe')));
} else {
appPath = path.dirname(app.getPath('exe'));
}
const configFile = path.join(appPath, 'Resources', 'app', 'languagepacks.json');
try {
return nodeRequire(configFile); // require.__$__nodeRequire
} catch (err) {
// Do nothing. If we can't read the file we have no
// language pack config.
}
return undefined;
}
const configs = getLanguagePackConfigurations(userDataPath); // 加载到了languagePacks.js内容
if (!configs) {
return defaultResult(initialLocale);
}
locale = resolveLanguagePackLocale(configs, locale); // zh-cn
if (!locale) {
return defaultResult(initialLocale);
}
/**
* @author lichangwei
* @todo 多语言处理
* @date 2022-10-27
*/
const packConfig = configs[locale];
const isDarwin = (process.platform === 'darwin');
let appContentPath = '';
if (isDarwin) {
appContentPath = path.dirname(path.dirname(app.getPath('exe')));
} else {
appContentPath = path.dirname(app.getPath('exe'));
}
const appPath = path.join(appContentPath, 'Resources', 'app');
for (let item in packConfig['translations']) {
const itemPath = packConfig['translations'][item];
const joinPath = path.join(appPath, itemPath);
if (!itemPath.includes(appPath)) {
packConfig['translations'][item] = joinPath;
}
}
const languagepacksPath = path.join(appContentPath, 'Resources', 'app', 'languagepacks.json');
// 这里对languagePacks.js里面的文件路径进行了重写,相对路径改成了绝对路径
writeFile(languagepacksPath, JSON.stringify(configs));
Por que reescrever languagePacks.js aqui? Como languagePacks.js costumava ser um caminho relativo, arquivos multilíngues não seriam encontrados aqui, então foi alterado para um caminho absoluto
Depois que o software é iniciado aqui, o chinês pode ser exibido primeiro