Skip to main content

Đồng bộ tệp bản dịch: Giữ khóa i18n đồng bộ giữa các ngôn ngữ

Mỗi khi lập trình viên thêm một khóa vào ngôn ngữ nguồn, 15 tệp ngôn ngữ khác lại mất đồng bộ. Khóa thiếu khiến người dùng thấy đường dẫn thô. Khóa lỗi thời làm lãng phí thời gian của biên dịch viên và tăng kích thước gói. Quy trình đồng bộ tự động giúp mọi tệp luôn nhất quán.

1

Vấn đề đồng bộ

Các tệp bản dịch liên tục mất đồng bộ. Một lập trình viên thêm 'settings.notifications.title' vào en.json nhưng quên thêm khóa này vào 15 tệp ngôn ngữ còn lại. Một lập trình viên khác xóa 'onboarding.welcome' khỏi mã nhưng vẫn để khóa này trong mọi tệp ngôn ngữ. Lập trình viên thứ ba đổi tên 'user.name' thành 'user.displayName' trong tiếng Anh nhưng không đổi ở các ngôn ngữ khác. Sau nhiều tháng, các tệp ngôn ngữ ngày càng khác nhau: khóa bị thiếu, lỗi thời hoặc không khớp giữa các ngôn ngữ.

The drift problem
// The problem: translation files drift out of sync

// Developer adds a new feature with new keys:
// en.json (source of truth)
{
  "nav.home": "Home",
  "nav.about": "About",
  "nav.pricing": "Pricing",     // NEW
  "nav.changelog": "Changelog"  // NEW
}

// de.json (out of sync - missing new keys)
{
  "nav.home": "Startseite",
  "nav.about": "Über uns"
  // nav.pricing - MISSING
  // nav.changelog - MISSING
}

// de.json also has stale keys from deleted features:
{
  "nav.home": "Startseite",
  "nav.about": "Über uns",
  "nav.legacy_page": "Alte Seite"  // STALE - removed from en.json
}
Khóa thiếu còn nghiêm trọng hơn bản dịch thiếu. Khi thiếu bản dịch, hệ thống có thể dùng ngôn ngữ nguồn làm phương án dự phòng. Khi thiếu khóa, hệ thống có thể phát sinh lỗi thời gian chạy, hiển thị đường dẫn khóa thô cho người dùng hoặc kết xuất chuỗi trống. Bạn phải thực thi quy trình đồng bộ thay vì chỉ trông chờ mọi người tuân thủ.
2

Phát hiện khóa thiếu

Khóa thiếu là khóa có trong ngôn ngữ nguồn nhưng không có trong ngôn ngữ đích. Đây là vấn đề đồng bộ phổ biến nhất và gây ảnh hưởng nghiêm trọng nhất — người dùng thấy đường dẫn khóa thô như 'settings.notifications.title' thay vì văn bản đã dịch. i18n-validate phát hiện khóa thiếu bằng cách đối chiếu cấu trúc khóa của từng ngôn ngữ với ngôn ngữ nguồn.

Terminal
# Detect missing and stale keys
npx i18n-validate sync \
  --source locales/en.json \
  --targets 'locales/*.json'

# Output:
# locales/de.json:
#   Missing keys (2):
#     - nav.pricing
#     - nav.changelog
#   Stale keys (1):
#     - nav.legacy_page
#   Coverage: 66.7% (2/3 keys)
#
# locales/ja.json:
#   Missing keys (5):
#     - nav.pricing
#     - nav.changelog
#     - settings.theme
#     - settings.language
#     - settings.notifications
#   Coverage: 50.0% (5/10 keys)
Chạy i18n-validate với cờ --check missing-keys để chỉ tập trung vào vấn đề đồng bộ. Dùng --severity error để khóa thiếu khiến CI thất bại, qua đó bảo đảm bạn sửa chúng trước khi hợp nhất.
3

Phát hiện khóa lỗi thời

Khóa lỗi thời là khóa có trong tệp bản dịch nhưng mã không còn tham chiếu đến. Khóa lỗi thời làm lãng phí thời gian của biên dịch viên (họ phải dịch các chuỗi không ai thấy), tăng kích thước gói và gây khó hiểu khi bảo trì. Để phát hiện khóa lỗi thời, bạn cần đối chiếu tệp ngôn ngữ với các tham chiếu trong mã.

Terminal
# Step 1: Check which files are out of sync
npx i18n-validate sync --source locales/en.json --targets 'locales/*.json'

# Step 2: Auto-fill missing keys with source values (as placeholders)
npx i18n-validate sync \
  --source locales/en.json \
  --targets 'locales/*.json' \
  --fill-missing \
  --fill-value "[NEEDS TRANSLATION] {{source}}"

# Step 3: Remove stale keys no longer in source
npx i18n-validate sync \
  --source locales/en.json \
  --targets 'locales/*.json' \
  --remove-stale

# Step 4: Sort keys to match source order (cleaner diffs)
npx i18n-validate sync \
  --source locales/en.json \
  --targets 'locales/*.json' \
  --sort-keys

# All at once:
npx i18n-validate sync \
  --source locales/en.json \
  --targets 'locales/*.json' \
  --fill-missing \
  --remove-stale \
  --sort-keys
4

Tự động hóa quy trình đồng bộ

Chiến lược đồng bộ hiệu quả nhất kết hợp ba lớp: 1) Hook pre-commit xác thực trạng thái đồng bộ ở mỗi commit. 2) Bước kiểm tra trong quy trình CI chặn các lần hợp nhất có vấn đề đồng bộ. 3) Đợt kiểm tra toàn diện định kỳ phát hiện sai lệch tích tụ từ bản sửa lỗi khẩn cấp và thay đổi thủ công.

.husky/pre-commit
# .husky/pre-commit
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

# Check if source locale file changed
SOURCE_CHANGED=$(git diff --cached --name-only | grep -c 'locales/en.json')

if [ "$SOURCE_CHANGED" -gt 0 ]; then
  echo "Source locale changed - checking sync..."

  npx i18n-validate sync \
    --source locales/en.json \
    --targets 'locales/*.json' \
    --fail-on-missing \
    --min-coverage 90

  if [ $? -ne 0 ]; then
    echo ""
    echo "Translation files are out of sync!"
    echo "Run: npx i18n-validate sync --fill-missing"
    exit 1
  fi
fi
.github/workflows/i18n-sync.yml
# .github/workflows/i18n-sync.yml
name: Translation Sync Check

on:
  pull_request:
    paths:
      - 'locales/**'

jobs:
  sync-check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Check translation sync
        run: npx i18n-validate sync \
          --source locales/en.json \
          --targets 'locales/*.json' \
          --fail-on-missing \
          --min-coverage 95

      - name: Comment on PR if out of sync
        if: failure()
        uses: actions/github-script@v7
        with:
          script: |
            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: 'Translation files are out of sync. Please run npx i18n-validate sync --fill-missing and commit.'
            })
5

Báo cáo mức độ bao phủ bản dịch

Mức độ bao phủ bản dịch là tỷ lệ phần trăm khóa nguồn đã có bản dịch trong từng ngôn ngữ đích. i18n-validate tạo báo cáo bao phủ với tỷ lệ phần trăm theo từng ngôn ngữ và làm nổi bật những ngôn ngữ đang tụt lại. Hãy đặt ngưỡng bao phủ trong CI để chặn hợp nhất khi tỷ lệ giảm xuống dưới mức chấp nhận được.

Namespace-based sync
// Split large translation files by feature/namespace
// locales/
// ├── en/
// │   ├── common.json      (nav, footer, errors)
// │   ├── auth.json         (login, register, reset)
// │   ├── dashboard.json    (dashboard-specific)
// │   └── settings.json     (settings page)
// ├── de/
// │   ├── common.json
// │   ├── auth.json
// │   ├── dashboard.json
// │   └── settings.json

// Sync with namespace support:
npx i18n-validate sync \
  --source 'locales/en/*.json' \
  --targets 'locales/*/%.json' \
  --namespace-pattern '{locale}/{namespace}.json'

// Benefits:
// - Smaller files, easier to review
// - Feature teams own their translations
// - Lazy-load only needed namespaces
// - Parallel translation workflows
Đặt ngưỡng bao phủ khác nhau cho từng ngôn ngữ. Các ngôn ngữ chính (de, fr, ja) có thể yêu cầu mức bao phủ 100%, còn các ngôn ngữ mới thêm (th, vi) có thể bắt đầu ở mức 80% rồi tăng dần theo thời gian.

Dùng thử i18n Agent ngay

Thả tệp bản dịch của bạn vào đây

JSON, YAML, PO, XML, CSV, Markdown, Properties

hoặc nhấp để duyệt

Ngôn ngữ đích

Không cần đăng kýBáo giá tức thì

Câu hỏi thường gặp về đồng bộ tệp bản dịch