O princípio da implementação multilíngue do vscode

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.jsonprimeiro 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

Acho que você gosta

Origin blog.csdn.net/woyebuzhidao321/article/details/131495834
Recomendado
Clasificación