Skip to content

Add Japanese (ja) locale: translated docs, translation pipeline fixes, UI strings - #325

Merged
zoltan-baba merged 70 commits into
mainfrom
ja-translation-test
Oct 7, 2026
Merged

zoltan-baba merged 70 commits into
mainfrom
ja-translation-test

Conversation

@zoltan-baba

Copy link
Copy Markdown
Collaborator

Summary

Adds the Japanese locale for the docs and updates the translation pipeline so new English changes translate correctly on their own. Nothing in docs/ or src/partials/ changes; English content is untouched.

Translated content (i18n/ja/)

  • 451 pages and 45 shared partials across Bitrise CI, Platform, Release Management, Build Hub, RDE, Insights and Build Cache, plus the changelog (translated once, shared).
  • Frontmatter titles/descriptions and hub-page text are translated.
  • Sidebar labels, navbar, "See also", breadcrumbs and search placeholders are translated.
  • Generated API reference docs are intentionally not translated.

Pipeline (.github/scripts/translate_docs.py and helpers)

  • Every translated heading keeps its English {#id}, so anchor links still work (scripts/heading_ids.py). A mid-line anchor is moved to the end of the heading.
  • Frontmatter and JSX hub-page strings are translated (scripts/translatable_strings.py).
  • Partials are translated first and Japanese pages import the Japanese copy.
  • Fix for bold text that ends in italic (***), which broke MDX.
  • A page whose English only changed in whitespace is not re-translated, and each run prints a plan line first.
  • A warning appears when the model returns a heading untranslated.
  • New scripts/translate_ui_strings.py plus a workflow step translate new sidebar labels and UI strings, using localization/ja-ui-strings.yaml.
  • Terminology: one rendering for AI agent, product names and warm pool stay in English.

Site code

  • docusaurus.config.ts: list-context partials expand from the Japanese copy under /ja/.
  • Hardcoded UI strings (navbar search, "See also", breadcrumbs, portal page) now go through translate().

Not verified

  • The pipeline has not run against the real API or in CI. All translations here came from Claude subagents with the same prompt. The workflow stays off until ANTHROPIC_API_KEY exists. I'd run it on a small test PR first.
  • No native-speaker review of the Japanese text.

Testing

  • Unit tests for the new and changed scripts pass (scripts/test_*.py).
  • npm run build passes for both locales. The 5 broken anchors per locale come from main and are the same in English.
  • scripts/heading_ids.py --check is clean.
  • The translated site was checked in a local build and served preview, with language switching.
  • Search and the cookie banner only work in production builds, so neither was tested locally.

Known gaps

  • A heading that is only partly English is not detected.
  • JSX hub strings only translate when each prop sits on its own line.
  • A broken link such as a doubled ](](url) is not detected; one case was fixed by hand.

🤖 Generated with Claude Code

zoltan-baba and others added 30 commits September 22, 2026 17:41
Disposable benchmark run replicating .github/scripts/translate_docs.py's
mask/translate/verify pipeline (masking + system prompt taken verbatim
from the production script) to measure time and token cost of translating
an untranslated docs section. 14/15 newly-translated pages passed the
script's own placeholder-token verification; getting-started-with-ios-projects.mdx
failed verification (duplicated token) and is intentionally left out.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Same disposable benchmark as the Getting started run: replicates
.github/scripts/translate_docs.py's mask/translate/verify pipeline
(masking + system prompt taken verbatim from the production script).
28/29 pages passed the script's own placeholder-token verification;
step-bundles.mdx failed (missing p111, duplicated p109) and is
intentionally left out, matching what a production retry-then-skip
would do.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Same disposable benchmark as prior sections: replicates
.github/scripts/translate_docs.py's mask/translate/verify pipeline.
18/18 pages passed the script's own placeholder-token verification.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Previous attempt dropped one placeholder token and duplicated another,
failing verification. Retried with explicit token-count self-check
instructions; all 260 tokens now match exactly.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Previous attempt duplicated a placeholder token, failing verification.
Retried with explicit token-count self-check instructions; tokens now
match exactly. Getting started section is now 16/16.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Same disposable benchmark as prior sections: replicates
.github/scripts/translate_docs.py's mask/translate/verify pipeline.
32/32 pages passed the script's own placeholder-token verification
on the first attempt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Same disposable benchmark as prior sections. 11/11 pages passed the
production script's placeholder-token verification on the first attempt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Same disposable benchmark as prior sections. 15/15 pages passed the
production script's placeholder-token verification on the first attempt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Same disposable benchmark as prior sections. 20/20 pages passed the
production script's placeholder-token verification on the first attempt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Same disposable benchmark as prior sections. 15/15 pages passed the
production script's placeholder-token verification on the first attempt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Same disposable benchmark as prior sections. 6/6 pages passed the
production script's placeholder-token verification on the first attempt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Same disposable benchmark as prior sections. 10/10 pages passed the
production script's placeholder-token verification on the first attempt,
including a 27k-char / 874-token configuration-yaml-reference.mdx that
self-corrected two dropped and one duplicated token before writing.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Same disposable benchmark as prior sections. 14/14 pages passed the
production script's placeholder-token verification on the first attempt.

This completes JA translation coverage for all 11 Bitrise CI navigation
sections in this disposable benchmark worktree.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Same disposable benchmark as the Bitrise CI run: replicates
.github/scripts/translate_docs.py's mask/translate/verify pipeline.
4/4 pages passed the production script's placeholder-token verification.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Same disposable benchmark as the Bitrise CI run: replicates
.github/scripts/translate_docs.py's mask/translate/verify pipeline.
19/19 pages passed the production script's placeholder-token
verification (one page self-corrected a duplicated token before
writing).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Same disposable benchmark as prior sections. 14/14 pages passed the
production script's placeholder-token verification on the first attempt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Same disposable benchmark as prior sections. 9/9 pages passed the
production script's placeholder-token verification on the first attempt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Same disposable benchmark as prior sections. 9/9 pages passed the
production script's placeholder-token verification (one page
self-corrected a token mix-up before writing).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Same disposable benchmark as prior sections. 18/18 pages passed the
production script's placeholder-token verification on the first attempt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Same disposable benchmark as prior sections. 35/35 pages passed the
production script's placeholder-token verification on the first attempt,
including two pure-token stub pages copied through unchanged.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Ran the production translate_docs.py mask/verify/unmask pipeline
manually against Claude subagents (no local ANTHROPIC_API_KEY) to
translate all 13 pages under docs/bitrise-platform/ai/.

13/13 pages passed token verification on first attempt, no retries
needed. Bitrise Platform hub is now 8/8 sections translated
(121/121 pages).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
1/1 page passed token verification on first attempt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
6/6 pages passed token verification on first attempt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…rtifacts

Apps section: 6/6 pages passed token verification on first attempt.
Installable artifacts (standalone page): 1/1 page passed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…tion

2/2 pages passed token verification on first attempt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
16/16 pages passed token verification on first attempt (2 top-level
pages + configuring-a-release/ 6 pages + managing-the-release-process/
8 pages).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
1/1 page passed token verification on first attempt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…-with-codepush

1/1 page passed token verification on first attempt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ates-with-bitrise-ci

1/1 page passed token verification on first attempt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…your-app-for-codepush

1/1 page passed token verification on first attempt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
zoltan-baba and others added 20 commits October 2, 2026 14:14
The eight changelog pages are thin wrappers around the shared
src/partials/changelog-content.mdx. Translate that partial once into
i18n/ja/partials/changelog-content.mdx (531/531 tokens verified; 70
headings, 61 heading ids, 61 time tags and 60 link targets match the
English file) and translate the wrapper intro sentence once. All eight
ja wrappers reuse both and import the Japanese partial.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Translate every reusable partial under src/partials/ (the changelog one
was done earlier) into i18n/ja/partials/. 44/44 passed token
verification; one needed an in-batch fix. Structure matches the English
originals for code fences, admonitions, links, headings, imports and
list items. One doubled "](" in a link was repaired by hand.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Rewrite 189 imports in 141 translated pages from @site/src/partials/
to @site/i18n/ja/partials/. Only the import lines change.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The markdown preprocessor splices list-style partial references from
src/partials before MDX parses a page, regardless of locale. Pass the
locale (derived from the page path under i18n/ja/) into the expansion so
Japanese pages read i18n/ja/partials and fall back to the English partial
when no translation exists. The cache is now keyed by locale.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The English source wraps an italic inside bold (**Key pair name - *required***).
The bold-to-<strong> promotion left "<strong>...*required</strong>*", which
fails MDX compilation. Use <strong>...<em>required</em></strong> instead
on the four affected lines.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Translating a heading changes the anchor Docusaurus generates from it, so
every #anchor link written against the English heading broke on the JA
site. Add scripts/heading_ids.py, which pairs English and Japanese
headings by position and gives each Japanese heading its English id as an
explicit {#id} (skipping fenced code, honouring existing ids, numbering
duplicates the way github-slugger does). translate_docs.py now calls it on
every page it writes; the module also runs standalone (--check / --write)
to repair existing pages.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Applies scripts/heading_ids.py --write: 1484 headings across 310 files
gain an explicit {#id}. Only heading lines change. Broken anchors on the
JA build drop from 197 pages to 2, the same two that are already broken on
the English build (glossary#custom-role).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The home page had every string hardcoded in English, so the JA site showed
an English landing page. Wrap its 49 strings (hero, tagline, search
placeholder, page title, seven product cards with descriptions and link
labels, "View all") in translate() with stable portal.* ids, keeping the
English text as the default message, and add the Japanese to
i18n/ja/code.json. Product names stay in Latin script; common terms follow
the existing site renderings.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Three gaps that would have undone the JA work on the next real run:

- Partials: translate src/partials/ into i18n/ja/partials/ like pages (new
  --partials-* options, route() for destinations, partials processed before
  pages). The workflow now triggers on and diffs src/partials too, and deletes
  or renames follow the same routing.
- Imports: repoint a translated page's @site/src/partials imports at the
  translated partial when it exists, so JA pages never render the English one.
- Bold ending in italic (**text *italic***) no longer leaves a stranded
  asterisk that fails MDX compilation.

Add stdlib unit tests, including an end-to-end run of main() with only the
model call faked, and a contributor-guide note on translated partials.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Brings the English docs, partials, specs and tooling up to date with main.
The JA pages and partials translated from the earlier English are now
stale where main changed them; they are re-translated in follow-up commits.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- ja-preferred-translations.yaml: one fixed rendering each for "AI agent"
  (AIエージェント), "AI coding agent" (AIコーディングエージェント),
  "coding agent" and "AI assistant", with no space inside the compound.
- "warm pool" is a UI term and stays in English: add it (all case and plural
  forms) to the builder's curated concepts and the generated glossary so it is
  masked and cannot be translated.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Re-translate or translate the pages and partials that changed or were added
on main since the translation snapshot: new CLI pages, warm pools, per-project
cache scoping, the changelog partial, and the largest edited pages. All 27
passed token verification; heading ids, partial imports and bold handling
come from the pipeline code.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- Translate or re-translate the remaining 39 files (all passed token
  verification with no retries): the CLI, RDE, Build Cache, Release
  Management and Platform pages that changed on main.
- Sync the frontmatter of the 5 pages whose only change was sidebar_position.
- Patch the 10 URL/markup-only edits (GlossTerm moved out of inline code,
  link targets) directly into their JA pages.
- Normalize "AI エージェント" / "AI コーディングエージェント" spacing to
  AIエージェント / AIコーディングエージェント everywhere.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
current.json gains 165 sidebar entries (286 -> 451) for the pages, categories
and links added on main, including the CLI pages and the new "Command
reference" link. Nothing removed; no existing message changed. code.json is
rewritten by the tool without the free-text descriptions on the portal
entries; all messages are identical.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ish changes

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…panese pages

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…and workflow step

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…heading untranslated

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A translation containing a quote would have broken the attribute.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 5, 2026

Copy link
Copy Markdown

@ilanazholobovsky ilanazholobovsky left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the JA locale and the translation pipeline end to end. The structure is in great shape: all 1,834 heading anchors match English, no code blocks changed, docs/ untouched, and the ja build passes. Really solid work.

I found a few defects, most of them caused by how the pipeline protects English terms, and I've opened two follow-up PRs into this branch:

#335: Repair structural defects in the JA docs (merge first)

  • Broken link markup on 14 pages. Root cause: relative_link_target masked the ] together with the target, so the model saw [text⟦p7⟧ with no closing bracket. 33 of 3,189 internal links broke, against 0 of 1,143 external ones.
  • 227 UI labels and Step names half-translated in bold (e.g. Newタスク), restored to the exact English.
  • 324 lost spaces between English words (iOScode signing), restored.
  • 2 stale sidebar_position values; "code signing" kept in English.

#338: Harden the pipeline against structural breakage (stacked on #335)

  • Fixes the masking at the cause, and adds structure_issues() next to verify_tokens in the retry loop and in CI. 30 problems at this branch's head, 0 after #335.
  • Narrows the list-item rule in nt_terms.context_allows(), which was freezing phrases like "Log in" mid-sentence.
  • Includes your fix/translate-ja-docs-diff-range commit (authorship kept), plus a few workflow and change-detection fixes.

Both PRs only make structural and keep-English changes, with no new Japanese wording. Each commit can be dropped on its own. Decisions that are yours to make are listed in #338 under "Decisions for Zoli".

Not covered: #331's changelog changes. Once it merges, the pipeline re-translates the changelog automatically, and I'll open a small PR to make its filter labels translatable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants