Add continuous translations (Faster Releases, Phase 2)#25675
Draft
jkmassel wants to merge 5 commits into
Draft
Conversation
Part of "Faster Releases" Phase 2 (continuous translations). A Fastlane helper (`StringPlaceholders`) that flags any localization key present in both the old and the new English source whose placeholder shape — count, position, or argument type — changed. New and removed keys are ignored, since copy that needs a fresh translation is expected to land under a new key. Exposed as the `validate_string_placeholders` lane, and reused to validate that AI-backfilled translations preserve their source's placeholders. Enforces the invariant the continuous-translation model relies on: never reuse a key for placeholder-incompatible copy.
Part of "Faster Releases" Phase 2 (continuous translations). The daily sync runs this so the app never ships an untranslated string. - `backfill_missing_translations` lane: for each locale, translate any key that exists in the English base but is missing from the locale, validate that each result preserves its placeholders, and append it to the locale's `Localizable.strings` under a marker comment. - `AITranslator` helper wraps the Anthropic API (sonnet-4-6, batched, JSON responses) and drops any translation whose placeholders don't match the source. - Adds the `anthropic` gem. Human translations from GlotPress overwrite these on the next sync; the AI output is never uploaded to GlotPress.
Phase 2 of the "Faster Releases" RFC. Both halves run in Buildkite.
Upload (on each trunk merge): regenerate the English `Localizable.strings` from
code, run the placeholder guardrail, and push to trunk so GlotPress imports new
strings promptly. Trunk-gated, and guarded against re-triggering itself.
Download (daily): `sync_translations` downloads the latest translations, runs the
AI backfill, and opens/updates a single PR to trunk (dependabot-style). Scheduled
via `.buildkite/translation-sync.yml`.
- `sync_translations` + `upload_strings_for_translation` lanes
- `.buildkite/commands/{sync-translations,upload-strings-for-translation}.sh`
- trunk-gated upload step in pipeline.yml (mac queue); daily pipeline yaml
The daily schedule itself is configured in Buildkite, pointing at the new pipeline.
Lets the upload-on-merge flow be exercised from a PR without touching trunk: `dry_run:true` regenerates the English strings and runs the placeholder guardrail but skips the commit and push. Adds a PR-only "Upload strings (dry run)" step; the real step stays trunk-gated.
Collaborator
Generated by 🚫 Danger |
The `fastlane/helpers/` path isn't covered by the lane-file exclusions in .rubocop.yml, so the Metrics cops apply. - Single-quote the model symbol (Style/QuotedSymbols). - Extract translation validation out of `translate` into `validated_translations` (AbcSize / CyclomaticComplexity / RedundantEach). - Collapse `signature` to one uniform position-keyed path and extract `specifiers` (AbcSize / CyclomaticComplexity / PerceivedComplexity). The signature string is internal — only compared within a run — so the change is behavior-preserving.
Contributor
|
| App Name | WordPress | |
| Configuration | Release-Alpha | |
| Build Number | 32722 | |
| Version | PR #25675 | |
| Bundle ID | org.wordpress.alpha | |
| Commit | 28313d6 | |
| Installation URL | 6h958nrtk3388 |
Contributor
|
| App Name | Jetpack | |
| Configuration | Release-Alpha | |
| Build Number | 32722 | |
| Version | PR #25675 | |
| Bundle ID | com.jetpack.alpha | |
| Commit | 28313d6 | |
| Installation URL | 5pcc8qi7citq8 |
This was referenced Jun 19, 2026
Open
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Description
Phase 2 of the Faster Releases RFC: keep translations continuously in sync instead of only at code freeze. Two halves, both in Buildkite, additive to the existing release process.
Upload on each trunk merge
Regenerate the English
Localizable.stringsfrom code, run a placeholder guardrail, and push to trunk so GlotPress imports new strings promptly.upload_strings_for_translationlane + a trunk-gated🌐 Localizationstep.StringPlaceholders,fastlane/helpers/string_placeholders.rb): an existing key may not change its placeholder shape — count, position, or argument type — without getting a new key, since that would silently break every existing translation. New and removed keys are fine.Download daily
Download the latest human translations, AI-backfill anything still untranslated so the app never ships untranslated copy, and open/update a single PR (dependabot-style, branch
bot/translation-sync).sync_translationslane +.buildkite/translation-sync.yml(the daily schedule itself is configured in Buildkite).backfill_missing_translations: translates missing keys viaclaude-sonnet-4-6, drops any result whose placeholders don't match the source, and appends under a/* Machine-translated */marker. The AI output is a stopgap — replaced by human translations on the next sync, and never uploaded to GlotPress.Testing instructions
This PR runs a
🌐 Upload strings (dry run)step: it regenerates the strings and runs the guardrail on this branch, but does not commit or push (dry_run:true). Watch that job to confirm regeneration + the guardrail work end-to-end in CI.source use-bot-for-git). Confirmwpmobilebotisn't blocked by trunk branch protection — otherwise we switch to an auto-merge PR.ANTHROPIC_API_KEYmust be present in the CI environment for the backfill.Related