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. These actions include:
- 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 translation files. 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." This branch serves as the central point for translation updates and synchronization between Lokalise and GitHub.
- Pushing translation files to Lokalise: To send updated translation files 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 Lokalise are tagged with the name of the hub branch that initiated the workflow.
- For advanced technical details and the default CLI parameters used by this action, read the technical details in the push action README.
- Pulling translation files from Lokalise: To bring translation files 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 translation files is created for the hub branch. After merging this pull request, your hub branch will be up-to-date with the latest translation files.
- For advanced technical details and the default CLI parameters used by this action, read the technical details in the pull action README.
This approach allows you to manage your translation process in a dedicated branch, giving you the flexibility to merge updates into your 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
To start, generate a read/write Lokalise API token and securely pass it to the action. Do not paste your token directly into the workflow configurations. Instead, store it as a repository secret:
- Open your repository's Settings.
- Navigate to Secrets and variables > Actions.
- Under Repository secrets, click New repository secret.
- Enter
LOKALISE_API_TOKEN
in the Name field. - Paste your API token into the Secret field.
- That's it! Your token is securely stored in GitHub and won't be exposed during workflow runs. We'll reference this token when configuring the push and pull workflows.
Mandatory workflow parameters
Every workflow requires the following parameters. These can be set as environment variables, repository secrets, or passed directly in the workflow YAML file.
api_token
— Lokalise API token. See the section above for setup instructions.project_id
— Your Lokalise project ID. If you don’t have a project yet, create a "Web and mobile" project on Lokalise and note its ID.translations_path
— One or more paths to your translation files. For example, if your translations are stored in thelocales
folder at the project root, uselocales
(omit leading and trailing slashes).file_format
— The format of your translation files. For example, usejson
for JSON files (no leading dot).base_lang
— The base language of your Lokalise project (e.g.,en
for English). Be mindful of regional codes! For example:- If your base language is French Canada (
fr_CA
), provide the exact value (fr_CA
) forbase_lang
. - Ensure the folder structure under
translations_path
matches the regional code (e.g.,locales/fr_CA
).
- If your base language is French Canada (
Providing workflow parameters
- Always provide the Lokalise API token as a GitHub repository secret for security.
- Other parameters (e.g.,
project_id
,base_lang
) can be set:
- Directly in the YAML file, e.g.,
base_lang: en
.- Via repository variables or secrets, e.g.,
project_id: ${{ vars.PROJECT_ID }}
.- If using repository variables, ensure they are named clearly and referenced correctly.
Running the workflows
To run a workflow:
- Open your GitHub repository and go to Actions.
- Select a workflow from the left pane.
- Find the Run workflow dropdown on the right side.
- Choose a hub branch to trigger the workflow for.
- 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 in a dedicated branch. To achieve this, you’ll create a new branch, which we’ll refer to as the "lokalise-hub" branch. However, before that, you’ll need to set up a workflow in the main branch of your repository.
- Create the Push action:
Switch to 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
The following parameters are used in this example (note that we’re not covering all supported parameters here):
api_token
: A secret variable containing your read/write Lokalise API token. Refer to the Lokalise API token section for setup instructions.project_id
: Your Lokalise project ID.file_format
: Specifies the format of your translation files, such asjson
. Do not include a leading dot.translations_path
: One or more directories in the project root containing your translation files without leading or trailing slashes (e.g.,locales
).- The full path to the translation files is built as
TRANSLATIONS_PATH/LOCALE/**/**.FILE_FORMAT
. Refer to the Translation files section for more details on file organization. - If your files are not nested under additional folders but instead stored directly in the
translations_path
(e.g.,locales/en.json
ori18n/fr.json
), set theflat_naming
parameter totrue
.
- The full path to the translation files is built as
base_lang
: The base language of your Lokalise project (e.g.,en
). Be mindful of regional codes! For example, if your base language isfr_CA
, provide exactly that value.- Ensure that the
translations_path
includes a folder named after the base language. For instance, if yourtranslations_path
is set tolocales
andbase_lang
isen
, the workflow expects to find translation files under the/locales/en/
folder. If this folder or the necessary files don’t exist yet, you’ll add them in step 3.
- Ensure that the
How changes are detected
- The Push action detects changes in translation files by comparing the latest commit with the one directly before it. This approach ensures the action processes only the most recent updates, rather than scanning the entire repository.
- If there are no changes between these two commits, the action will not upload any files to Lokalise. To ensure your updates are processed, make sure the most recent commit includes all intended changes to your translation files.
- Create and switch to the lokalise-hub branch:
git checkout -b lokalise-hub
- Set up the translation folder and files:
In this branch, create a folder for your translations if you haven't already done so. The folder name should match thetranslations_path
you configured in step 1.- For example, if your base language on Lokalise is English (
en
), create a folder calledlocales
and inside it, anen
directory. Place your base language translation files in this directory. For this demo, we’ll use the JSON format.
Your folder structure should look like this:
- For example, if your base language on Lokalise is English (
locales/
├── en/
│ ├── main.json
│ └── en.json
- 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 supports several optional parameters for further customization. These parameters provide flexibility when handling specific workflows or addressing edge cases.
-
additional_params
: Extra parameters to pass to the Lokalise CLI when pushing files. For example, you can use--convert-placeholders
to handle placeholders. Multiple CLI arguments can be included as needed. Defaults to an empty string. -
flat_naming
: Use flat naming convention. Set this totrue
if your translation files follow a flat naming pattern, such aslocales/en.json
, instead of being organized in nested folders likelocales/en/file.json
. Defaults tofalse
. -
max_retries
: The maximum number of retries in case of rate limit errors (HTTP 429). Defaults to3
. -
sleep_on_retry
: The number of seconds to wait before retrying after a rate limit error. Defaults to1
. -
upload_timeout
: The timeout for the upload operation, in seconds. This defines the maximum time allowed for a file upload before it is considered a failure. Defaults to120
. -
upload_poll_timeout
: The timeout for polling the upload status, in seconds. This defines the maximum time to wait for an upload process to complete before retrying. Defaults to120
.
Pushing translations to Lokalise
Now that everything is set up, you're ready to push translations from GitHub to Lokalise.
- Go to the Actions tab in your GitHub repository.
- Open the Push to Lokalise workflow. From the branch dropdown, select the
lokalise-hub
branch.
- Click Run workflow.
- 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 already have translation files in your main branch before switching to the lokalise-hub
branch, there’s no need to worry. The Push action only processes translation files that have been created or changed since the most recent commit. Files already in your version control history will not be treated as “new,” so they won’t be uploaded again unless modified.
When no changes are detected between the last two commits, the action checks if it is running for the first time on the current branch by searching for a lokalise-upload-complete
tag:
- If the tag exists, it means the initial upload has already occurred, and the action will exit without uploading anything.
- If the tag is missing, the action will upload all translation files for the base language to Lokalise. After completing the upload, it creates the
lokalise-upload-complete
tag to indicate that the initial setup is finished.
Recommendation: After the initial run, pull the tag into your local repository using
git pull
to ensure your local copy reflects this setup.
If you have additional translation files for other (non-base) languages that you want to upload, you’ll need to do this manually in Lokalise. When uploading these files, ensure the filenames match the structure expected by Lokalise. For example, if your base language files are stored in locales/%LANG_ISO%/main.json
, ensure that files for other languages follow the same structure (e.g., locales/fr/main.json
for French or locales/de/main.json
for German).
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 or creating new keys in Lokalise, you can sync these changes back to your hub branch.
- Create the Pull action
Start by switching to the main branch of your repository. Then, create a.github/workflows/pull.yml
file and add the pull action configuration to it.
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
, andnonhidden
.- For example:
additional_params: "--filter-data translated"
.
The following parameters are used in this example (note that we’re not covering all supported parameters here):
api_token
: Secret variable containing your read/write API token. Refer to the Lokalise API token section for setup instructions.project_id
: Your Lokalise project ID.translations_path
: One or more directories in the project root containing your translation files without leading or trailing slashes (e.g.,locales
).- The full path to the translation files is constructed as
TRANSLATIONS_PATH/LOCALE/**/**.FILE_FORMAT
. Check the Translation files section for more details on file organization. - If your files are not nested under additional folders and instead stored directly in the
translations_path
(e.g.,locales/en.json
ori18n/fr.json
), set theflat_naming
parameter totrue
.
- The full path to the translation files is constructed as
base_lang
: The base language of your Lokalise project (e.g.,en
). Be mindful of regional codes! For example:- If your base language is
fr_CA
, provide exactly that value. - Ensure the
translations_path
includes a folder named after the base language. For instance, if yourtranslations_path
is set tolocales
andbase_lang
isen
, the workflow expects translation files under the/locales/en/
folder.
- If your base language is
file_format
: Specifies the format of your translation files, such asjson
. Do not include a leading dot.
- Push your newly created action to the main branch on GitHub.
- Grant proper permissions to the actions. To achieve that:
- Go to your GitHub repository's Settings.
- Navigate to Actions > General.
- Under Workflow permissions, set the permissions to Read and write permissions.
- 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").
Assigning Lokalise filenames and tags
Before running this action, ensure that your translation keys on Lokalise are correctly assigned with appropriate filenames and tags.
If you are running this action from the
hub
branch on GitHub, the action will download only the keys that have thehub
tag assigned. If no such keys are found, the action will halt execution.If you specify
locales
as thetranslations_path
, your keys must include filenames that align with this structure, such as:
locales/%LANG_ISO%.json
locales/%LANG_ISO%/main.xml
If the filenames do not include the correct directory prefix (like
locales/
), the action will fail to compare the downloaded files with the existing files in yourtranslations_path
. In this case, the workflow logs will show the message: "No changes detected in translation files.".
- Head back to your GitHub repository and navigate to the Actions tab.
- Select the Pull from Lokalise action.
- Make sure you choose the hub branch as the trigger for this workflow.
- Once the workflow completes, switch to the Pull requests tab. You should see a new pull request created.
- 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 prefixlok
, followed by the hub branch name. - 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.
- 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 totrue
when configuring the action.
Additional parameters for the Pull action
The Pull action supports several optional parameters for further customization. These parameters allow you to tailor the workflow to your specific needs.
-
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, such as--indentation 2sp --placeholder-format icu
. Defaults to an empty string. -
temp_branch_prefix
: A prefix for the temporary branch used to create the pull request. For example, usinglok
will result in a branch name starting withlok
. Defaults tolok
. -
always_pull_base
: By default, changes in the base language translation files (as defined by thebase_lang
option) are ignored when checking for updates. Set this option totrue
to include changes in the base language translations in the pull request. Defaults tofalse
. -
flat_naming
: Use flat naming convention. Set this totrue
if your translation files follow a flat naming pattern likelocales/en.json
instead of being organized in nested folders likelocales/en/file.json
. Defaults tofalse
. -
skip_include_tags
— Skip setting the--include-tags
argument during download. This will download all translation keys for the specified format, regardless of tags. You can also provide custom filtering options viaadditional_params
, for example--include-tags staging,dev
. -
max_retries
: The maximum number of retries on rate limit errors (HTTP 429). Defaults to3
. -
sleep_on_retry
: The number of seconds to sleep before retrying on rate limit errors. Defaults to1
. -
download_timeout
: The timeout for the download operation, in seconds. This defines the maximum time allowed for downloading files before the operation is considered a failure. Defaults to120
.
Assumptions and defaults
Translation files
This workflow assumes that the translations_path
option can include one or more directories where your translation files are stored. By default, each folder specified in translations_path
should contain subfolders named after your project locales. For example, if your base language is en
, there should be a folder named en
inside each specified path. Here's an example directory structure:
locales/
├── en/
│ ├── main.json
│ └── admin.json
└── fr/
├── main.json
└── admin.json
When managing translation keys on Lokalise, ensure the filenames match your repository structure. If you store translations under translations_path/%LANG_ISO%/
, the filenames assigned to the keys must follow this pattern: translations_path/%LANG_ISO%/TRANSLATION_FILE_NAME
.
Nested files
Nested folders are fully supported. For example, you can organize files like this: locales/en/nested_folder/main.json
.
Flat naming convention
If your translation files are stored directly in the translations_path
without locale-specific subfolders (e.g., locales/en.json
or locales/fr.json
), set the flat_naming
parameter to true
. Here's an example of a flat naming structure:
locales/
├── en.json
├── fr.json
└── de.json
Tags
Every translation key uploaded to Lokalise via the Push action is automatically tagged with the name of the branch that triggered the workflow. For example, if the workflow is triggered by the lokalise-hub
branch, all affected keys will receive a lokalise-hub
tag.
When running the Pull action, the workflow filters keys by the tag matching the branch name. For instance, if you run the Pull action from the lokalise-hub
branch, only keys tagged with lokalise-hub
will be downloaded, while other keys will be ignored.
To ensure all relevant keys are included in the workflow, it’s essential to retain these tags. If a tag is removed by mistake, you can reassign it manually via the Lokalise UI.
Ignoring tags on pull
If you need to pull all keys regardless of the assigned tags, set the skip_include_tags
option to true
. You can also provide custom filtering options via additional_params
, for example --include-tags staging,dev
.
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.
Updated 1 day ago