在 github/awesome-copilot 仓库里翻 Skill 的时候,我被这个文件卡住了。430 个 SKILL.md,中位数 6668 字节,均值 8961,最长的一个接近 29 万字节。而
vscode-ext-localization只有 1473 字节,一个文件,没有脚本,没有参考文档,也没有任何示例,是整个仓库最小的 33 个之一。
按体量判断,这种文件基本等于没写。但读完那三十行之后我改了主意。它要解决的不是“怎么用工具”,而是“团队里最容易烂、最没人愿意管的那件事,到底归谁管”。

VS Code 扩展的本地化恰好就是这件事。你加一个 setting,加一个 command,改一句运行时提示,十几种语言的翻译文件在同一秒全部过期。没人记得同步,也没人会主动去查哪个文件缺了哪条 key。
所以我打算把它拆开看完:一个极简 Skill 靠什么立住,在哪一步明显没走完,以及真要落地还差哪几块。顺带提一句,整个仓库里带 vscode-ext- 前缀的只有两个,另一个是 1545 字节的 vscode-ext-commands,同一次提交进来的。
先把文件摊开。整个 SKILL.md 只有四块内容:
-
YAML frontmatter -
一句功能声明 -
两条触发条件 -
三条资源映射
没有 Few-shot,没有反面示例,没有参考链接。这种密度在 430 个 Skill 里反而成了一种设计选择,它逼着每一句话都落到具体文件名上,没地方写“注意保持一致性”那种正确的废话。
---
name: vscode-ext-localization
description: 'Guidelines for proper localization of VS Code extensions, following VS Code extension development guidelines, libraries and good practices'
---
frontmatter 里真正干活的只有 description 这一行。Agent 决定要不要加载这个 Skill,靠的就是这句话里的关键词命中。“VS Code extensions”“localization”“guidelines”三个词撑起了全部路由。
有意思的是描述里没出现任何一个具体文件名。Agent 看到它时只知道“这个 Skill 管 VS Code 扩展本地化规范”,不知道管的是 package.nls 还是 bundle.l10n。这在触发精度上是个隐患,所有跟 i18n 沾边的请求都可能把它拉起来。
再往下是两条触发条件,写得相当具体。第一条管 contributed configurations,具体覆盖这几类:
-
settings -
commands -
menus -
views -
walkthroughs
第二条管源码里面向用户的字符串。这两条基本圈定了 VS Code 扩展里所有会出现英文的地方,边界划得比很多几千字节的 Skill 都干净。
然后是一个结构上的瑕疵,## When to use this skill 用的是 H2,紧接着的 # Instructions 却跳回了 H1:
## When to use this skill
Use this skill when you need to:
- Localize new or existing contributed configurations ...
- Localize new or existing messages or other string resources ...
# Instructions ← 层级倒挂,应为 ## Instructions
同一份文件里标题倒挂不是风格选择,是笔误。Markdown 渲染出来 Instructions 会跟文档主标题同级,人读着别扭,Agent 的章节切分也可能跟着错位。这种小东西在所有 Skill 里都常见,但它说明这个文件写完就没再回头看过一眼。
三条映射,和它背后那句真规则
Instructions 正文第一句才是全篇最值钱的地方,可惜很多人会直接扫过去。“When a new localizable resource is created or updated, the corresponding localization for all currently available languages must be created/updated.”翻成大白话就是:动一个,就得动全部。
这才是本地化真正的痛点。加一个 setting 不难,难的是加完之后你得记得去十几个 package.nls.xx.json 里各补一条 key。而 AI 最容易犯的错恰恰是只改 package.json 和英文那一份,剩下的一句不提。
后面三条是查表。每条结构一模一样:先说资源类型,再用 -> 指向产物文件的命名模板,最后给一个 pt-br 的具体例子。
| 资源所在位置 | 产物命名模板 | pt-br 示例 |
|---|---|---|
package.json 里的 settings / commands / menus / views / ViewsWelcome / walkthrough 标题 |
package.nls.LANGID.json |
package.nls.pt-br.json |
| walkthrough 正文(独立 Markdown 文件) | walkthrough/<name>.LANGID.md |
walkthrough/someStep.pt-br.md |
| 源码 JS / TS 里的消息与字符串 | bundle.l10n.LANGID.json |
bundle.l10n.pt-br.json |
这套映射的精度是够的。它没说“新建一个翻译文件”这种废话,而是直接给出 package.nls.LANGID.json 这种可执行的模板。对 Agent 来说,有模板和没模板完全是两回事。
全篇唯一用到的具体语言 ID 是 pt-br。这个选择本身就在传递信息:语言码小写、地区码用连字符、大小写不敏感但约定小写。可惜这条规矩是隐含的,没有显式写出来,遇到 zh-cn 还是 zh-CN 这种真实分歧时,Skill 帮不上忙。

官方体系里,生成产物这一步
问题也在这里:这个 Skill 只告诉你产物该放哪,完全没告诉你产物怎么来。你要手写 package.nls.zh-cn.json 吗,还是有什么工具能生成?
官方给的是 @vscode/l10n-dev,最新 v0.0.35,上月下载量 53.9 万次。它做的事情是扫你的源码,把所有 vscode.l10n.t(...) 调用里的字符串抽出来,生成 bundle.l10n.json。
npx @vscode/l10n-dev export -o ./l10n ./src
前提是你在代码里用了 vscode.l10n.t。这是 VS Code 1.72 引入的官方 API,用来取代老的 vscode-nls 和 vscode-nls-dev。老包还能跑,但不会再有新功能。
import * as vscode from 'vscode';
// 最简形式
vscode.window.showInformationMessage(vscode.l10n.t('Hello'));
// 带占位符
vscode.l10n.t('Hello {0}', userName);
// 带译者注释,译员靠这个理解 {0} 到底是什么
vscode.l10n.t({
message: 'Hello {0}',
args: [userName],
comment: ['The name of the user']
});
还有个硬性前提,package.json 里必须声明 l10n 目录,否则运行时根本找不到 bundle。这一步漏了,前面全白做。
{
"main": "./out/extension.js",
"l10n": "./l10n"
}
拿到 bundle.l10n.json 之后才进入真正的翻译流程。官方的做法是生成 XLF 交给译员,译完再导回来。如果你压根不懂外语,还有一条零成本捷径:伪本地化,生成 qps-ploc 语言包,装个 Pseudo Language Pack 就能肉眼看出哪些字符串漏标了。
# 生成 XLF 交给译员
npx @vscode/l10n-dev generate-xlf ./package.nls.json ./l10n/bundle.l10n.json -o ./vscode-ext.xlf
# 译员返回后导回各语言
npx @vscode/l10n-dev import-xlf ./translations/vscode-ext.zh-cn.xlf
# 零外语成本验证:生成伪本地化包
npx @vscode/l10n-dev generate-pseudo -o ./l10n/ ./l10n/bundle.l10n.json ./package.nls.json

哪些场景它管用,哪些场景它装死
判断一个 Skill 值不值得装,最实在的办法是把它丢进真实场景里挨个过。我按自己写扩展时遇到的情况分了七类,覆盖度差别很大。
| 场景 | 覆盖情况 | 说明 |
|---|---|---|
| 新增 setting / command / menu | 完整 | 直接给出 package.nls 命名模板 |
| 改源码里的用户可见提示语 | 完整 | 明确指向 bundle.l10n |
| walkthrough 步骤文档 | 完整 | 单独建带 LANGID 的 md 文件 |
| 修改一条已存在的 key | 半覆盖 | 只在开头一句提了“必须全量同步”,没有校验手段 |
| Webview 内部文案 | 无 | vscode.l10n.t 在 Webview 里拿不到 |
| 子进程 / Worker 里的字符串 | 无 | 需要 @vscode/l10n 单独配置 |
| 遥测与日志文案 | 无 | 这类本就不该本地化,Skill 没说“不要做” |
前三种是它的主场。你跟 Agent 说“给这个扩展加中文翻译”,它能立刻对上号:package.json 的贡献点走 package.nls,源码字符串走 bundle.l10n,walkthrough 单独建文件。这一层它的表现比很多几千字节的 Skill 都稳。
第四种是最常见的真实场景,也是最薄弱的地方。改一条已有文案,Skill 会告诉你“所有语言都要同步更新”,但它不告诉你怎么检查有没有漏。规则立了,执行手段没有。
后面三种是明确的盲区。Webview 是个大坑,vscode.l10n.t 只存在于扩展宿主进程,Webview 拿不到。官方解法是引入 @vscode/l10n 这个 npm 包,把 bundle 的 URI 传进去手工配置。
这块值得单独说一句:@vscode/l10n 上月下载 2507 万次,比 l10n-dev 高出两个数量级。这个数字我没法拆出多少是直接引用,从量级看大部分应该是传递依赖带进来的,但也侧面说明子进程场景在真实扩展里有多普遍。
我会怎么补这三十行
先说它做对的地方。三条映射给的命名模板是可执行的,不是“新建一个翻译文件”这种正确的废话。全量同步规则放在 Instructions 第一句而不是结尾,优先级给得很清楚。这两个决定让 1473 字节产生了远超体量的约束力。

缺的东西也很清楚,我数下来至少四块:
-
LANGID 规范:哪些语言 ID 合法,大小写怎么定,zh-cn 还是 zh-CN -
生成方式: vscode.l10n.t的三种签名,l10n-dev 的四个命令怎么用 -
反面约束:command id 不能翻译、key 名不能本地化、 %key%占位符必须留在 package.json 里 -
校验手段:CI 里怎么自动拦截“某个语言 bundle 缺了 key”
第三条尤其重要。现在的 Skill 只说“要做什么”,一句“不要做什么”都没有。而 Agent 犯错的高发区恰恰在反面:把 extension.sayHello.title 这个 key 本身也一起翻译了,结果 VS Code 找不到对应条目,界面直接显示原始占位符。
补齐之后大概会涨到 4000 到 5000 字节,仍然远低于仓库中位数。我觉得这个体量是对的:Skill 不是文档,塞太多等于把整篇文档推进上下文,Agent 反而抓不住重点。
真正让我记住的是它的定位选择。它没打算教会你本地化,它只固化一条团队约定:动一个就要动全部,产物必须落在指定文件里。约束型 Skill 的价值就在这种地方,跟知识量基本没关系。
资源地址
| 资源 | 链接 |
|---|---|
| Smithery 技能页 | https://smithery.ai/skills/github/vscode-ext-localization |
| SKILL.md 源码 | https://github.com/github/awesome-copilot/blob/main/skills/vscode-ext-localization/SKILL.md |
| awesome-copilot 仓库 | https://github.com/github/awesome-copilot |
| 官方 l10n 示例 | https://github.com/microsoft/vscode-extension-samples/tree/main/l10n-sample |
| @vscode/l10n-dev | https://www.npmjs.com/package/@vscode/l10n-dev |
| microsoft/vscode-l10n | https://github.com/microsoft/vscode-l10n |
回头看
一句话评价:值得装,但只在你已经在写 VS Code 扩展、并且已经决定要做多语言的前提下。它管的是纪律,不是知识,别指望它教你本地化。
如果你自己要写这类 Skill,我建议先问一个问题:我要固化的是知识还是约定。知识型 Skill 怎么写都嫌短,约定型 Skill 超过 2000 字就开始稀释重点。
还有个没查完的事留给你。这个 Skill 是 2026 年 1 月 11 日一次提交进来的,之后再没动过,Smithery 上显示 21 次安装。awesome-copilot 里有多少 Skill 处于这种“提交即完成”的状态,我没统计完,有兴趣可以顺着 commit history 自己看一眼。

