Home | Resources | Blog

How to sync GitHub with Phrase Strings for continuous localization

Connecting GitHub to Phrase Strings lets developers and localization teams stop passing locale files back and forth by hand. New source strings get picked up automatically, translations come back as a pull request, and nobody has to interrupt a sprint to ask “is the German file ready yet.”

There are two ways to do this today, and which one fits depends on how your team ships software:

  • Repo Sync — a UI-driven connection between a Phrase project and a GitHub repository. Best if you want a visual setup, project-level control, and translations delivered as pull requests without touching your CI config.
  • The Phrase Strings GitHub Action — installs the Phrase CLI directly into your GitHub Actions workflow. Best if localization needs to be a first-class step in your existing CI/CD pipeline, not a parallel process.

Most teams end up using one as their primary sync and can add the other later. This guide covers both, plus a continuous localization workflow you can adapt to your branching model.

Before you start: create your .phrase.yml

Both methods rely on the same configuration file. .phrase.yml tells Phrase where your locale files live in your repository and how they map to the locales in your Phrase project. It sits in your project’s root folder.

You don’t need to write this by hand. Run phrase init from the Phrase CLI, and it’ll prompt you for a Phrase API access token (create one in your Phrase account settings) and generate a working config.

A basic config looks like this:

phrase:

  project_id: your_project_id

  push:

    sources:

      – file: ./config/locales/en.yml

        params:

          locale_id: en

          file_format: yml

  pull:

    targets:

      – file: ./config/locales/<locale_code>.yml

        params:

          file_format: yml

If only your developers should be creating new source strings, restrict the push source to your default locale, as shown above. For pulling, include every locale you support, including the default, since content editors sometimes fix typos directly in that file too.

Commit .phrase.yml to your repository. If you generated an access token to run phrase init locally, remove it from the file before committing: the GitHub Action authenticates via a repository secret instead, and Repo Sync doesn’t need it in the file at all.

Option 1: Set up Repo Sync

Repo Sync is the fastest way to connect a Phrase project to GitHub without editing your CI pipeline.

First, make sure your repository meets the prerequisites: read and write access for Phrase, a valid .phrase.yml at the root of the branch you want to monitor, and, if the target repository requires signed commits, GitHub App authentication rather than a personal access token (commits pushed via a personal access token aren’t signed, so the sync will fail on repositories that require verification).

To connect a repository:

  1. In Phrase, go to Automations → Repo Syncs (or open Integrations, scroll to Repo Sync, and click Configure).
  2. Click Add Sync/GitHub.
  3. Select the Phrase project you want to connect.
  4. Choose your authentication method: GitHub App (recommended), personal access token, or self-hosted instance. For the GitHub App, click Authenticate if it isn’t installed yet, or Manage installation if it already is; this is a one-time step and the same authentication can be reused across multiple repository syncs.
  5. Select the GitHub repository and the branch to sync (usually your main branch).
  6. Optionally, name the branch Phrase will use for pull requests. Leave it blank and Phrase defaults to phrase-translations.
  7. Click Validate Configuration to confirm your authentication and .phrase.yml are set up correctly.
  8. Optionally, set an Import behavior to control when new or updated files are automatically pulled into the project.
  9. Click Save.

Your project is now connected and listed on the Repo Syncs page. From there, use Import to pull new source strings into Phrase, and Export to open a pull request with the latest translations, once translators have completed their work. A History view on the same page tracks past imports and exports per project.

If a sync fails, the CLI is the fastest way to debug: run it locally against your .phrase.yml to surface the actual error before contacting support.

Option 2: Set up the Phrase Strings GitHub Action

If localization should live inside your CI/CD pipeline rather than beside it, use the Phrase Strings GitHub Action (https://developers.phrase.com/en/developer-tools/strings-github-action). It installs the Phrase CLI as a workflow step, so pushing and pulling translations becomes part of the same pipeline that builds and deploys your app.

steps:

  – uses: actions/checkout@v4

  – uses: phrase/setup-cli@v1

    with:

      version: 2.19.0

  – run: phrase pull

  – run: phrase push –wait

    env:

      PHRASE_ACCESS_TOKEN: ${{ secrets.PHRASE_ACCESS_TOKEN }}

Store your Phrase API access token as a GitHub Actions secret named PHRASE_ACCESS_TOKEN rather than committing it anywhere. The action reads your repository’s .phrase.yml for its push and pull configuration, so once that file is in place, this is close to the entire setup.

This approach suits teams who want zero manual steps after initial setup: new strings get pushed to Phrase automatically on every relevant build, and translated content pulls back in without anyone clicking a button.

A continuous localization workflow

However you connect GitHub, the workflow logic is similar. Here’s a common pattern for teams using feature branches and pull requests into a main branch:

  1. A developer adds new source strings while building a feature, using only the default locale.
  2. On merge to main (or on your chosen trigger), new keys reach Phrase, either automatically via Repo Sync’s Import behavior setting or through the GitHub Action’s phrase push.
  3. Translators see the new strings appear in Phrase and work through them, with full context if you’ve set up in-context preview.
  4. Completed translations come back to your repository, either as a pull request from Repo Sync’s Export, or via phrase pull in your pipeline.
  5. A developer reviews and merges the translation pull request, and the localized feature ships.

Keeping main deployable. There’s usually a gap between a feature merging and its translations coming back. If your main branch needs to be deployable at all times, a common fix is to merge feature branches into a shared development or staging branch first, then merge to main only once translations for that batch are in. Configure whichever branch you use for this in your Repo Sync or Action settings, not necessarily main itself.

Which one should you use?

If you’re not sure where to start: Repo Sync gets you running with a visual setup and no pipeline changes, which is often the quicker first step. If your team already treats infrastructure as code and wants localization to fail loudly in CI if something’s misconfigured, start with the GitHub Action instead. Many teams eventually run both, using the Action for automated pushes on every build and Repo Sync’s pull request flow for reviewing incoming translations.

FAQs

Can I use Repo Sync and the GitHub Action together?

Yes, and many teams do. A common pattern is using the GitHub Action to push new source strings to Phrase automatically on every build, then using Repo Sync’s pull request flow to review and merge translations as they come back. Both rely on the same `.phrase.yml` configuration, so there’s no conflict between running them side by side.

What happens if my repository requires signed commits?

Use GitHub App authentication rather than a personal access token. Commits pushed via a personal access token aren’t signed, so the sync will fail with the error “The repository requires verified (signed) commits.” The GitHub App method produces signed commits and works with this requirement.

How do I keep my main branch deployable while translations are in progress?

There’s usually a lag between a feature’s pull request merging and its translations coming back from Phrase. If your main branch needs to be deployable at all times, merge feature branches into a shared development or staging branch first, and only merge to main once translations for that batch are complete.

Do I need to set up a webhook for auto-import?

No. When you connect a repository through Repo Sync, you can set an Import behavior option to control when new or updated files are automatically pulled into your Phrase project. This replaces the manual webhook setup that earlier versions of this integration required.

Keep exploring

Blog post

Why accessibility matters in translation tools: Improving our CAT editor

Accessibility is shaping the future of translation tools. Learn how WCAG-aligned improvements in the Phrase CAT editor are helping linguists work faster, with greater clarity and fewer barriers.

Blog post

From constitution to campus: What keeps a language alive?

Ireland’s Irish language revival spans law, education, and modern translation technology. Dr Jamie Murphy of University College Dublin explores how constitutional status, university programs, and language technology are shaping the future of Irish in national and European institutions

Blog post

The rise of the global intelligence function: Inside Loc360° 2025

Localization is shifting from delivery to global intelligence. Loc360° and UnLOCked 2025 brought together leaders from AWS, Microsoft, Uber, Booking.com, Nike, and more to explore AI governance, business impact, and the rise of data-literate localization leadership.

Blog post

Brian Klaas: Embracing chaos: why leaders must rethink control, resilience, and trust

Jason Hemingway speaks with political scientist and author Dr. Brian Klaas and Phrase CEO Georg Ell about how chaos, randomness, and influence shape our lives and our work.

Pile of yellow "Face with Tears of Joy" emojis symbolizing emotional expression and misinterpretation in digital conversations

Blog post

The Emoji is the new Lingua Franca… but are we all speaking the same way?

Are Emojis a Universal Language? Not Quite. Emoji use is global—but not universally understood. From cultural misfires to platform-specific designs, even the simplest symbols can confuse. Discover how brands can avoid common emoji pitfalls and communicate more clearly across borders.