How to integrate Crowdin with Flutter for translation

March 19, 2023

We have recently begun an exercice to make our privacy-friendly apps, ente Photos & ente Authenticator, translation ready. Our community members have shown interest in helping us translate the apps into various languages. Naturally, we started looking for various solutions that will allow anyone to easily contribute to the translation. In the end, we decided to use Crodwin for managing the translations after enrolling in their generous open-source program.

This guide assumes that you have already extracted the strings from your Flutter app and created a Crowdin account and project for your app.

After the integration, the GitHub Action will:

  • Automatically upload new source strings to the Crowdin website.
  • Create a pull request to add translated strings.
Here are the steps to get started:
  1. Create a Crowdin personal access token and project ID, which you can obtain from the Crowdin website. To do this, visit, create a token, and copy the numeric project ID. Github action

  2. In your Github repo, add CROWDIN_PERSONAL_TOKEN and CROWDIN_PROJECT_ID as Repository secrets (Repo Settings -> Secrets and Variables -> Actions).

  3. Modify Workflow Permissions to allow the Github Action to automatically create Pull Requests (Settings -> Actions -> General). Github action

  4. Add crowdin.yml file in your root directory with the config:

project_id_env: CROWDIN_PROJECT_ID

  - source: /lib/l10n/arb/app_en.arb
    translation: /lib/l10n/arb/app_%two_letters_code%.arb
  1. Add a Github Action workflow file (.github/workflows/l18n-crowdin.yml) with the following code:
name: Sync crowdin translation

    paths: # run action automatically when app_en.arb file is changed
      - 'lib/l10n/arb/app_en.arb'
    branches: [ main ]
    - cron: '0 */12 * * *' # Every 12 hours -*/12_*_*_*
  workflow_dispatch: # for manually running the action

    runs-on: ubuntu-latest

      - name: Checkout
        uses: actions/checkout@v3

      - name: crowdin action
        uses: crowdin/github-action@v1
          upload_sources: true
          upload_translations: true
          download_translations: true
          localization_branch_name: l10n_translations
          create_pull_request: true
          skip_untranslated_strings: true
          pull_request_title: 'New Translations'
          pull_request_body: 'New translations via Crowdin GH Action.'
          pull_request_base_branch_name: 'main'
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Here's an example PR for step 4 & 5.

Based on your need, you can add addtional triggers to automatically run the actions.

To verify the integration, you can manually execute the action. If everything is configured correctly, you should see a PR similar to this.

That's it, we are done!

Hope you found this guide helpful in integrating translations into your apps. If you'd like to know more of our adventures with Flutter, follow us on Twitter, or come hang out on our lovely Discord!