307 lines
11 KiB
Markdown
307 lines
11 KiB
Markdown
# GitHub-Side Localization Workflow Report
|
|
|
|
## Scope
|
|
|
|
This document defines the repository-side localization workflow for Option B.
|
|
It focuses on GitHub Actions, branch conventions, pull requests, and validation gates around Crowdin.
|
|
|
|
This is intentionally repository-specific operational guidance, not a generic Crowdin or GitHub Actions tutorial.
|
|
|
|
External prerequisite:
|
|
|
|
- the Crowdin project and GitHub Actions secrets must already be configured
|
|
- if Crowdin's native GitHub integration exists on the Crowdin side, it must not be used as a second write-back path for this repository
|
|
|
|
## Repository Policy
|
|
|
|
- `zh-CN` is the only source language of truth in the repository
|
|
- target-locale files committed in the repository are synchronization artifacts and reviewable outputs, not the normal long-term editing surface
|
|
- existing committed target translations must be bootstrapped into Crowdin once before steady-state sync is trusted
|
|
- after bootstrap, Crowdin is the normal editing surface for target translations
|
|
- GitHub Actions is the only allowed GitHub-side synchronization mechanism between this repository and Crowdin
|
|
- translations return through `l10n_*` pull requests, not direct pushes into `main` or `r-dev`
|
|
|
|
## Branch Model
|
|
|
|
- source branches covered by the localization workflow:
|
|
- `main`
|
|
- `r-dev`
|
|
- Crowdin return branches:
|
|
- `l10n_main`
|
|
- `l10n_r-dev`
|
|
- merge strategy:
|
|
- translations do not go directly into `main` or `r-dev`
|
|
- translations are reviewed through pull requests before merge
|
|
|
|
## Source of Truth and Trigger Surface
|
|
|
|
- source locale for JSON translations: `locales/zh-CN/*.json`
|
|
- source locale for prompt templates: `prompts/zh-CN/**/*.prompt`
|
|
- source locale for dashboard WebUI translations: `dashboard/src/i18n/locales/zh.json`
|
|
- current prompt template extension in the repository: `.prompt`
|
|
- dashboard WebUI keeps short runtime locale filenames (`zh`, `en`, `ja`, `ko`) in Git, but `dashboard/src/i18n/locales/zh.json` is still the repository-side `zh-CN` source asset for that file group
|
|
|
|
Normal push-triggered source uploads remain strictly source-driven.
|
|
Translated target assets are not part of the steady-state upload trigger set.
|
|
|
|
## Workflows Involved
|
|
|
|
### 1. `crowdin-bootstrap.yml`
|
|
|
|
Role:
|
|
|
|
- provides a manual bootstrap path for existing committed target translations
|
|
- seeds Crowdin from the repository's current target-locale state
|
|
- keeps this exceptional upload path separate from normal source-driven sync
|
|
|
|
Triggers:
|
|
|
|
- manual dispatch only
|
|
|
|
Visibility requirement:
|
|
|
|
- because this workflow uses `workflow_dispatch`, GitHub only exposes it after the workflow file exists on the repository default branch
|
|
- in this repository, maintainers should merge the workflow file into `main` before expecting it to appear in the Actions UI or be runnable through `gh workflow run`
|
|
|
|
Inputs:
|
|
|
|
- `base_branch`: `main` or `r-dev`
|
|
- `confirm_bootstrap`: explicit confirmation string
|
|
|
|
Behavior:
|
|
|
|
- checks out the selected repository branch
|
|
- uploads sources and committed target translations to Crowdin
|
|
- does not download translations
|
|
- does not create or update `l10n_*` pull requests
|
|
|
|
Guardrail:
|
|
|
|
- this workflow is intentionally one-time or exceptional
|
|
- maintainers must not treat it as a continuous GitHub-to-Crowdin target-translation sync path
|
|
|
|
### 2. `crowdin-sync.yml`
|
|
|
|
Role:
|
|
|
|
- uploads source-language assets to Crowdin
|
|
- downloads currently available translations from Crowdin when the workflow runs
|
|
- creates or updates localization pull requests back to the matching base branch
|
|
|
|
Triggers:
|
|
|
|
- manual dispatch
|
|
- scheduled sync every 6 hours: `17 */6 * * *` UTC
|
|
- push to `main` or `r-dev` when one of these paths changes:
|
|
- `crowdin.yml`
|
|
- `locales/zh-CN/*.json`
|
|
- `prompts/zh-CN/**/*.prompt`
|
|
- `dashboard/src/i18n/locales/zh.json`
|
|
|
|
Branch behavior:
|
|
|
|
- push-triggered runs sync the current Git branch and use a matching localization branch name:
|
|
- `main -> l10n_main -> PR into main`
|
|
- `r-dev -> l10n_r-dev -> PR into r-dev`
|
|
- scheduled runs explicitly cover both `main` and `r-dev`
|
|
|
|
Permissions and credentials:
|
|
|
|
- `contents: write`
|
|
- `pull-requests: write`
|
|
- `GITHUB_TOKEN`
|
|
- `CROWDIN_PROJECT_ID`
|
|
- `CROWDIN_PERSONAL_TOKEN`
|
|
|
|
Important boundary:
|
|
|
|
- the steady-state workflow keeps the PR-based return flow intact
|
|
- normal runs do not upload direct GitHub edits to target-locale files back into Crowdin
|
|
|
|
### 3. `i18n-validate.yml`
|
|
|
|
Role:
|
|
|
|
- runs repository-side localization validation
|
|
- blocks structurally invalid or policy-breaking localization changes
|
|
|
|
Triggers:
|
|
|
|
- pull requests that touch:
|
|
- `locales/**/*.json`
|
|
- `prompts/**/*.prompt`
|
|
- `dashboard/src/i18n/index.ts`
|
|
- `dashboard/src/i18n/locales/*.json`
|
|
- `scripts/i18n_validate.py`
|
|
- `src/common/i18n/**/*.py`
|
|
- `src/common/prompt_i18n.py`
|
|
- `src/prompt/prompt_manager.py`
|
|
- pushes to `main` or `r-dev` for the same path set
|
|
|
|
Validation scope:
|
|
|
|
- JSON locale key alignment against `zh-CN`
|
|
- dashboard nested JSON locale key alignment against `dashboard/src/i18n/locales/zh.json`
|
|
- placeholder consistency
|
|
- dashboard i18next interpolation placeholder consistency
|
|
- plural structure consistency
|
|
- prompt placeholder consistency
|
|
- English locale protection against Chinese source-language leakage
|
|
- rejection of non-`zh-CN` entries that directly preserve Chinese source text
|
|
|
|
Prompt behavior note:
|
|
|
|
- missing target prompt files currently produce warnings, not hard failures
|
|
- runtime still falls back to `zh-CN` prompt templates when localized prompt files are absent
|
|
|
|
### 4. `precheck.yml`
|
|
|
|
Role:
|
|
|
|
- checks whether a pull request conflicts with its real target branch
|
|
- preserves the existing conflict-label behavior
|
|
|
|
Behavior:
|
|
|
|
- checks out the PR head commit
|
|
- fetches the actual PR base branch from `github.event.pull_request.base.ref`
|
|
- performs a merge simulation against that real base branch
|
|
- marks the PR as conflicted only if the merge simulation produces unmerged files
|
|
|
|
This means:
|
|
|
|
- feature branches into `main` are checked against `main`
|
|
- feature branches into `r-dev` are checked against `r-dev`
|
|
- `l10n_main` PRs are checked against `main`
|
|
- `l10n_r-dev` PRs are checked against `r-dev`
|
|
|
|
### 5. `ruff-pr.yml`
|
|
|
|
Role:
|
|
|
|
- runs Ruff lint and format checks for pull requests that are relevant to Python code quality
|
|
|
|
Effect:
|
|
|
|
- translation-only localization pull requests do not run Ruff by default
|
|
- Python or Ruff-related pull requests still run the existing Ruff checks
|
|
|
|
## End-to-End GitHub Flow
|
|
|
|
### A. One-time bootstrap of existing target translations
|
|
|
|
1. A maintainer chooses `main` or `r-dev` as the branch whose committed target translations should seed Crowdin.
|
|
2. The maintainer manually runs `crowdin-bootstrap.yml` with explicit confirmation.
|
|
3. The workflow uploads the selected branch's current sources and committed target translations to Crowdin.
|
|
4. No `l10n_*` pull request is created by this bootstrap workflow.
|
|
5. After bootstrap, target-language maintenance should move to Crowdin as the normal editing surface.
|
|
|
|
### B. Normal source-language update on `main` or `r-dev`
|
|
|
|
1. A source-language change is pushed to `main` or `r-dev`.
|
|
2. `crowdin-sync.yml` uploads source-language assets to Crowdin, including the dashboard WebUI source file `dashboard/src/i18n/locales/zh.json`.
|
|
3. The same workflow may also download any translations currently available in Crowdin when that workflow run executes.
|
|
4. A localization pull request is opened or updated:
|
|
- `l10n_main -> main`
|
|
- `l10n_r-dev -> r-dev`
|
|
|
|
### C. Translation return flow
|
|
|
|
1. Translators work in Crowdin.
|
|
2. Repository updates do not appear in `main` or `r-dev` immediately at approval time.
|
|
3. Repository write-back happens when `crowdin-sync.yml` runs.
|
|
4. GitHub updates or creates `l10n_${branch}` pull requests.
|
|
5. Maintainers review and merge the localization pull request in the normal PR flow.
|
|
|
|
### D. Scheduled sync
|
|
|
|
1. Every 6 hours, GitHub Actions runs a scheduled localization sync.
|
|
2. The workflow explicitly processes both `main` and `r-dev`.
|
|
3. If Crowdin currently has downloadable translation updates, GitHub updates or creates the corresponding `l10n_` pull requests.
|
|
|
|
## How the Setup Avoids Sync Loops
|
|
|
|
- source uploads are triggered only from:
|
|
- `crowdin.yml`
|
|
- `locales/zh-CN/*.json`
|
|
- `prompts/zh-CN/**/*.prompt`
|
|
- `dashboard/src/i18n/locales/zh.json`
|
|
- translated target files do not trigger another steady-state upload cycle
|
|
- the bootstrap path is manual and confirmation-gated
|
|
- translations return through `l10n_` branches and PRs instead of direct pushes to base branches
|
|
- translation-only PRs do not trigger Ruff, which reduces unnecessary CI noise without weakening Python quality gates
|
|
|
|
## GitHub-Usable Maintainer Operations
|
|
|
|
### Trigger the bootstrap path
|
|
|
|
GitHub UI:
|
|
|
|
- Actions -> `Crowdin Bootstrap Target Translations`
|
|
- if it does not appear yet, first make sure the workflow file has already landed on the default branch (`main`)
|
|
- choose `main` or `r-dev`
|
|
- set `confirm_bootstrap` to `yes-bootstrap-current-target-translations`
|
|
|
|
GitHub CLI:
|
|
|
|
```bash
|
|
gh workflow run crowdin-bootstrap.yml \
|
|
--ref main \
|
|
-f base_branch=r-dev \
|
|
-f confirm_bootstrap=yes-bootstrap-current-target-translations
|
|
```
|
|
|
|
Use this only when seeding Crowdin from already-committed target translations, or in another exceptional recovery scenario.
|
|
|
|
### Trigger a normal manual sync
|
|
|
|
GitHub UI:
|
|
|
|
- Actions -> `Crowdin Sync`
|
|
- if a newly added manual workflow does not appear, confirm that workflow file is already on the default branch
|
|
- run the workflow on `main` or `r-dev`
|
|
|
|
GitHub CLI:
|
|
|
|
```bash
|
|
gh workflow run crowdin-sync.yml --ref main
|
|
```
|
|
|
|
### Inspect workflow runs
|
|
|
|
```bash
|
|
gh run list --workflow crowdin-sync.yml --limit 5
|
|
gh run list --workflow crowdin-bootstrap.yml --limit 5
|
|
```
|
|
|
|
### Inspect resulting localization pull requests
|
|
|
|
```bash
|
|
gh pr list --head l10n_main
|
|
gh pr list --head l10n_r-dev
|
|
```
|
|
|
|
### Verify that GitHub Actions is the repository write-back path
|
|
|
|
- confirm there is a successful `crowdin-sync.yml` run corresponding to the latest `l10n_*` PR update
|
|
- confirm translated content returned through `l10n_main` or `l10n_r-dev`, not a direct push into `main` or `r-dev`
|
|
- do not rely on a separate Crowdin native GitHub integration PR or branch flow for this repository
|
|
|
|
## Guardrails That Remain Intact
|
|
|
|
- localization PRs are still checked against their real base branch
|
|
- repository-side localization validation still runs where expected
|
|
- translation-only PRs still avoid unnecessary Ruff noise by default
|
|
- Python-impacting PRs still run Python quality gates where appropriate
|
|
- the steady-state `zh-CN` source-trigger model remains unchanged
|
|
|
|
## Bottom Line
|
|
|
|
The GitHub-side localization workflow now supports the intended Option B model:
|
|
|
|
- `zh-CN` remains the only repository source language
|
|
- existing committed target translations can be bootstrapped into Crowdin once through a manual workflow
|
|
- steady-state sync remains source-driven and GitHub Actions-only
|
|
- translated content still returns through `l10n_${branch}` pull requests
|
|
- existing PR validation and reduced-noise translation PR behavior remain intact
|