I18n: Refactor crowdin workflow (#81571)

* refactor: crowdin config

* feat: add GH actions

* refactor: remove old GH action

* refactor: fix formatting issue

* refactor: adjust docs

* refactor: add changes after code review

* refactor: add changes after code review

* refactor: update CODEOWNERS file
pull/81704/head
Laura Benz 1 year ago committed by GitHub
parent bac4c7fb32
commit 967a650d2d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 3
      .github/CODEOWNERS
  2. 51
      .github/workflows/i18n-crowdin-download.yml
  3. 67
      .github/workflows/i18n-crowdin-fix-files.yml
  4. 29
      .github/workflows/i18n-crowdin-upload.yml
  5. 20
      contribute/internationalization.md
  6. 7
      crowdin.yml
  7. 4
      public/locales/i18next-parser.config.js

@ -678,7 +678,8 @@ embed.go @grafana/grafana-as-code
/.github/workflows/ephemeral-instances-pr-opened-closed.yml @grafana/grafana-operator-experience-squad /.github/workflows/ephemeral-instances-pr-opened-closed.yml @grafana/grafana-operator-experience-squad
/.github/workflows/create-security-patch-from-security-mirror.yml @grafana/grafana-release-guild /.github/workflows/create-security-patch-from-security-mirror.yml @grafana/grafana-release-guild
/.github/workflows/core-plugins-build-and-release.yml @grafana/plugins-platform-frontend @grafana/plugins-platform-backend /.github/workflows/core-plugins-build-and-release.yml @grafana/plugins-platform-frontend @grafana/plugins-platform-backend
/.github/workflows/i18n-crowdin-fix-files.yml @grafana/grafana-frontend-platform /.github/workflows/i18n-crowdin-upload.yml @grafana/grafana-frontend-platform
/.github/workflows/i18n-crowdin-download.yml @grafana/grafana-frontend-platform
/.github/workflows/feature-toggle-cleanup.yml @tolzhabayev /.github/workflows/feature-toggle-cleanup.yml @tolzhabayev
/.github/workflows/scripts/feature-toggle-cleanup/feature-toggle-cleanup.js @tolzhabayev /.github/workflows/scripts/feature-toggle-cleanup/feature-toggle-cleanup.js @tolzhabayev

@ -0,0 +1,51 @@
name: Crowdin Download Action
on:
workflow_dispatch:
schedule:
- cron: "0 * * * *"
jobs:
download-sources-from-crowdin:
runs-on: ubuntu-latest
permissions:
contents: write # needed to commit changes into the PR
pull-requests: write # needed to update PR description, labels, etc
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.head_ref }}
- name: Download sources
uses: crowdin/github-action@v1
with:
upload_sources: false
upload_translations: false
download_sources: false
download_translations: true
localization_branch_name: i18n_crowdin_translations
create_pull_request: true
pull_request_title: 'I18n: Download translations from Crowdin'
pull_request_body: |
:robot: Automatic download of translations from Crowdin.
Steps for merging:
1. A quick sanity check of the changes and approve. Things to look out for:
- No changes in the English file. The source of truth is in the main branch, NOT in Crowdin.
- Translations maybe be removed if the English phrase was removed, but there should not be many of these
- Anything else that looks 'funky'. Ask if you're not sure.
2. Approve & (Auto-)merge. :tada:
If there's a conflict, close the pull request and **delete the branch**. A GH action will recreate the pull request.
Remember, the longer this pull request is open, the more likely it is that it'll get conflicts.
pull_request_labels: 'area/frontend, area/internationalization, no-changelog, no-backport'
pull_request_reviewers: 'grafana-frontend-platform'
pull_request_base_branch_name: 'main'
base_url: 'https://grafana.api.crowdin.com'
config: 'crowdin.yml'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}

@ -1,67 +0,0 @@
# When Crowdin creates a pull request from the crowdin-service-branch branch,
# run `yarn i18n:extract` and commit the changed grafana.json files back into the PR
# to reformat crowdin's changes to prevent conflicts with our CI checks.
name: Fix Crowdin I18n files
on:
pull_request:
paths:
- 'public/locales/*/grafana.json'
branches:
- main # Only run on pull requests *target* main (will be merged into main)
jobs:
fix-files:
# Only run on pull requests *from* the crowdin-service-branch branch
if: github.head_ref == 'crowdin-service-branch'
name: Fix files
runs-on: ubuntu-latest
permissions:
contents: write # needed to commit changes back into the PR
pull-requests: write # needed to update PR description
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.head_ref }}
- uses: actions/setup-node@v4
with:
node-version: 20.9.0
cache: 'yarn'
- name: Install dependencies
run: yarn install
- name: Extract I18n files
run: yarn i18n:extract
- name: Commit changes
uses: stefanzweifel/git-auto-commit-action@8756aa072ef5b4a080af5dc8fef36c5d586e521d # v5.0.0
with:
commit_message: "Github Action: Auto-fix i18n files"
file_pattern: public/locales/*/grafana.json
- name: Update PR description
uses: devindford/Append_PR_Comment@32dd2619cd96ac8da9907c416c992fe265233ca8 # v1.1.3
if: ${{ ! contains(github.event.pull_request.body, 'Steps for merging') }}
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
body-update-action: prefix
body-template: |
:robot: Automatic sync of translations from Crowdin.
Steps for merging:
1. Wait for the "Github Action: Auto-fix i18n files" commit that may be required for CI to pass.
2. A quick sanity check of the changes and approve. Things to look out for:
- No changes to the English strings. The source of truth is already in the main branch, NOT Crowdin.
- Translations maybe be removed if the English phrase was removed, but there should not be many of these
- Anything else that looks 'funky'. Ask if you're not sure.
3. Approve & (Auto-)merge. :tada:
If there's a conflict, close the pull request and **delete the branch**. Crowdin will recreate the pull request eventually.
Remember, the longer this pull request is open, the more likely it is that it'll get conflicts.

@ -0,0 +1,29 @@
name: Crowdin Upload Action
on:
push:
paths:
- 'public/locales/en-US/grafana.json'
branches:
- main
jobs:
upload-sources-to-crowdin:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Upload sources
uses: crowdin/github-action@v1
with:
upload_sources: true
upload_translations: false
download_translations: false
create_pull_request: false
base_url: 'https://grafana.api.crowdin.com'
config: 'crowdin.yml'
env:
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}

@ -9,7 +9,8 @@ Grafana uses the [i18next](https://www.i18next.com/) framework for managing tran
- Use `<Trans i18nKey="search-results.panel-link">Go to {{ pageTitle }}</Trans>` in code to add a translatable phrase - Use `<Trans i18nKey="search-results.panel-link">Go to {{ pageTitle }}</Trans>` in code to add a translatable phrase
- Translations are stored in JSON files in `public/locales/{locale}/grafana.json` - Translations are stored in JSON files in `public/locales/{locale}/grafana.json`
- If a particular phrase is not available in the a language then it will fall back to English - If a particular phrase is not available in the a language then it will fall back to English
- To update phrases in English, edit the default phrase in both the component's source and the [English grafana.json message catalogue](../public/locales/en-US/grafana.json), then run `yarn i18n:extract`. - To update phrases in English, edit the default phrase in the component's source and then run `yarn i18n:extract`.
- The single source of truth for en-US (fallback language) is in grafana/grafana, the single source of truth for any translated language is Crowdin
- To update phrases in any translated language, edit the phrase in Crowdin. Do not edit the `{locale}/grafana.json` - To update phrases in any translated language, edit the phrase in Crowdin. Do not edit the `{locale}/grafana.json`
## How to add a new translation phrase ## How to add a new translation phrase
@ -40,7 +41,8 @@ const ErrorMessage = ({ id, message }) => <Trans i18nKey={`errors.${id}`}>There
2. Upon reload, the default English phrase will appear on the page. 2. Upon reload, the default English phrase will appear on the page.
3. Before submitting your PR, run the `yarn i18n:extract` command to extract the messages you added into the `grafana.json` file and make them available for translation. 3. Before submitting your PR, run the `yarn i18n:extract` command to extract the messages you added into the `public/locales/en-US/grafana.json` file and make them available for translation.
**Note:** All other languages will receive their translations when they are ready to be downloaded from Crowdin.
### Plain JS usage ### Plain JS usage
@ -64,20 +66,20 @@ While the `t` function can technically be used outside of React functions (e.g,
## How to add a new language ## How to add a new language
1. Add new locale in Crowdin and sync files to repo 1. Add new locale in Crowdin and download files to repo
1. Grafana OSS Crowdin project -> "dot dot dot" menu in top right -> Target languages 1. Grafana OSS Crowdin project -> "dot dot dot" menu in top right -> Target languages
2. Grafana OSS Crowdin project -> Integrations -> Github -> Sync Now 2. If Crowdin's locale code is different from our IETF language tag, add a custom mapping in Project Settings -> Language mapping
3. If Crowdin's locale code is different from our IETF language tag, add a custom mapping in Project Settings -> Language mapping 3. GH repo grafana/grafana -> Actions -> Choose `Crowdin Download Action` -> Run workflow -> Creates a PR automatically
2. Update `public/app/core/internationalization/constants.ts` (add new constant, and add to `LOCALES`) 2. Review the PR `I18n: Download translations from Crowdin`
3. Update `public/locales/i18next-parser.config.js` to add the new locale to `locales` 3. Update `public/app/core/internationalization/constants.ts` (add new constant, and add to `LOCALES`) and add changes to the open PR
4. Run `yarn i18n:extract` and commit the result 4. Approve and merge the PR
## How translations work in Grafana ## How translations work in Grafana
Grafana uses the [i18next](https://www.i18next.com/) framework for managing translating phrases in the Grafana frontend. It: Grafana uses the [i18next](https://www.i18next.com/) framework for managing translating phrases in the Grafana frontend. It:
- Marks up phrases within our code for extraction - Marks up phrases within our code for extraction
- Extracts phrases into messages catalogues for translating in external systems - Extracts phrases into the default messages catalogue for translating in external systems
- Manages the user's locale and putting the translated phrases in the UI - Manages the user's locale and putting the translated phrases in the UI
Grafana will load the message catalogue JSON before the initial render. Grafana will load the message catalogue JSON before the initial render.

@ -2,7 +2,6 @@ files:
- source: /public/locales/en-US/grafana.json - source: /public/locales/en-US/grafana.json
translation: /public/locales/%locale%/%original_file_name% translation: /public/locales/%locale%/%original_file_name%
type: i18next_json type: i18next_json
pull_request_title: 'I18n: Crowdin sync' # The following are pulled from env variables
pull_request_labels: project_id_env: CROWDIN_PROJECT_ID
- area/internationalization api_token_env: CROWDIN_PERSONAL_TOKEN
- no-changelog

@ -1,8 +1,8 @@
module.exports = { module.exports = {
// Default namespace used in your i18next config // Default namespace used in your i18next config
defaultNamespace: 'grafana', defaultNamespace: 'grafana',
// Adds changes only to en-US when extracting keys, every other language is provided by Crowdin
locales: ['en-US', 'fr-FR', 'es-ES', "de-DE", "zh-Hans", 'pseudo-LOCALE'], locales: ['en-US'],
output: './public/locales/$LOCALE/$NAMESPACE.json', output: './public/locales/$LOCALE/$NAMESPACE.json',

Loading…
Cancel
Save