本文目录导读:

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
这些钩子脚本可以根据项目的具体需求进行调整,关键是找到检查严格性和开发效率之间的平衡点。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播