GitHub action to upload changed translation files in the base language from your GitHub repository to Lokalise TMS.
- Step-by-step tutorial covering the usage of this action is available on Lokalise Developer Hub.
- If you're looking for an in-depth tutorial, check out our blog post
To download translation files from Lokalise to GitHub, use the lokalise-pull-action.
To find documentation for the stable version 3, browse the v3 tag.
Use this action in the following way:
name: Demo push with tags
on:
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Push to Lokalise
uses: lokalise/[email protected]
with:
api_token: ${{ secrets.LOKALISE_API_TOKEN }}
project_id: LOKALISE_PROJECT_ID
base_lang: en
translations_path: |
TRANSLATIONS_PATH1
TRANSLATIONS_PATH2
file_ext: |
json
additional_params: >
{
"convert_placeholders": true,
"hidden_from_contributors": true
}You'll need to provide some parameters for the action. These can be set as environment variables, secrets, or passed directly. Refer to the General setup section for detailed instructions.
api_token— Lokalise API token with read/write permissions.project_id— Your Lokalise project ID.translations_path— One or more paths to your translations. For example, if your translations are stored in thelocalesfolder at the project root, uselocales(leave out leading and trailing slashes). Defaults tolocales.file_format—⚠️ DEPRECATED: usefile_extinstead. This will be removed in the next stable release. Defines the format of your translation files, such asjsonfor JSON files. Defaults tojson. This format determines how translation files are processed and also influences the file extension used when searching for them. However, some specific formats, such asjson_structured, still use the generic.jsonextension. If you're using such a format, make sure to set thefile_extparameter explicitly to match the correct extension for your files. Alternatively, configure thename_patternparameter.base_lang— The base language of your project (e.g.,enfor English). Defaults toen.file_ext— File extension(s) to use when searching for translation files without leading dot. This parameter has no effect when thename_patternis provided.
file_ext: json
# OR
file_ext: |
strings
stringsdictflat_naming— Use flat naming convention. Set totrueif your translation files follow a flat naming pattern likelocales/en.jsoninstead oflocales/en/file.json. Defaults tofalse.name_pattern— Custom pattern for naming translation files. Overrides default language-based naming. Must include both filename and extension if applicable (e.g.,"custom_name.json"or"**/*.yaml"). Default behavior is used if not set.- When
name_patternis set, the action respects yourtranslations_pathbut does not append language-based folders. For example:"en/**/custom_*.json"will match nested files for theenlocale"custom_*.json"matches files directly under the given path
This approach gives you fine-grained control similar toflat_naming, but with more flexibility.
- When
additional_params— Extra parameters to pass to the Upload file API endpoint. Must contain valid JSON. Defaults to an empty string. Be careful when setting theinclude_pathadditional parameter tofalse, as it will mean your keys won't be assigned with any filename upon upload: this might pose a problem if you're planning to utilize the pull action to download translation back. You can include multiple API parameters as needed:
additional_params: >
{
"convert_placeholders": true,
"hidden_from_contributors": true
}skip_tagging— Do not assign tags to the uploaded translation keys on Lokalise. Set this totrueto skip adding tags like inserted, skipped, or updated keys. Defaults tofalse.skip_polling— Skips waiting for the upload operation to complete. When set totrue, thepoll_initial_waitandpoll_max_waitparameters are ignored. Defaults tofalse.skip_default_flags— Prevents the action from setting additional default flags for theuploadcommand. By default, the action includesreplace_modified,include_path, anddistinguish_by_fileset totrue. Whenskip_default_flagsistrue, these parameters are not added. Defaults tofalse.rambo_mode— Always upload all translation files for the base language regardless of changes. Set this totrueto bypass change detection and force a full upload of all base language translation files. Defaults tofalse.use_tag_tracking— Enables branch-specific sync tracking using Git tags. When set totrue, the action creates a unique tag for each branch to remember the last successfully synced commit. On subsequent runs, it compares the current commit against the tagged commit to detect all changes since the last successful sync — regardless of how many commits occurred in between. This feature is still experimental.- By default, when
use_tag_trackingisfalse, the action compares just the last two commits (HEADandHEAD~1) to determine what changed. Enablinguse_tag_trackingallows the action to detect broader changes across multiple commits and ensure nothing gets skipped during uploads. - This parameter has no effect if the
rambo_modeis set totrue.
- By default, when
max_retries— Maximum number of retries on rate limit (HTTP 429) and other retryable errors. Defaults to3.sleep_on_retry— Number of seconds to sleep before retrying on retryable errors (exponential backoff applies). Defaults to1.upload_timeout— Timeout for the whole upload operation, in seconds. Defaults to600.poll_initial_wait— Initial timeout for the upload poll operation, in seconds. Defaults to1.poll_max_wait— Maximum timeout for the upload poll operation, in seconds. Defaults to120.http_timeout— Timeout in seconds for every HTTP operation. Defaults to120.
git_user_name— Optional Git username to use when tagging the initial Lokalise upload. If not provided, the action will default to the GitHub actor that triggered the workflow. This is useful if you'd like to show a more descriptive or bot-specific name in your Git history (e.g., "Lokalise Sync Bot").git_user_email— Optional Git email to associate with the Git tag for the initial Lokalise upload. If not set, the action will use a noreply address based on the username (e.g.,[email protected]). Useful for customizing commit/tag authorship or when working in teams with dedicated automation accounts.
os_platform— Target platform for the precompiled binaries used by this action (linux_amd64,linux_arm64,mac_amd64,mac_arm64). These binaries handle tasks like uploading and processing translations. Typically, you don't need to change this, as the default (linux_amd64) works for most environments. Override if running on a macOS runner or a different architecture.
This action outputs the following values:
initial_run— Indicates whether this is the first run on the branch. The value istrueif thelokalise-upload-completetag does not exist, otherwisefalse.files_uploaded— Indicates whether any files were uploaded to Lokalise. The value istrueif files were successfully uploaded, otherwisefalse(e.g., no changes or upload step skipped).
This actions requires the following permissions:
permissions:
contents: writeWhen triggered, this action follows a multi-step process to detect changes in translation files and upload them to Lokalise:
-
Detect changed files:
- The action identifies all changed translation files for the base language specified under the
translations_path. - By default, changes are detected only between the latest commit and the one preceding it.
- You can enable detection across multiple commits using the
use_tag_trackingoption:- When
use_tag_trackingis set totrue, the action compares the current commit with the last known synced commit on the branch (stored as a Git tag). - This ensures that any files changed across multiple previous commits are still uploaded, even when the action is run manually or after a batch push.
- When
- The action identifies all changed translation files for the base language specified under the
-
Upload modified files:
- Any detected changes are uploaded to the specified Lokalise project in parallel, with up to six requests being processed simultaneously.
- Each translation key is tagged with the name of the branch that triggered the workflow for better traceability in Lokalise. This also helps pulling your files back using the lokalise-pull action.
-
Handle initial push:
- If no changes are detected, the action determines if it is running for the first time on the branch:
- First run: The action checks for the presence of a
lokalise-upload-completetag.- If the tag is not found, it performs an initial upload, processing all translation files for the base language. This also happens when the
rambo_modeis set totrue. - After successfully uploading all files, the action creates a
lokalise-upload-completetag to mark the initial setup as complete.
- If the tag is not found, it performs an initial upload, processing all translation files for the base language. This also happens when the
- Subsequent runs: If the tag is found and no new changes are detected (or no new commits when using
use_tag_tracking), the action exits early without uploading any files.
- First run: The action checks for the presence of a
- If no changes are detected, the action determines if it is running for the first time on the branch:
-
Track synced commits per branch (optional):
- When
use_tag_trackingis enabled and files are uploaded, the action creates or updates a branch-specific tag namedlokalise-sync-<branch-name>pointing to the latest synced commit. - This tag is used on future runs to determine the delta of changed files, preventing missed uploads.
- When
-
Mark completion:
- For the first run on the branch, after completing the initial upload, the action pushes the
lokalise-upload-completetag to the remote repository. - Recommendation: Pull the changes to your local repository to ensure the tag is included in your local Git history.
- For the first run on the branch, after completing the initial upload, the action pushes the
For more information on assumptions, refer to the Assumptions and defaults section.
By default, the following API parameters and headers are set when uploading files to Lokalise:
X-Api-Tokenheader — Derived from theapi_tokenparameter.project_idGET param — Derived from theproject_idparameter.filename— The currently uploaded file.lang_iso— The language ISO code of the translation file.replace_modified— Set totrue.include_path— Set totrue.distinguish_by_file— Set totrue.tag_inserted_keys— Set totrue.tag_skipped_keys— Set totrue.tag_updated_keys— Set totrue.tags— Set to the branch name that triggered the workflow.
Apache license version 2