最近项目需要参考VS Code的插件国际化方案,网上的资料比较少,所以研究了一下,算是有点成果,记录一下。
VS Code插件的国际化,官方提供了两个工具 和 ,vscode-nls在源码中引入,对字符串进行翻译,vscode-nls-dev用于提取源码中需要翻译的字符串,生成指定格式的国际化文件。本文参考了官方提供的,同样使用gulp自动化构建工具。
个人没有做过VS Code插件开发,所以以最简单的插件做示例,对普通Javascript、Typescript、webpack三种插件开发或打包方式做国际化,三者的区别主要在gulpfile.js的编写。
准备个VS Code插件项目,安装vscode-nls、vscode-nls-dev、gulp三个包,后两个只在开发环境中使用。
Typescript只是导入vscode-nls不同,其他一致。
const nls = require('vscode-nls');
const localize = nls.loadMessageBundle();
let text = localize('nlssample.hello', 'Hello!');
// 带有参数的翻译
text = localize('nlssample.time', 'Time: {0}!', Date.now());
或者使用config自定义配置:
const localize = nls.config({
locale:'zh-cn',
bundleFormat: nls.BundleFormat.standalone,
messageFormat: nls.MessageFormat.both
})();
国际化文件有三种存在方式
config的参数主要就是配置如何使用国际化文件的。其中bundleFormat决定是使用语言包还是插件自己的国际化文件,由于vscode-nls的,两者不能共存,messageFormat用于配置使用单文件还是多文件或者都允许,但优先单文件。
nls.config一般只需要在插件入口调用一次,该接口实际返回的也是loadMessageBundle。其他文件中需要调用loadMessageBundle,该方法加载js文件相对应的翻译信息并返回一个方法。vscode-nls-dev会在loadMessageBundle参数插入当前文件路径作为上下文。
Javascript 插件代码如下,其他类型文件参考里的gulpfile.js:
const gulp = require('gulp');
const del = require('del');
const rename = require('gulp-rename');
const es = require('event-stream');
const nls = require('vscode-nls-dev');
// 支持的语言
const languages = [{ folderName: 'zh-cn', id: 'zh-cn' }];
const cleanout = function () {
return del(['out/**', 'package.nls.*.json']);
}
gulp.task('clean', cleanout);
// 源码
const sourcesNsl = function () {
var r = gulp.src(['./**/*.js', '!node_modules/**', '!gulpfile.js'])
.pipe(nls.rewriteLocalizeCalls())
.pipe(nls.createAdditionalLanguageFiles(languages, 'i18n', ''))
.pipe(nls.bundleMetaDataFiles('js-nls-sample', ''))
.pipe(nls.bundleLanguageFiles());
// 输出到out目录
return r.pipe(gulp.dest("out"));
};
// package.json
const packageNls = function () {
return gulp.src(['package.nls.json'], { allowEmpty: true })
.pipe(nls.createAdditionalLanguageFiles(languages, 'i18n'))
.pipe(gulp.dest('.'));
};
gulp.task('nls', gulp.series(cleanout, sourcesNsl, packageNls));
Typescript和Webpack参考 。该文件有比较多的细节,如果项目有不一样的配置,可以自己修改看看每一步都做了什么。我简单说明一下单一国际化文件的生成过程,对应sourcesNsl定义的任务:
// 提取需要翻译的字符串到i18n/base目录,方便翻译
const sourcesMsg = function () {
const suffix = '.i18n.json';
var r = gulp.src(['./**/*.js', '!node_modules/**', '!out/**', '!gulpfile.js'])
.pipe(nls.rewriteLocalizeCalls())
.pipe(nls.createKeyValuePairFile())
.pipe(es.through(function (file) {
// 仅处理.i18n.json
if (file.path.indexOf(suffix, file.path.length - suffix.length) !== -1) {
this.queue(file);
}
}))
.pipe(gulp.dest(`./i18n/base`));
return r;
};
// package.nls.json,结构一致,只需要拷贝一份
const packageMsg = function () {
var r = gulp.src(['package.nls.json'], { allowEmpty: true })
.pipe(rename({ basename: "package", suffix: ".i18n" }))
.pipe(gulp.dest(`./i18n/base`));
return r;
};
const messageTask = gulp.series(sourcesMsg, packageMsg);
gulp.task('message', messageTask);
与上一步一样,涉及到package.nls.json文件,这个文件是package.json里需要做的翻译,需要手动编写,gulp任务也只是拷贝了一份。
格式如下:
{
"jsnls.sample.description": "javascript extension nls example for VS Code"
}
const languages = [{ folderName: 'zh-cn', id: 'zh-cn' }];
运行gulp nls,生成单一的翻译文件,同时会生成nls.metadata.json、nls.metadata.header.json、nls.bundle.json三个文件。
{
loader: 'vscode-nls-dev/lib/webpack-loader',
options: {
base: path.join(__dirname, 'src')
}
}
base为源码路径,拼接src是为了去掉翻译信息上下文的srcconst sourcesNsl = function () {
return gulp.src(['**/*.nls.metadata.json'], { base: "./out" })
.pipe(nls.createAdditionalLanguageFiles(languages, 'i18n', ''))
.pipe(nls.bundleMetaDataFiles('webpack-nls-sample', ''))
.pipe(nls.bundleLanguageFiles())
.pipe(gulp.dest(`./out`));
};
其中gulp.src第二个参数设置了base,是因为metadata文件内容不包含上下文信息,通过路径计算需要以out为相对路径实际生成的国际化文件并不是键值对格式:
{
"extension": [
"你好!",
"时间: {0}!"
],
"hello/message": [
"这是一个示例消息"
]
}
重写源码后,localize是通过索引定位的,metadata文件里可以看到固定的顺序。
上面提到国际化文件有三种存在方式,除了语言包还有一种是多个翻译文件,比如对于extension.js文件,可以生成extension.nls.json、extension.nls.zh-cn.json文件,通过messageFormat配置支持多文件方式即可。
以普通Javascript插件为例,不需要执行bundleMetaDataFiles和bundleLanguageFiles:
const sourcesNsl = function () {
var r = gulp.src(['./**/*.js', '!node_modules/**', '!gulpfile.js'])
.pipe(nls.rewriteLocalizeCalls())
.pipe(nls.createAdditionalLanguageFiles(languages, 'i18n', ''));
// 输出到out目录
return r.pipe(gulp.dest("out"));
};
这种方式不太可能,可以测试。
vscode-nls-dev导出的接口中没有用于生成语言包国际化文件格式的接口,上面说到nls.bundle格式不是键值对,语言包中的是键值对,可以自己尝试生成。
就这些,又研究了一个没太大用的知识……
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- yrrf.cn 版权所有 赣ICP备2024042794号-2
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务