惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

F
Fortinet All Blogs
爱范儿
爱范儿
P
Proofpoint News Feed
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
T
Tailwind CSS Blog
J
Java Code Geeks
宝玉的分享
宝玉的分享
Jina AI
Jina AI
B
Blog
N
Netflix TechBlog - Medium
Recent Announcements
Recent Announcements
aimingoo的专栏
aimingoo的专栏
腾讯CDC
C
Check Point Blog
The Cloudflare Blog
阮一峰的网络日志
阮一峰的网络日志
博客园 - Franky
罗磊的独立博客
B
Blog RSS Feed
WordPress大学
WordPress大学
小众软件
小众软件
博客园 - 叶小钗
M
MIT News - Artificial intelligence
GbyAI
GbyAI

Anyeの小站

PlayGuard,让你的播放器老实点! Peg - 命令行便签 · 把终端输出钉上布告板 2025 年终总结:折腾不止,热情常青 告别公网暴露风险:mTLS助你构建家里云安全边界 🚀 0 代码部署:Halo 博客与企业门户系统 B站跟随系统深色模式脚本——让你的B站体验更丝滑 【1024抽奖】EdgeOne下线源站防护?这个办法更简单! 全新!Edge 还是卸载不掉?来试试这个! 混元模型玩家必看:CNB API 不限量调用! 1Panel 应用商店如何上架应用 Next Terminal 实战:内网无密码安全登录 用了 EdgeOne 降本增效,源站却可能裸奔? 降本增效!上云真香! 在线重装 Proxmox VE SSL证书申请老出问题?这套组合直接帮你搞定! 🌐 森屿云:让数字化转型像呼吸一样自然 1Panel v2 首发体验(alpha) DockerHub Mirror 终极解决方案——零成本,速度超快! 本地跑不动 QwQ?快用 CNB,免费运行满血 QwQ! Docker Push 巨慢?Skopeo 来拯救 2024 年终总结:与 17170 位读者相遇的旅程 云厂 200Mbps 小鸡,家里云的希望 Halo 插件 thyuu-embed 主题样式注入模板 Windows 11 卸载 Edge 小破站 6 级萌新前来挑战硬核会员,答题分享 手机系统杂谈 1Panel 自建邮局 - Docker Mailserver 1Panel 推送 SSL 证书到阿里云、腾讯云 整了几个简洁的单页,欢迎来扒 1Panel 部署 Logto 对接自有平台
Vscode/Code-Server 安装中文包——CI/CD
Anye · 2025-04-20 · via Anyeの小站

前言

啊好多人问我怎么还不更新,其实本月是已经写了一篇测评的,但是鉴于过于超前会给产品带来不好的影响,所以就没有公开。那么既然这样本月就再更新一篇。

首先 声明 一点,安装中文包的初衷不是看不懂英文,也不是对某些语言有偏见,既然它存在必然有其存在的理由,所以本文仅从技术的角度分析如何安装。

由于 Code-server 是基于 Vscode 的二开版本,本文将以 Code-server 为例来讲解。

项目链接

https://github.com/microsoft/vscodehttps://github.com/coder/code-server

问题初现

可能有人看到这个标题会很好奇,Vscode 安装中文语言包?那不是几秒钟的事?

啊确实,但是那是基于在 GUI 环境下,但是如果是在运行之前就将其设定为中文启动呢?

你可能又会说,这有何难,安装中文语言包不就行了,再改个配置文件,不一样可以实现?

那么问题就出在了这里,Vscode 上游有 BUG !

根据 Vscode 官网文档:我们是可以通过修改 .vscode/argv.json 的内容来实现修改为中文的(对于 Code-server 来说是 $HOME/.local/share/code-server/User/argv.json)。

那么查看一下手动修改中文后的 argv.json 文件是什么样的:

{
  "locale": "zh-cn"
}

啊🤔,秒了?这好像没难度,那么我就这么写?

curl -fsSL https://code-server.dev/install.sh | sh && \
    code-server --install-extension ms-ceintl.vscode-language-pack-zh-hans

cat >> $HOME/.local/share/code-server/User/argv.json << EOF
{
  "locale": "zh-cn"
}
EOF

测试运行!

好好好。。。有问题 🤣👉🤡

那么我都文档操作都有问题,想必也不是个例,看看 issue 吧

显然许多人也遇到了同样的问题,通过查看 issue,发现这似乎与 languagepacks.json 文件有关

验证猜想

但是毕竟这条回答来源于 2021 年,其问题是否被修复难以确认,根据这个提示,我就尝试在 $HOME/.local/share/code-server/ 文件夹下起了一个 git 来查看是否确实是这个原因

切换语言,发现确实生成了 languagepacks.json ,那么 issue 中提到的手动复制 languagepacks.json 的办法应该确实可行,

进阶实现

但是 languagepacks.json 里是存在插件版本信息的,每次手动本地生成复制也不是办法,那么有没有办法手动用脚本生成 languagepacks.json 呢,这样就只需要安装插件后执行脚本生成就好了。

translations

观察 languagepacks.json 中的数据,动态变化的应该是 hash uuid translations 这几个值了,先看看插件包里是否存在

大概可以看出来 translations 是用语言包里 package.json 的相对路径改成绝对路径即可。

uuid

uuid 应该也是有的,全局搜索下先:

不错不错,$HOME/.local/share/code-server/extensions/extensions.json 就有,直接拿过来就好。

hash

这应该是得算了,翻翻源码看看是怎么算的

就在这里了,看看实现:

private updateHash(languagePack: ILanguagePack): void {
	if (languagePack) {
		const md5 = createHash('md5'); // CodeQL [SM04514] Used to create an hash for language pack extension version, which is not a security issue
		for (const extension of languagePack.extensions) {
			md5.update(extension.extensionIdentifier.uuid || extension.extensionIdentifier.id).update(extension.version); // CodeQL [SM01510] The extension UUID is not sensitive info and is not manually created by a user
		}
		languagePack.hash = md5.digest('hex');
	}
}

原来是拼接了 UUID 和 VERSION,那就好说,一句话解决:

HASH=$(echo -n "$LANGUAGE_PACK_UUID$LANGUAGE_PACK_VERSION" | md5sum | awk '{print $1}')

那就来个脚本

https://cnb.cool/Anyexyz/DevEnv/default-dev-env/-/blob/main/create_languagepacks
#!/bin/bash

# 定义路径
EXTENSIONS_DIR="$HOME/.local/share/code-server/extensions"
OUTPUT_DIR="$HOME/.local/share/code-server"
LANGUAGE_PACK_PREFIX="ms-ceintl.vscode-language-pack-"

# 定义输出文件
LANGUAGEPACKS_FILE="$OUTPUT_DIR/languagepacks.json"
ARGV_FILE="$OUTPUT_DIR/User/argv.json"
EXTENSIONS_JSON="$EXTENSIONS_DIR/extensions.json"

# 创建 User 目录(如果不存在)
mkdir -p "$(dirname "$ARGV_FILE")"

# 查找语言包目录
LANGUAGE_PACK_FOLDER=$(find "$EXTENSIONS_DIR" -type d -name "${LANGUAGE_PACK_PREFIX}*" | head -n 1)

# 检查语言包文件夹是否存在
if [ -z "$LANGUAGE_PACK_FOLDER" ]; then
  echo "未找到语言包文件夹,请确保路径正确。"
  exit 1
fi

# 从 package.json 中提取数据
PACKAGE_JSON="$LANGUAGE_PACK_FOLDER/package.json"
if [ ! -f "$PACKAGE_JSON" ]; then
  echo "未找到 package.json 文件,请检查语言包目录。"
  exit 1
fi

# 从 extensions.json 中提取 UUID
if [ ! -f "$EXTENSIONS_JSON" ]; then
  echo "未找到 extensions.json 文件,请检查路径。"
  exit 1
fi

LANGUAGE_PACK_NAME=$(jq -r '.name' "$PACKAGE_JSON")
echo "找到语言包: $LANGUAGE_PACK_NAME"
LANGUAGE_PACK_UUID=$(jq -r --arg id "ms-ceintl.$LANGUAGE_PACK_NAME" '.[] | select(.identifier.id == $id) | .identifier.uuid' "$EXTENSIONS_JSON")

if [ -z "$LANGUAGE_PACK_UUID" ]; then
  echo "未能在 extensions.json 中找到对应语言包的 UUID"
  exit 1
fi

# 提取其他必要信息
LANGUAGE_ID=$(jq -r '.contributes.localizations[0].languageId' "$PACKAGE_JSON")
LANGUAGE_LABEL=$(jq -r '.contributes.localizations[0].localizedLanguageName' "$PACKAGE_JSON")
LANGUAGE_PACK_VERSION=$(jq -r '.version' "$PACKAGE_JSON")

# 动态生成 translations
TRANSLATIONS=$(jq -n --arg dir "$LANGUAGE_PACK_FOLDER" --argjson translations "$(jq '.contributes.localizations[0].translations' "$PACKAGE_JSON")" '
  reduce $translations[] as $item ({}; . + {($item.id): "\($dir)/\($item.path)"})
')

# 生成 languagepacks.json
HASH=$(echo -n "$LANGUAGE_PACK_UUID$LANGUAGE_PACK_VERSION" | md5sum | awk '{print $1}')
cat > "$LANGUAGEPACKS_FILE" <<EOL
{
    "${LANGUAGE_ID}": {
        "hash": "${HASH}",
        "extensions": [
            {
                "extensionIdentifier": {
                    "id": "${LANGUAGE_PACK_NAME}",
                    "uuid": "${LANGUAGE_PACK_UUID}"
                },
                "version": "${LANGUAGE_PACK_VERSION}"
            }
        ],
        "translations": ${TRANSLATIONS},
        "label": "${LANGUAGE_LABEL}"
    }
}
EOL

# 格式化 languagepacks.json
jq '.' "$LANGUAGEPACKS_FILE" > "$LANGUAGEPACKS_FILE.tmp" && mv "$LANGUAGEPACKS_FILE.tmp" "$LANGUAGEPACKS_FILE"
echo "languagepacks.json 已生成并格式化: $LANGUAGEPACKS_FILE"

# 生成 argv.json
cat > "$ARGV_FILE" <<EOL
{
    "locale": "${LANGUAGE_ID}"
}
EOL

# 格式化 argv.json
jq '.' "$ARGV_FILE" > "$ARGV_FILE.tmp" && mv "$ARGV_FILE.tmp" "$ARGV_FILE"
echo "argv.json 已生成并格式化: $ARGV_FILE"

调用

https://cnb.cool/Anyexyz/DevEnv/default-dev-env/-/blob/main/Dockerfile