本文目录导读:

Git 钩子脚本可以通过检查代码中的硬编码字符串、缺少国际化(i18n)方法调用、或者不符合规范的翻译键来确保国际化支持,以下是几种常见的实现方案:
pre-commit 钩子检查
场景:在提交前检查新增的代码是否使用了国际化方法,而不是硬编码字符串。
示例脚本:.git/hooks/pre-commit
#!/bin/bash
# 防止硬编码字符串(针对 JavaScript/TypeScript 项目)
echo "检查国际化支持..."
# 获取暂存区中新增或修改的文件
changed_files=$(git diff --cached --name-only --diff-filter=ACM)
# 定义需要检查的文件类型
file_types=("*.js" "*.jsx" "*.ts" "*.tsx" "*.vue" "*.svelte")
has_error=0
for file in $changed_files; do
# 检查文件类型
for pattern in "${file_types[@]}"; do
if [[ "$file" == $pattern ]]; then
# 检查是否有硬编码的中文字符串(适用于中文项目)
if grep -nP '[\x{4e00}-\x{9fa5}]' "$file" | grep -v '//.*\|/\*.*\*/' ; then
echo "⚠️ 发现硬编码中文: $file"
echo " 请使用 $t('xxx') 或 i18n.t('xxx') 替换"
has_error=1
fi
# 检查是否缺少国际化调用(字符串字面量检测)
if grep -nE '(["\''])\1' "$file" | grep -v 'i18n\|t(' ; then
echo "⚠️ 发现未包装的字符串: $file"
has_error=1
fi
break
fi
done
done
if [ $has_error -ne 0 ]; then
echo "提交失败:请先修复国际化问题"
exit 1
fi
exit 0
commit-msg 钩子检查
场景:检查提交信息中是否包含了国际化相关的变更描述。
#!/bin/bash
# .git/hooks/commit-msg
commit_msg_file=$1
commit_msg=$(cat "$commit_msg_file")
# 要求国际化相关的提交必须包含 [i18n] 标记
if echo "$commit_msg" | grep -qiE '新增|添加|文案|文本|message|string'; then
if ! echo "$commit_msg" | grep -qi '\[i18n\]'; then
echo "⚠️ 提交信息包含文本内容变更,请添加 [i18n] 标记"
echo "示例: feat: 新增登录页文案 [i18n]"
exit 1
fi
fi
exit 0
更严格的国际化检查脚本
使用 ESLint 或自定义规则:
#!/bin/bash
# .git/hooks/pre-commit
# 使用 ESLint 的 i18n 插件检查
if command -v npx &> /dev/null; then
echo "运行 ESLint 国际化检查..."
npx eslint --rule '{
"no-restricted-syntax": ["error",
{
"selector": "Literal[value=/[\x{4e00}-\x{9fa5}]/]",
"message": "请使用国际化函数处理中文文本"
}
]
}' $(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(js|jsx|ts|tsx|vue)$')
fi
自定义检查工具示例
创建专门的检查脚本 scripts/check-i18n.sh:
#!/bin/bash
# 国际化检查工具
ERRORS=()
# 检查硬编码文本(支持多种语言)
check_hardcoded_text() {
local file=$1
# 匹配常见语言的 Unicode 范围
local language_patterns=(
'[\x{4e00}-\x{9fff}]' # 中文
'[\x{3040}-\x{309f}]' # 日文平假名
'[\x{ac00}-\x{d7af}]' # 韩文
'[\x{0400}-\x{04ff}]' # 俄文
)
for pattern in "${language_patterns[@]}"; do
if grep -Pn "$pattern" "$file" | grep -vE '^\s*($|//|\*|<!--)' > /dev/null 2>&1; then
ERRORS+=("发现非英文字符: $file")
return 1
fi
done
}
# 检查翻译键命名规范
check_translation_keys() {
local file=$1
# 检查是否符合键命名规范(如 module.key 格式)
if grep -Pn "\$t\('([a-z]+\.[a-z]+\.[a-z0-9_]+)'\)" "$file" | grep -vP '^\s*//' > /dev/null 2>&1; then
return 0
fi
# 检查是否有使用变量作为翻译键(需要特别处理)
if grep -Pn "\$t\([^'\"\)]" "$file" | grep -vE '^\s*(//|/\*)'> /dev/null 2>&1; then
ERRORS+=("发现动态翻译键: $file")
return 1
fi
}
# 主检查逻辑
main() {
local files=$(git diff --cached --name-only --diff-filter=ACM)
for file in $files; do
case "$file" in
*.js|*.jsx|*.ts|*.tsx|*.vue|*.html|*.svelte)
check_hardcoded_text "$file"
check_translation_keys "$file"
;;
*.json|*.yaml|*.yml)
# 检查国际化资源文件格式
check_i18n_resource_file "$file"
;;
esac
done
if [ ${#ERRORS[@]} -gt 0 ]; then
echo "⚠️ 国际化检查发现以下问题:"
printf '%s\n' "${ERRORS[@]}"
exit 1
fi
echo "✅ 国际化检查通过"
exit 0
}
main
配合 Lint-staged 使用
在 package.json 中配置:
{
"lint-staged": {
"*.{js,jsx,ts,tsx,vue}": [
"eslint --rule 'no-restricted-syntax: [\"error\", { \"selector\": \"Literal[value=/[\\x{4e00}-\\x{9fa5}]/]\", \"message\": \"请使用国际化函数\" }]'",
"bash scripts/check-i18n.sh"
]
}
}
使用建议
-
选择合适的检查粒度:
- 首次引入:先做基础检查(硬编码字符串检测)
- 成熟阶段:增加翻译键规范检查
-
考虑性能:
- 只检查暂存区的变更文件
- 避免在钩子中执行耗时的全量扫描
-
提供清晰的错误信息:
- 指出具体文件和行号
- 给出正确的国际化调用示例
-
允许临时绕过:
# 使用环境变量跳过检查 SKIP_I18N_CHECK=1 git commit -m "紧急修复"
-
集成到 CI/CD:
# .github/workflows/i18n-check.yml - name: 国际化检查 run: | bash scripts/check-i18n.sh --ci
这些钩子脚本可以根据项目的具体需求进行调整,关键是找到检查严格性和开发效率之间的平衡点。