Skip to content

Latest commit

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

TextSetu GitHub Action

Sync translations with TextSetu from GitHub Actions. A thin wrapper around @textsetu/cli.

Where this lives. The action is developed here, inside the CLI package, so that a change to a CLI flag and the action input that passes it land in the same commit. It is published to the Marketplace from a mirror repo (TextSetu/github-action), which is what uses: refers to.

The two workflows worth having

1. Push sources when they change. Your repo is the source of truth for English; TextSetu is where it gets translated.

name: Upload strings to TextSetuon:
push:
branches: [main]paths: ["locales/**"]jobs:
upload:
runs-on: ubuntu-lateststeps:
- uses: actions/checkout@v4
- uses: TextSetu/github-action@v1with:
api_key: ${{ secrets.TEXTSETU_API_KEY }}upload_sources: true

2. Bring translations back as a pull request. On a schedule, so a reviewer sees them rather than a bot committing to main.

name: Download translations from TextSetuon:
schedule: [{ cron: "0 6 * * 1" }] # Mondays, 06:00 UTCworkflow_dispatch:
permissions:
contents: writepull-requests: writejobs:
download:
runs-on: ubuntu-lateststeps:
- uses: actions/checkout@v4
- uses: TextSetu/github-action@v1with:
api_key: ${{ secrets.TEXTSETU_API_KEY }}upload_sources: falsedownload_translations: truecreate_pull_request: true

permissions is required, and so is allowing Actions to create pull requests (Settings → Actions → General). Without both, the run fails at the push step.

Gating a release

- uses: TextSetu/github-action@v1with:
api_key: ${{ secrets.TEXTSETU_API_KEY }}upload_sources: falsecheck_threshold: 95# fail the job if any locale is below 95%

The gate runs last, so it reflects whatever the same run just synced. It fails the job through the CLI's exit code 4, which is distinct from a generic failure — so a pipeline can tell "translations aren't ready" from "the token expired" (3).

Which token

Use a project token (tsu_proj_…) — it is bound to one project, which is what you want for a repo secret. Create it in the web app under Project settings → API tokens, granting only translation_read (to pull) and translation_create (to push).

Note a project token never counts as an approver: on a project that requires approval, its pushes land as pending_review rather than live, and it cannot complete a branch merge. Both are usually what you want from CI.

Inputs

InputDefaultNotes
api_keyRequired. Put it in a secret, never in the workflow file.
api_urlproductionOnly for a self-hosted deployment.
projectfrom configOverrides projectId in textsetu.json.
configtextsetu.jsonPath, if not at the repo root.
cli_versionlatestPin it for reproducible builds.
upload_sourcestrue
upload_translationsfalseOpt-in: pushing targets can overwrite reviewed work.
download_translationsfalse
download_statusapprovedall | approved | pending_review | draft
localesallSpace-separated, e.g. fr de.
branchmainA TextSetu translation branch, not a git branch.
dry_runfalsePrint the resolved file plan and change nothing.
check_thresholdSet to run the completeness gate.
create_pull_requesttrueOnly applies when downloading.
localization_branch_namel10n_textsetu
pull_request_titleNew TextSetu translations
pull_request_body
pull_request_base_branch_namethe current branch
pull_request_labelsComma-separated.
commit_messagechore(i18n): update translations from TextSetu
github_tokengithub.tokenNeeds contents:write + pull-requests:write.
command / command_argsEscape hatch: run any CLI command instead.

Outputs

OutputNotes
changedtrue if downloading modified any tracked file.
pull_request_urlThe PR that was created or updated, if any.

Behaviour worth knowing

  • The PR branch is force-pushed to a single commit. It represents "the translations as they are now"; a growing chain of update translations commits makes the PR unreviewable. An already-open PR is reused rather than replaced.
  • pull runs with --force. A runner is a fresh clone, so the CLI's lockfile conflict guard has no local edit to protect — it would only ever be comparing against what is committed, and exiting 5 there would wedge the workflow permanently. On a developer's machine that guard is exactly what you want, which is why it is on by default there and off here.
  • Nothing is committed when nothing changed.changed is false and the PR step is skipped.

About

Sync translations with TextSetu in CI. Uploads sources, downloads translations, and opens a pull request with the result.

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors