Add Japanese localization pipeline: NT-tag do-not-translate mechanism, translation scripts, and ja locale wiring - #140
Merged
Merged
Conversation
zoltan-baba
requested review from
aorcsik,
ilanazholobovsky and
matenadasdi
as code owners
July 23, 2026 15:27
zoltan-baba
marked this pull request as draft
July 23, 2026 15:29
zoltan-baba
added a commit
that referenced
this pull request
Jul 23, 2026
- translate_docs.py: deterministically rewrite **<NT>...</NT>** to <strong><NT>...</NT></strong> after unmasking. Markdown ** emphasis depends on whitespace/punctuation next to the delimiter to tell one ** pair from another; Japanese chains bold <NT> terms back-to-back with only a particle between them, which reliably breaks that disambiguation (verified against a real build: bold attached to the wrong span, a literal ** leaked into the page). <strong> sidesteps delimiter matching entirely. Ordinary bold with no <NT> inside is left untouched. - check-links-source.js: strip JSX/MDX tags before slugifying heading text. The NT-tagging pass wrapped terms inside some headings (e.g. "The <NT>Dashboards</NT> page"); the checker's slugify() had no rule for JSX, so the tag name survived as literal text and produced a mismatched slug for every such heading — 182 false "broken anchor" failures on PR #140's check-links job. The real Docusaurus build was never affected (its slugger already strips JSX); this only fixes the separate lightweight source-level checker. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…n/-prefix infra
Rebuilds ja-localization-full's tooling on top of main's now-merged
strip-en-prefix-urls PR, instead of merging the two histories directly:
that PR and this branch's NT-tagging commit both touched almost every
file under docs/ and src/partials/ for unrelated reasons (link-prefix
stripping vs. do-not-translate tagging), so a real merge produced 280+
conflicts. Content-bearing commits are cherry-picked as targeted patches
onto main's versions instead; superseded fixes (this branch's own navbar
/en/ regex, GlossTerm path, DocSidebar/DocBreadcrumbs hrefs) are dropped
in favor of main's better versions of the same fix.
Brings over:
- ja translation pipeline: .github/scripts/{build_ui_library,translate_docs}.py,
the ja-style-check/refresh-ui-library/translate-ja-docs workflows,
.textlintrc.yaml, localization/ (glossary, preferred translations,
translation guide, README).
- Locale-switch UI: navbar localeDropdown item in docusaurus.config.ts,
white-text CSS for it against the purple header (it would otherwise
render dark-on-dark), i18n/ja/'s UI-string scaffold.
- scripts/patch-api-info.js: disambiguates duplicate OpenAPI sidebar
labels, which broke `docusaurus write-translations` outright once a
second locale existed.
- scripts/check-links-source.js: strips JSX/MDX tags before slugifying
heading text, so a heading like "The <NT>Dashboards</NT> page" slugifies
the same as Docusaurus's real build-time slugger.
- src/components/NT + 'NT' added to docusaurus.config.ts's tag-escaping
preprocessor allowlist: the do-not-translate marker component itself,
not yet applied to any doc content (that's a separate change).
- scripts/add_notranslate_tags.py, the term-wrapping script this pipeline
runs — included here with a fix for a bug never caught before because it
was never rebased onto other real content changes: it wrapped terms
inside a heading's explicit anchor ID too (`{#workspace}` ->
`{#<NT>workspace</NT>}`), producing an invalid anchor. Fixed by excluding
`{#...}` spans the same way frontmatter/code/JSX attributes already are.
Still not run against docs content — that's the next commit.
- .claude/launch.json: a production-build-all-locales entry, since dev
mode only ever serves one locale at a time.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Bulk, mechanical rename of the 83 remaining plain-Markdown doc pages to .mdx — no content changes. Needed so scripts/add_notranslate_tags.py (reintroduced in the previous commit but not yet run) can wrap terms in these pages too: the <NT> marker it inserts is a JSX component, which .md files can't carry. Frontmatter `slug` values are untouched, so no URLs change and no redirects.json entries are needed. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Plain Markdown tolerates an unclosed <br>, but MDX parses it as JSX,
which requires a matching closing tag or a self-closing slash. Renaming
these two pages to .mdx in the previous commit surfaced the mismatch
("Unexpected closing tag </details>, expected corresponding closing tag
for <br>") and failed the build. Verified: a full build of both en and
ja locales now succeeds.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…generated docs scripts/patch-api-info.js gained duplicate-sidebar-label disambiguation in an earlier commit, but that only takes effect by actually running the script — it doesn't retroactively touch the already-generated API reference files committed to the repo. Without this, building the ja locale fails outright: "Download files" duplicated across codespaces-service-session-download and codespaces-service-session-download-file broke `docusaurus write-translations`'s sidebar translation keys. Ran `node scripts/patch-api-info.js` and committed the result; the next `npm run gen-api-docs` will reproduce the same output automatically. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This translated page predates main's strip-en-prefix-urls merge, so its internal links still carried the old hardcoded /en/ prefix. Under the new per-locale baseUrl, that resolved to broken /ja/en/... URLs — the same class of bug that PR fixed everywhere else. Fixed with the same tool: `python3 scripts/strip_en_prefix.py` (i18n/ is already in its scope). Verified: building the ja locale no longer logs any /ja/en/ link warnings. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Left over from before the src_root/dest_root path-mapping logic it's a fallback for existed. Every real call passes a docs/-relative path (from git diff output, --src-root defaults to "docs"), so this branch was unreachable and, if it ever were reached, would guess wrong under the current per-locale routing anyway (paths here are file paths, not URLs, but the string was still a leftover assumption worth not carrying forward). Raises loudly instead of guessing, matching this repo's convention elsewhere (see promote-root-static-files.js) of failing hard rather than drifting silently. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Ran `docusaurus write-translations --locale ja` to sync current.json with main's sidebar changes since this scaffold was last generated: two new RDE API sidebar entries (git provider integration get/update) and a stale /en/-prefixed description string for the API reference link, now bare. No other i18n JSON file changed — navbar, footer, and code.json scaffolds are already in sync. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
zoltan-baba
force-pushed
the
ja-localization-full
branch
from
August 18, 2026 13:27
4414c1a to
c01c3af
Compare
This was referenced Aug 18, 2026
Brings in the infrastructure that was split out of this PR and has since merged — #188 (the <NT> component, the 83 .md -> .mdx renames, the check-links-source.js anchor fix, the patch-api-info.js duplicate-label fix) and #189 (the MCP sync /en/ fix) — plus #187's docusaurus-plugin-llms bump. The overlapping work is identical on both sides, so it resolves without conflict. What remains unique to this branch is the translation pipeline, the localization glossary and guides, the i18n/ja content, and the locale switcher. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.
Summary
The Japanese localization pipeline: the scripts that generate the term glossary, tag protected terms in the docs source, and translate changed pages — plus the
jalocale content and the locale switcher.The infrastructure prep that used to live here has been split out and merged (#188, #189), and
mainis merged back in, so this branch is now purely additive: 19 files, +4,892 / −0, and up to date withmain.Pipeline
.github/scripts/build_ui_library.py— scans the product frontends + steplib + docs, emitsui_copy_library.jsonand the tiered do-not-translate glossary.scripts/add_notranslate_tags.py— reads that glossary and wraps protected terms in<NT>directly in the.mdxsource. Idempotent, and inserts its own import..github/scripts/translate_docs.py— mask → translate → unmask. Masks whole<NT>spans, code, URLs, env vars, filenames and MDX syntax before the model sees the text. JTF house-style system prompt, plus a preferred-translations map for terms that are translated. Front matter is split off and never sent, soslugcan't be touched. Auto-generated OpenAPI pages are excluded — they'd go stale on the next spec sync.translate-ja-docs.yml(translate changed pages on docs PRs),refresh-ui-library.yml(weekly glossary regeneration + re-tag),ja-style-check.yml+.textlintrc.yaml(JTF textlint).Locale content and switcher
i18n/ja/— theme strings (code.json, translated), sidebar labels (current.json, scaffolded but still English), and one fully translated pilot page.docusaurus.config.ts) plus the navbar text colour it needs to be readable on the purple header (src/css/custom.css).Docs
localization/README.mdandJA-TRANSLATION-GUIDE.md— how the pipeline fits together, with a LIVE/PROCESS/ROADMAP status legend.Open issues — read before merging
All re-verified against the merged tree.
No
<NT>tags are applied yet. The tagger has never been run against the tree: zero files underdocs/orsrc/partials/contain a tag, while a dry run reports 17,140 wraps across 499 files. Until that pass lands,translate_docs.pyhas nothing to mask beyond code, URLs and ALL-CAPS runs — measured on one real page, 99 occurrences of unambiguous protected terms (Bitrise ×18, Workspace ×13, Workflow ×6, Release Management ×5, …) are fully exposed to the model. The glossary is not a fallback: it is the tagger's term source and is never read at translation time.translate-ja-docs.ymlruns on every docs PR and auto-commits, so merging before the tagging pass turns on unprotected translation immediately. Deciding where that pass lands is the one thing blocking this PR from being safe to merge.translate_docs.pytruncates silently.max_tokens=8000with nostop_reasoncheck (line 179). Seven pages exceed 20KB, the largest is 44KB. A truncated response is written to disk and committed by the workflow with no signal. No retry or error handling either.ja-style-check.ymlis a no-op — and its green check here is misleading. Verified: textlint exits 0 with no output on.mdx, silently skipping unsupported extensions, and every page is.mdxnow. The same content as.mdreports 2 errors, both Docusaurus:::note[title]syntax tripping JTF rule4.3.2, so that rule needs disabling before MDX support is worth adding. It also has nocontinue-on-error, so despite being described as non-blocking it becomes a hard gate the moment it starts working.The weekly refresh will drop glossary tiers.
build_ui_library.pyemitsstep_names:, butadd_notranslate_tags.pyreadsstep_names_and_field_labels— and the generator emits nocode_literalsat all, which the tagger also reads.refresh-ui-library.ymlregenerates the glossary then re-runs the tagger and opens a PR, so the first scheduled run silently drops all 156 Step names and produces a mass-untagging PR that looks like a routine chore.Stale comments in the glossary. Line 13 still says
do_not_translateterms "are injected into the translation prompt as a hard rule", describing the design this PR replaced — reading the file top-down gives the wrong model of how protection works. Thepreferred_translations: {}stub at the bottom is also dead;ja-preferred-translations.yamlsupersedes it.Known gaps (by design, documented in
JA-TRANSLATION-GUIDE.md)src/partials/) aren't translated. They're inlined via JSX import, so a translated page still renders an English partial.titleanddescriptionstay English, so JA pages show English titles in nav and English social preview cards.current.jsonis scaffolded but still English, and nothing in the pipeline translates it.ja-preferred-translations.yamlseed values need a fluent Japanese reviewer before being treated as authoritative.static/_headersstill noindexes/ja/*. Correct while one page of ~440 is translated, but main's commit 3444eb4 asks for the rule to be revisited here — worth an explicit decision and a drop criterion.Test plan
npm run build) succeeds for bothenandja.bitrise-ci/getting-started/getting-started) translated through the full mask/translate/unmask pipeline and verified rendering in a served production build.mainmerged in;check-links-source,check-partials-sourceandcheck-generated-partialsall clean on the merged tree.refresh-ui-library.ymlrun.🤖 Generated with Claude Code