前言
啊好多人问我怎么还不更新,其实本月是已经写了一篇测评的,但是鉴于过于超前会给产品带来不好的影响,所以就没有公开。那么既然这样本月就再更新一篇。
首先 声明 一点,安装中文包的初衷不是看不懂英文,也不是对某些语言有偏见,既然它存在必然有其存在的理由,所以本文仅从技术的角度分析如何安装。
由于 Code-server 是基于 Vscode 的二开版本,本文将以 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}')
那就来个脚本
#!/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"