GitHub Actions for content exchange

We provide a collection of ready-to-use GitHub actions that help you exchange translation files between Lokalise "Web and mobile" projects and GitHub repositories. It includes the following actions:

  • Push: Upload new or updated translation files (for the base language) from GitHub to Lokalise.
  • Pull: Download translation files from Lokalise to GitHub as a pull request.

These actions are lightweight and do not require installing the GitHub app for Lokalise.

Scenario overview: Push and pull with tags

This is the simplest and recommended approach for managing translations. It relies on using key tags in Lokalise to map translations to the corresponding branch in GitHub.

  • Using the hub branch: In GitHub, designate a specific branch to manage your translations. We'll refer to this branch as the "hub" branch.
  • Pushing translations to Lokalise: To send updated translations from GitHub to Lokalise, manually trigger the "Push to Lokalise" workflow from the hub branch. When you do this, any new or updated keys in the Lokalise project are tagged with the name of the hub branch that initiated the workflow.
  • Pulling translations from Lokalise: To bring translations from Lokalise back into GitHub, manually trigger the "Pull from Lokalise" workflow from the hub branch. This workflow filters the translation keys by the tag matching the hub branch’s name. Once filtered, a pull request with the updated translations is created for the hub branch. After you merge this pull request, your hub branch will be up-to-date with the latest translations.

This approach allows you to manage your translation process in a separate branch, giving you the flexibility to merge it into the main branch whenever needed.

Getting started with GitHub Actions for Lokalise

General setup overview

Every action from this collection requires some general setup. In this section, we'll summarize general configuration options. Later, we'll show where and how these values should be provided.

Lokalise API token

First, you'll need to generate a read/write Lokalise API token and pass it to the action. Do not paste your token directly into the workflow configurations. Use repository secrets instead:

  1. Open repository Settings.
  2. Go to Secrets and variables > Actions.
  3. Under Repository secrets, click New repository secret.
  4. Enter LOKALISE_API_TOKEN in the Name field.
  5. Paste your API token into the Secret field.
  6. That's it! Your token will be securely stored on GitHub and won't be visible during workflow runs. We'll use this token when configuring push and pull workflows.

Mandatory workflow parameters

You'll need to provide some mandatory parameters for the workflows. These can be set as environment variables, secrets, or passed directly to the workflow inside the YAML file.

The following parameters are required for every workflow (we’ll show where to specify these later):

  • api_token — Lokalise API token. Check the section above for additional instructions.
  • project_id — Your Lokalise project ID. If you haven’t created a project yet, set up a "Web and mobile" project on Lokalise and note its ID.
  • translations_path — One or more paths to your translations. For example, if your translations are stored in the locales folder at the project root, use locales (omit leading and trailing slashes).
  • file_format — Translation file format. For example, if you're using JSON files, just put json (no leading dot).
  • base_lang — The base language of your Lokalise project (e.g., en for English). Be mindful of regional codes! If your base language is French Canada (fr_CA), you must provide the exact value for base_lang. Also, ensure the nested folder under translations_path is named fr_CA.

🔐

Providing workflow parameters

It's crucial to provide the Lokalise API token via GitHub repository secrets. Other parameters (project_id, base_lang, etc.) can be set directly inside the YAML file or via repository variables/secrets.

If you choose to set other parameters via GitHub repository variables, make sure you name them properly. For example, if you name your repo variable as PROJECT_ID, it should be referenced like this: project_id: ${{ vars.PROJECT_ID }}.

Running the workflows

To run a workflow:

  1. Open your GitHub repository and go to Actions.
  2. Select a workflow from the left pane.
  3. Find the Run workflow dropdown on the right side.
  4. Choose a hub branch to trigger the workflow for.
  5. Click Run workflow.

Push and pull with key tags

Creating the hub branch and setting up Push action

Suppose your project uses the main branch, but you want to manage translations separately. To do this, you’ll create a new branch, which we'll call the "lokalise-hub" branch. But first, we'll need to create a new workflow in the main branch of the repository.

  1. Create the Push action:

Switch the the main branch of your repository and create a new file at .github/workflows/push.yml.

name: Push to Lokalise  
on:  
  workflow_dispatch:

jobs:  
  build:  
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Repo
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Push files to Lokalise
        uses: lokalise/[email protected]
        with:
          api_token: ${{ secrets.LOKALISE_API_TOKEN }}
          project_id: LOKALISE_PROJECT_ID
          file_format: FILE_FORMAT
          translations_path: |
            TRANSLATIONS_PATH1
            TRANSLATIONS_PATH2
          base_lang: BASE_LANG_ISO

Configuration params:

  • api_token: Secret variable containing your read/write API token. Check the section above for additional instructions.
  • project_id: Your Lokalise project ID.
  • file_format: Set this to the translation file format you’re using, such as json. Do not provide a leading dot.
  • translations_path: One or more directories in the project root containing your translation files without leading and trailing slashes (for example, locales).
    • The full path to the translations is built like this: TRANSLATIONS_PATH/LOCALE/**/**.FILE_FORMAT. Check the Translation files section to learn more about files organization.
  • base_lang: The project base language (for example, en). Be mindful of regional codes! If your Lokalise project has fr_CA set as the base language, make sure to provide exactly the same value. Also, ensure that inside your translations_path, there's a folder named after the base language.
    • For example, if your translations_path is set to locales and base_lang is en, the workflow expects to find translation files under the /locales/en/ folder. If you don't have this folder and/or files yet, we'll add those in step 3.
  1. Create and switch to the lokalise-hub branch:
git checkout -b lokalise-hub
  1. Set up the translation folder and files:
    In this branch, create a folder for your translations if you haven't already done so. It should be named according to the translations_path configured in step 1.
    1. For example, if your base language on Lokalise is English (en), create a folder called locales and inside it, an en directory. Place your translation files for the base language in this directory. For this demo, we’ll use the JSON format.
      Your folder structure should look like this:
locales/  
├── en/  
│   ├── main.json  
│   └── en.json
  1. Push the new branch to your GitHub repository:
git add .  
git commit -m "Added translation files for English (base)"  
git push origin lokalise-hub

Additional parameters for the Push action

The Push action also supports additional parameters that you can specify for further customization. Please note that these are optional.

  • additional_params — Extra parameters to pass to the Lokalise CLI when pushing files. For example, you can use --convert-placeholders to handle placeholders. You can include multiple CLI arguments as needed.
  • max_retries — Maximum number of retries on rate limit errors (HTTP 429). The default value is 3.
  • sleep_on_retry — Number of seconds to sleep before retrying on rate limit errors. The default value is 1.

Pushing translations to Lokalise

Now that everything is set up, you're ready to push translations from GitHub to Lokalise.

  1. Go to the Actions tab in your GitHub repository.
  2. Open the Push to Lokalise workflow. From the branch dropdown, select the lokalise-hub branch.
  1. Click Run workflow.
  2. The workflow will take a few moments to complete. Once finished, you’ll see the confirmation that the workflow has been successfully completed.

What if I already had translation files in my main branch?

If you've already got translation files in your main branch before switching to lokalise-hub, don’t worry. The Push action only looks for files that have been created or changed since your last commit. So, if your main branch already has these files and you move to a new branch, the Push action won’t consider those existing files as “new” because they’re already in your version control history.

If the Push action doesn’t find any changes in your translation files, it checks if this is the first time the action is running on the current branch. To achieve that, it looks for a tag labeled lokalise-upload-complete:

  1. If it finds that tag, it means the initial upload has already happened, and the action will stop.
  2. If it doesn’t find that tag, the action will upload all your translation files for the base language to Lokalise. After that, the action creates a lokalise-upload-complete tag to show that the initial setup is done. It’s recommended to pull this tag into your local repository by running git pull to make sure your local copy is up to date.

If you already have additional translation files for other (non-base languages), upload those to Lokalise manually. Make sure to assign the proper filenames on Lokalise when uploading these additional files. For example, if your keys created after the initial push were assigned to locales/%LANG_ISO%/main.json file, and you upload the main.json file for another non-base language, adjust its name to locales/%LANG_ISO%/main.json.

Editing translations on Lokalise

Once you're set up, you can head over to your Lokalise project and start managing translations. You'll notice that your translation keys are tagged with the lokalise-hub tag (or another tag named after the hub branch).

It's important to keep this tag intact to maintain the connection with your GitHub branch. If you need to add other tags, feel free to do so, but be careful not to remove the lokalise-hub tag. If it's accidentally removed, you can easily add it back using the Lokalise UI.

In Lokalise, you can add one or more target languages to your project and manage translations as usual.

Pulling translations from Lokalise

After editing your translations and creating new keys in Lokalise, it’s time to sync these changes back to your hub branch.

  1. Create the Pull action
    Start by switching to the main branch of your repository. Create a .github/workflows/pull.yml file and include the pull action configuration.
name: Pull from Lokalise

on:
  workflow_dispatch:

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout Repo
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Pull from Lokalise
        uses: lokalise/[email protected]
        with:
          api_token: ${{ secrets.LOKALISE_API_TOKEN }}
          project_id: LOKALISE_PROJECT_ID
          translations_path: |
            TRANSLATIONS_PATH1
            TRANSLATIONS_PATH2
          base_lang: BASE_LANG_ISO
          file_format: FILE_FORMAT

❗️

Filtering data based on translation status

By default, this action pulls all keys with the assigned tag, regardless of translation status. To control this, use the additional_params option with the --filter-data parameter. This parameter accepts the following values: translated, untranslated, reviewed, reviewed_only, last_reviewed_only, verified, and nonhidden. For example: additional_params: "--filter-data translated".

Configuration parameters:

  • api_token: Secret variable containing your read/write API token. Check the section above for additional instructions.
  • project_id: Your Lokalise project ID.
  • translations_path: One or more directories in the project root containing your translation files without leading and trailing slashes (for example, locales).
    • The full path to the translations is built like this: TRANSLATIONS_PATH/LOCALE/**/**.FILE_FORMAT. Check the Translation files section to learn more about files organization.
  • base_lang: The project base language (for example, en). Be mindful of regional codes! If your Lokalise project has fr_CA set as the base language, make sure to provide exactly the same value. Also, ensure that inside your translations_path, there's a folder named after the base language.
  • file_format: Set this to the translation file format you’re using, such as json. Do not provide a leading dot.
  1. Push your newly created action to the main branch on GitHub.
  2. Grant proper permissions to the actions. To achieve that:
    1. Go to your GitHub repository's Settings.
    2. Navigate to Actions > General.
    3. Under Workflow permissions, set the permissions to Read and write permissions.
    4. Enable Allow GitHub Actions to create and approve pull requests on the same page (under "Choose whether GitHub Actions can create pull requests or submit approving pull request reviews").
  3. Head back to your GitHub repository and navigate to the Actions tab.
  4. Select the Pull from Lokalise action.
  5. Make sure you choose the hub branch as the trigger for this workflow.
  1. Once the workflow completes, switch to the Pull requests tab. You should see a new pull request created.
  1. In the pull request, you'll notice it's created for the lokalise-hub branch, originating from a temporary branch. The name of this branch starts with the prefix lok, followed by the hub branch name.
  2. Review the changed files to see the updates. You may notice that your translations have been reordered and the indentation level updated. This behavior can be adjusted by setting additional parameters.
  1. When you're satisfied with the changes, go ahead and merge the pull request. After merging, you can safely delete the temporary branch.

This process can be repeated as often as needed. If no changes are detected in the translations (meaning the translations in Lokalise match those in the hub branch), a pull request won’t be created.

📘

Tracking changes to the base language

By default, the Pull action does not track changes to the base language files. To include these files, set the always_pull_base option to true when configuring the action.

Additional parameters for the Pull action

The Pull action also supports additional parameters that you can specify for further customization. Please note that these are optional.

  • additional_params — Extra parameters to pass to the Lokalise CLI when pulling files. For example, you can use --indentation 2sp to manage indentation. Multiple CLI arguments can be added, like: --indentation 2sp --placeholder-format icu.
  • temp_branch_prefix — A prefix for the temporary branch used to create the pull request. This value will be part of the branch name. For example, using lok will result in a branch name starting with lok. The default value is lok.
  • always_pull_base — By default, changes in the base language translation files (defined by the base_lang option) are ignored when checking for updates. Set this option to true to include changes in the base language translations in the pull request. The default value is false.
  • max_retries — Maximum number of retries on rate limit errors (HTTP 429). The default value is 3.
  • sleep_on_retry — Number of seconds to sleep before retrying on rate limit errors. The default value is 1.

Assumptions and defaults

Translation files

This workflow assumes that inside the translation folder (set with the translations_path option), there are nested folders named after your project locales. For example, if your base language is en, there should be a folder with that name. Here's a sample directory structure:

locales/
├── en/
│   ├── main.json
│   └── admin.json
└── fr/
    ├── main.json
    └── admin.json

When managing translation keys on Lokalise, make sure the filenames match your repository structure. If you store translations under locales/%LANG_ISO%/, the filenames assigned to the keys must follow this structure: locales/%LANG_ISO%/TRANSLATION_FILE_NAME.

Nested folders are also supported. For example: locales/en/nested_folder/main.json.

Tags

Every translation key uploaded to Lokalise via the Push action automatically gets a tag based on the branch that triggered the workflow. For instance, if the workflow is triggered by the lokalise-hub branch, all affected keys will have a lokalise-hub tag.

When using the Pull action to download translation keys to your GitHub repo, it will filter keys by the tag that matches the branch name. So, if you run the Pull action from the lokalise-hub branch, only keys with the matching tag will be downloaded; others will be ignored.

To ensure all relevant keys are included in the workflow, it's important to keep these tags. If a tag is removed by mistake, you can always add it back through the Lokalise UI.

Note on cron jobs

You can easily schedule your workflows using cron (POSIX syntax). To do that, add a new schedule event.

on:
  schedule:
    - cron: "0 0 * * *"

In this example, the workflow will run every day at midnight. If you need help creating the right schedule, check out this cron expression generator.

A few things to keep in mind:

  • Scheduled workflows always run on the latest commit from the default or base branch.
  • The minimum interval for running scheduled workflows is every 5 minutes.
  • You can use if conditions to skip specific times: if: github.event.schedule != '30 5 * * 1,3'.
  • Watch out for GitHub Actions quotas. On the Free plan, you get 2000 minutes per month.