Skip to content
Use this GitHub action with your project
Add this Action to an existing workflow or create a new one
View on Marketplace

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

310 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🌐 Resource Translator

All Contributors

GitHub Marketplace ci CodeQL docs

A GitHub Action that opens machine-translated pull requests for resource files in your repository β€” without retranslating your entire catalog every time one string changes. Choose one translation provider per run β€” Azure AI Translator (default), AWS Translate, or Google Cloud Translation β€” behind a single, unified API surface. Each provider is driven by its official SDK (@azure-rest/ai-translation-text, @aws-sdk/client-translate, @google-cloud/translate), with built-in retry/throttling β€” no hand-rolled HTTP clients.

Note

Fully backward compatible. provider defaults to azure, so existing workflows keep working unchanged β€” no edits required.

Supported formats: .resx, .xliff, .po, .json, .ini, .restext.

Smart change detection

Translate the diff, not the catalog. Smart change detection is on by default and provider independent. The action keeps a compact, deterministic state manifest at .github/resource-translator-state.json and uses parser keys plus source-value hashes to translate only keys that are new, missing from a target file, changed in the source locale, or affected by translation-setting changes. Unchanged target values are reused, manual target-file edits are preserved, and every decision is logged with audit-friendly rule codes.

Commit the state manifest so future runs have a reliable baseline. Set changeDetection: disabled (or false) to restore the legacy behavior of translating every eligible key on every run, or set statePath to move the manifest.

If you already have localized target files and want to avoid the initial full retranslation, run once with snapshotOnly: true. Snapshot mode does not call Azure, AWS, or Google and does not write target resource files; it creates the state manifest from existing source/target files, then future smart runs only translate changed or missing keys.

πŸ“š Documentation

Everything lives on the docs site: ievangelist.github.io/resource-translator

πŸš€ Quick start

name: translate

on:
  push:
    branches: [main]
    paths:
      - "**/*.en.resx"
      - "**/*.en.json"

permissions:
  contents: write
  pull-requests: write

jobs:
  translate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5

      - id: translator
        uses: IEvangelist/resource-translator@v3
        with:
          sourceLocale: en
          provider: |
            azure:
              subscriptionKey: ${{ secrets.AZURE_TRANSLATOR_SUBSCRIPTION_KEY }}
              endpoint: ${{ secrets.AZURE_TRANSLATOR_ENDPOINT }}
              region: ${{ secrets.AZURE_TRANSLATOR_REGION }}
          toLocales: '["es","fr","de"]'

      - if: steps.translator.outputs.has-new-translations == 'true'
        uses: peter-evans/create-pull-request@v7
        with:
          branch: machine-translation
          title: ${{ steps.translator.outputs.summary-title }}
          body: ${{ steps.translator.outputs.summary-details }}
          labels: localization

For all inputs, repo config, glossary, tone/industry control, and recipes, see the full docs.

🌐 Translation providers

Pick one provider per run via the provider input (defaults to azure). For cleaner workflows, provider can be a nested YAML block with that provider's credentials and native behavior settings; the older flat inputs still work and override values inside the block. The providers docs include dedicated Azure, AWS, and Google sections with links to the official vendor docs.

Provider provider value SDK Credentials
Azure AI Translator azure (default) @azure-rest/ai-translation-text subscriptionKey, endpoint, region?
AWS Translate aws @aws-sdk/client-translate OIDC/default chain, or awsAccessKeyId + awsSecretAccessKey; awsRegion
Google Cloud Translation google @google-cloud/translate googleApiKey or googleCredentials (service-account JSON)

Important

Locale codes differ per provider (e.g. Simplified Chinese is zh-Hans on Azure, zh on AWS, zh-CN on Google). Codes pass through as-is and drive the output file names, so pick toLocales values your chosen provider supports.

AWS Translate (OIDC β€” recommended)

permissions:
  id-token: write # for aws-actions/configure-aws-credentials OIDC
  contents: write
  pull-requests: write

jobs:
  translate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5

      - uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123456789012:role/gh-actions-translate
          aws-region: us-east-1

      - id: translator
        uses: IEvangelist/resource-translator@v3
        with:
          provider: |
            aws:
              region: us-east-1 # or rely on AWS_REGION from the step above
              formality: FORMAL
              brevity: true
          sourceLocale: en
          toLocales: '["es","fr","de"]'

To use static keys instead of OIDC, drop the configure-aws-credentials step and add accessKeyId / secretAccessKey (via secrets) to the nested aws block, or use the equivalent flat inputs.

Google Cloud Translation

jobs:
  translate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5

      - id: translator
        uses: IEvangelist/resource-translator@v3
        with:
          provider: |
            google:
              # Provide EITHER a service-account JSON credential...
              credentials: ${{ secrets.GCP_TRANSLATE_CREDENTIALS }}
              # ...OR an API key:
              # apiKey: ${{ secrets.GCP_TRANSLATE_API_KEY }}
              model: nmt
          sourceLocale: en
          toLocales: '["es","fr","de"]'

Provider-specific intent specifiers are mapped where an equivalent exists: textType β†’ Google format; profanityAction (Marked/Deleted) β†’ AWS profanity masking. categoryId, apiVersion, profanityMarker, and allowFallback are Azure-only and ignored by the other providers.

Provider-native knobs are also available: AWS supports formality, brevity, terminologyNames, and parallelDataNames; Google supports model, apiEndpoint, and autoRetry.

πŸ”— Project links

✨ Contributors

Thanks goes to these wonderful people (emoji key):

vs-savelich
vs-savelich

πŸ’» ⚠️
Yevgen Nykytenko
Yevgen Nykytenko

πŸ›
Peter Rekdal Khan-Sunde
Peter Rekdal Khan-Sunde

πŸ›
Tim Heuer
Tim Heuer

πŸ› πŸ€” πŸ‘€
Tibor Tompa
Tibor Tompa

πŸ€”
Matteo
Matteo

πŸ’» ⚠️
Jeffrey T. Fritz
Jeffrey T. Fritz

πŸ“–

This project follows the all-contributors specification. Contributions of any kind welcome!

About

A GitHub Action that automatically creates machine-translated PRs of translation files. Supported file formats include, .ini, .po, .restext, .resx, .xliff .json.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

71 stars

Watchers

7 watching

Forks

Releases

Sponsor this project

Used by

Contributors

Languages