本地化与语言
本地化(l10n)让插件面向全球用户:界面文案跟随 VS Code 显示语言自动切换。VS Code 的本地化体系分为静态(package.json 描述)与动态(运行时字符串)两层。
本地化体系总览
text
package.nls.json 英文(默认)插件描述
package.nls.zh-cn.json 简体中文插件描述
└─ contributes 静态文本
l10n bundle(extension.l10n.zh-cn.json) 运行时字符串翻译
└─ vscode.l10n.t() 动态文本| 层级 | 覆盖内容 | 文件 |
|---|---|---|
| 静态 | 命令名、菜单标题、配置描述 | package.nls.json |
| 动态 | 运行时提示、错误消息 | l10n bundle |
插件描述本地化
VS Code 启动时根据显示语言自动选择 package.nls.<语言>.json:
package.nls.json(默认英文)
json
{
"mylinter.commands.run": "Run MyLinter",
"mylinter.config.enable": "Enable MyLinter",
"mylinter.config.maxWarnings": "Maximum number of warnings"
}package.nls.zh-cn.json(简体中文)
json
{
"mylinter.commands.run": "运行 MyLinter",
"mylinter.config.enable": "启用 MyLinter",
"mylinter.config.maxWarnings": "最大警告数"
}package.json 引用翻译键
package.json 中的显示文本用 %键名% 占位:
json
{
"contributes": {
"commands": [
{
"command": "mylinter.run",
"title": "%mylinter.commands.run%"
}
],
"configuration": {
"properties": {
"mylinter.enable": {
"type": "boolean",
"default": true,
"description": "%mylinter.config.enable%",
"markdownDescription": "%mylinter.config.enable%"
}
}
}
}
}语言文件命名
| 文件 | 适用语言 |
|---|---|
package.nls.json | 默认(英语) |
package.nls.zh-cn.json | 简体中文 |
package.nls.zh-tw.json | 繁体中文 |
package.nls.ja.json | 日语 |
package.nls.de.json | 德语 |
命名遵循 BCP 47 语言标签:zh-cn、zh-tw、ja、de、fr 等。
contributes.localizations 注册
高级用法:手动注册本地化资源,指定翻译文件路径:
json
{
"contributes": {
"localizations": [
{
"languageId": "zh-cn",
"languageName": "Chinese (Simplified)",
"localizedLanguageName": "简体中文",
"translations": [
{
"id": "vscode",
"path": "./translations/vscode.zh-cn.json"
},
{
"id": "myextension",
"path": "./translations/myextension.zh-cn.json"
}
]
}
]
}
}| 字段 | 说明 |
|---|---|
languageId | 语言标识(BCP 47) |
translations | 翻译资源列表(id 为扩展 ID 或 vscode) |
vscode.l10n.t 运行时翻译
代码中的字符串用 vscode.l10n.t 包裹,自动加载翻译:
typescript
import * as vscode from 'vscode';
export async function runCheck() {
const result = await performCheck();
if (result.hasError) {
// 可翻译字符串
vscode.window.showErrorMessage(
vscode.l10n.t('检查失败:{0} 个错误', result.errorCount)
);
}
vscode.window.showInformationMessage(
vscode.l10n.t('检查通过,共 {0} 个文件', result.fileCount)
);
}占位符语法
typescript
// 数字占位符 {0} {1}...
vscode.l10n.t('找到 {0} 个问题', issues.length);
// 命名占位符(推荐,可读性更好)
vscode.l10n.t('文件 {file} 无法读取:{reason}', {
file: uri.fsPath,
reason: err.message
});
// 无占位符
vscode.l10n.t('操作已取消');| 写法 | 示例 |
|---|---|
| 位置占位符 | t('共 {0} 条', n) |
| 命名占位符 | t('打开 {name}', { name }) |
| 复数处理 | t('{0} 个文件', n) 翻译端自行处理 |
生成翻译文件
VS Code 的本地化系统基于 l10n bundle 文件。目录结构约定:
text
extension/
├── package.nls.json
├── package.nls.zh-cn.json
└── l10n/
├── bundle.l10n.json 提取的字符串源
└── bundle.l10n.zh-cn.json 中文翻译提取字符串
用 @vscode/l10n-dev 工具提取代码中的可翻译字符串:
text
# 安装工具
npm install -g @vscode/l10n-dev
# 从源码提取生成 bundle.l10n.json
npx @vscode/l10n-dev export --outDir ./l10n ./src生成的 bundle.l10n.json:
json
{
"检查失败:{0} 个错误": "检查失败:{0} 个错误",
"检查通过,共 {0} 个文件": "检查通过,共 {0} 个文件",
"文件 {file} 无法读取:{reason}": "文件 {file} 无法读取:{reason}"
}翻译文件
json
{
"检查失败:{0} 个错误": "Check failed: {0} errors",
"检查通过,共 {0} 个文件": "Check passed, {0} files scanned",
"文件 {file} 无法读取:{reason}": "Cannot read {file}: {reason}"
}指定 bundle 路径
在 package.json 声明 l10n bundle 位置:
json
{
"l10n": "./l10n"
}声明后,vscode.l10n.t 从 ./l10n/bundle.l10n.<语言>.json 加载翻译。
翻译键与字符串映射
vscode.l10n.t 的匹配逻辑:
text
用户显示语言 zh-cn
→ 查找 ./l10n/bundle.l10n.zh-cn.json
→ 以英文源字符串为 key 查找翻译
→ 找到则用翻译,否则用原文翻译文件的 key 是源码中的英文/原始字符串,value 是目标语言译文。所以代码中统一使用一种语言书写可翻译字符串(习惯用英语),翻译文件按语言提供译文。
更新流程
新增字符串
typescript
// 1. 代码中使用新字符串
vscode.window.showInformationMessage(
vscode.l10n.t('配置已重置')
);text
# 2. 重新提取
npx @vscode/l10n-dev export --outDir ./l10n ./src
# 3. 翻译文件补充译文(手动或交给翻译平台)修改字符串
修改源码中的字符串会改变 key,需要同步更新所有翻译文件。建议:保持 key 稳定,用占位符传参而非拼接。
常见本地化问题
| 问题 | 处理 |
|---|---|
| 中文直接写在代码里 | 改用 vscode.l10n.t 包裹 |
| 字符串拼接 | 用占位符 {0} 而非 + |
| 忘记添加 nls 翻译 | 检查 %键% 是否有对应语言文件 |
| bundle 未生效 | 确认 package.json 的 l10n 字段路径 |
| 繁体缺失 | 补充 package.nls.zh-tw.json 与 bundle 翻译 |
完整示例
typescript
import * as vscode from 'vscode';
export function activate(context: vscode.ExtensionContext) {
context.subscriptions.push(
vscode.commands.registerCommand('mylinter.run', async () => {
const result = await checkAll();
// 动态字符串本地化
if (result.errorCount > 0) {
vscode.window.showErrorMessage(
vscode.l10n.t('检查发现 {0} 个错误', result.errorCount)
);
} else {
vscode.window.showInformationMessage(
vscode.l10n.t('检查完成,未发现问题')
);
}
})
);
}本地化让插件走出单一语言环境。最后一块拼图是快捷键:为用户提供键盘入口。