Tutorials

GitHub Sync for Translations: Automate Your i18n Workflow

Ali Osman Delismen
Ali Osman Delismen
·8 min read
Share
GitHub Sync for Translations: Automate Your i18n Workflow

The manual translation workflow is a silent tax on engineering velocity. Every time a developer adds a new string, someone has to:

  1. Notice the new key exists
  2. Export the translation file
  3. Send it to translators (or a TMS)
  4. Wait for translations
  5. Import the translated files
  6. Commit the changes
  7. Deploy

If your release cycle is weekly, this is manageable. If you ship multiple times per day, it breaks down fast. Strings go untranslated. Features launch in English-only. "We'll fix translations in the next release" becomes the default, and you end up with a localization debt that's expensive to pay back.

GitHub sync eliminates this tax.

What GitHub Sync Actually Does

When you connect Better i18n to your GitHub repository, the sync runs in both directions:

Code → TMS (on push):

  • When you push a commit that adds or modifies translation source files, Better i18n detects the changes
  • New keys are added to the TMS automatically
  • Modified source strings are flagged for re-translation in all target languages
  • Deleted keys are archived (never deleted immediately, to avoid losing translations)

TMS → Code (after translation):

  • When translations are approved in the TMS, Better i18n automatically opens a pull request with the updated translation files
  • The PR description lists exactly what changed and which languages
  • You merge it like any other PR

This creates a closed loop: engineers ship code, translations flow in automatically, completed translations flow back out as PRs.

Setting Up GitHub Sync with Better i18n

Step 1: Connect your repository

In the Better i18n dashboard, go to your project → Settings → GitHub Sync. Click "Connect Repository" and authenticate with GitHub. Select the repo and branch to sync from (usually main or develop).

Step 2: Configure file patterns

Tell Better i18n where your translation files live:

source:
  branch: main
  path: src/locales/en.json
  format: json

targets:
  - path: src/locales/{locale}.json
    languages: [de, fr, es, ja, zh, pt-BR]

Better i18n supports JSON, YAML, PO/POT, XLIFF, Android XML, iOS strings, Flutter ARB, and more. For nested files, use glob patterns:

source:
  path: src/locales/en/**/*.json
targets:
  - path: src/locales/{locale}/**/{filename}

Step 3: Configure the translation workflow

Choose what happens when new keys are detected:

Option A: AI translation + auto-PR — New keys are automatically translated by AI and a PR is opened immediately. Best for teams that trust AI quality for their content and want maximum speed.

Option B: AI translation + review required — New keys are AI-translated but require human review before the PR is opened. Best for marketing copy, legal text, or languages where quality is critical.

Option C: Human translation only — New keys are added to the translation queue for human translators. Best for highly regulated content or Tier 1 languages.

You can set different workflows for different key prefixes — AI for ui.* and errors.*, human review for legal.* and emails.*.

Step 4: Handle the .gitignore question

Keep translated files in the repo (recommended for most teams): Translated files are committed alongside your source, so your build has everything it needs without a runtime dependency. PRs from Better i18n update these files.

CDN-only delivery: If you're using Better i18n's CDN delivery, you don't need translated files in your repo at all — your SDK fetches them at runtime. You can .gitignore all locale files except the source language. This eliminates translation PR noise entirely.

The Pull Request Workflow

When Better i18n opens a translation PR, it looks like this:

feat(i18n): add translations for de, fr, es [Better i18n]

Translated 14 new keys added in commits a1b2c3d..f4e5d6c

Languages:
✅ German (de) — 14/14 keys
✅ French (fr) — 14/14 keys
✅ Spanish (es) — 14/14 keys
⏳ Japanese (ja) — 8/14 keys (6 pending review)

Automated by Better i18n GitHub Sync

The PR can be configured to target a specific branch, require CI to pass before merge, auto-merge when all languages are complete, or notify specific reviewers for specific languages.

Handling Edge Cases

Source string changed? Better i18n marks all translations for that key as "outdated" and flags them for re-translation.

Key deleted? Archived, not deleted. Bulk-delete archived keys from the dashboard when you're sure.

Merged before translations are ready? Better i18n tracks which commit introduced each key and opens the translation PR as soon as they're done.

Monorepos? Multiple projects per repository are supported, each with their own language set and workflow.

CI/CD Integration

# Check translation coverage before deployment
better-i18n check --project my-project --require-languages de,fr,es --min-coverage 95
# .github/workflows/i18n-check.yml
name: Translation Coverage Check

on:
  pull_request:
    paths:
      - 'src/locales/en.json'

jobs:
  i18n-check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npx @better-i18n/cli check --require-languages de,fr,es
        env:
          BETTER_I18N_API_KEY: ${{ secrets.BETTER_I18N_API_KEY }}

This blocks merges that would ship new English strings without translations in your critical languages.

Before and After

Before GitHub SyncAfter GitHub Sync
New string addedDeveloper adds key, manually notifies TMS teamSync detects change, creates translation task automatically
Translation completeTranslator emails developerPR opened automatically
DeploymentManual import of translated filesMerge the PR, done
Coverage visibilityAd-hoc, often discovered at launchReal-time dashboard + CI checks
Time from code to translatedDays to weeksHours to days
Engineering time spent on i18n coordination2-4 hours/week< 30 minutes/week

Getting Started

  1. Create a Better i18n account (free tier includes GitHub sync)
  2. Connect your repository in the dashboard
  3. Configure your file patterns and language list
  4. Push a commit with a new translation key — watch the magic happen

The first sync imports all your existing translation files and calculates coverage. From there, every commit is handled automatically.

Set up GitHub Sync →