JA localization prep: <NT> marker, .mdx renames, and duplicate API sidebar labels - #188
Merged
Conversation
scripts/add_notranslate_tags.py globs docs/**/*.mdx and src/partials/**/*.mdx only, so the 83 pages still authored as plain .md would be silently skipped by the do-not-translate tagging pass. Rename them now, on their own, so the extension change is reviewable in isolation and any MDX parse fallout is attributable to this commit rather than buried in a 17k-line tagging diff. Content is byte-identical; only the extension moves. Routes are unaffected (every page carries an explicit `slug:` and Docusaurus strips both extensions), so no redirects are needed. Note the real behavior change: docusaurus.config.ts's markdown.preprocessor is gated on `.mdx`, so these pages now go through expandListPartials and the JSX tag escaper, and are parsed as MDX rather than CommonMark. Co-Authored-By: Claude Opus 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 in the previous commit surfaces the mismatch ("Unexpected closing tag
</details>, expected corresponding closing tag for <br>") and fails the
build.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`NT` wraps product names, UI labels, Step names, and other terms that must
stay in English in every locale. It renders a bare `<span translate="no">`
— no lookup, no styling — which also stops browser/OS auto-translate from
touching the content.
Nothing is tagged yet: this lands the component, its allow-list entry, and
the checker fix that the tagging pass depends on, so the tagging diff itself
(~17k wraps across ~500 files) can be reviewed on its own against a repo
that already builds with `NT` in place.
Two supporting changes:
- docusaurus.config.ts's preprocessor escapes any JSX tag not in ALLOWED, so
without `NT` on that list every `<NT>` would render as literal escaped
text instead of the component.
- scripts/check-links-source.js's heading slugifier now strips JSX/MDX tags
before slugifying. Docusaurus's real slugger renders a heading's element
tree to plain text first, so `## The <NT>Dashboards</NT> page` anchors at
`the-dashboards-page`. Without the strip, the tag delimiters are dropped
by the punctuation pass but the tag *name* survives as word characters
("the-ntdashboardsnt-page"), and the checker would flag every heading with
a tag in it as a broken anchor.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Two different operations can share an identical OpenAPI `summary`. Docusaurus
derives i18n translation keys from sidebar labels, so a duplicate breaks
`docusaurus write-translations` outright — which is how these surfaced.
Three pairs exist today:
organization-machine-type-update / user-machine-type-update
both "Migrate machine types" -> qualified with (organization) / (user)
codespaces-service-session-download
duplicate of SessionDownloadFile, which supersedes it -> "Download files
(deprecated)", matching the operation's own description
Fixing this upstream isn't an option here: api/bitrise-ci.json and
api/bitrise-rde.json are themselves synced/generated, and the plugin
regenerates the .api.mdx files from them on every run. So the overrides go in
scripts/patch-api-info.js alongside the existing displayed_sidebar and
license patches, as an explicit keyed map rather than an auto-disambiguation
heuristic — extend it if a future spec sync introduces another duplicate.
Both the page frontmatter and the separate `label` in the generated
sidebar.ts need patching; the sidebar.ts entry is what Docusaurus actually
reads, so patching only the page leaves the duplicate alive for i18n.
Verified idempotent: re-running `node scripts/patch-api-info.js` over the
patched tree produces no diff.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
scripts/sync_mcp_docs.py wrote each page under the source repo's own filename, which is always .md. Now that these eight pages exist here as .mdx, the next sync run would have written a second .md copy alongside each one — two files carrying the same explicit `slug`, which Docusaurus rejects as a duplicate route. Derive the destination from the stem and pin the extension to .mdx instead. Also self-close bare void tags (`<br>` -> `<br/>`) at sync time. The source repo is plain Markdown, where an unclosed `<br>` is fine; as .mdx it is JSX and fails the build. The two occurrences were fixed by hand two commits ago, but these files are generated — CLAUDE.md's rule is not to hand-edit them — so the fix only holds if the sync applies it. Verified against a real sync run: the transform is idempotent, reapplies both `<br/>`, and no stray .md files appear. Unrelated pre-existing bug, left for its own PR: rewrite_internal_links() still emits `/en/`-prefixed targets, so a sync run reintroduces eight links that 51f565b stripped repo-wide. Those break under any non-default locale (`/ja/en/...`). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
matenadasdi
requested review from
aorcsik,
ilanazholobovsky and
zoltan-baba
as code owners
August 18, 2026 14:16
The previous guidance said to use .md when a page has no JSX, and to rename only when adding a partial, <Tabs>, or <GlossTerm>. That's now backwards: a <NT> do-not-translate wrapper is JSX, so a .md page physically cannot carry one, and the tagging pass globs **/*.mdx — a stray .md page is skipped with no error, leaving its product names and UI labels to be machine-translated. Record the rule where the rename established it, plus the two consequences that turned up as real build failures (MDX parsing, and the preprocessor being gated on the extension), and the fact that scripts writing pages have to pin .mdx as well. Also fixes the stale `index.md` topichead reference, the `.md`/`.mdx` in the description check, and the layout table's page row. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
zoltan-baba
approved these changes
Aug 18, 2026
This was referenced Aug 18, 2026
matenadasdi
added a commit
that referenced
this pull request
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.
Infrastructure prep split out of #140, so the risky parts of that PR can be reviewed on their own. No user-visible change except three corrected API reference sidebar labels.
#140 bundles three separable things: infrastructure, the translation pipeline (scripts + 3 workflows), and content (
i18n/ja/+ one translated page). This is the first — the pieces that are inert on their own, are prerequisites for everything else, and carry the build risk worth isolating.What's here
<NT>do-not-translate marker (src/components/NT) — renders a bare<span translate="no">. Nothing is tagged yet; this lands the component so the tagging pass (~17k wraps across ~500 files) can be reviewed on its own, against a repo that already builds withNTin place.Two supporting changes it depends on:
NTadded toALLOWEDindocusaurus.config.ts. The preprocessor escapes any JSX tag not on that list, so without this every<NT>would render as literal escaped text.scripts/check-links-source.jsnow strips JSX/MDX tags before slugifying headings. Docusaurus renders a heading's element tree to plain text first, so## The <NT>Dashboards</NT> pageanchors atthe-dashboards-page. Without the strip, the tag delimiters are dropped by the punctuation pass but the tag name survives as word characters (the-ntdashboardsnt-page), and the checker would flag every tagged heading as a broken anchor.83
.md→.mdxrenames.add_notranslate_tags.pyglobs**/*.mdxonly, so these pages would be silently skipped by the tagging pass. Content is byte-identical; routes are unaffected (every page carries an explicitslug:), so no redirects are needed. The real change is thatdocusaurus.config.ts's preprocessor is gated on.mdx, so these pages now go throughexpandListPartialsand the JSX escaper and are parsed as MDX rather than CommonMark. That surfaced two unclosed<br>tags, fixed in a follow-up commit.MCP sync kept in step (
scripts/sync_mcp_docs.py). Two problems the rename creates, both fixed at the source since these files are generated and hand-edits don't survive a sync:.mdfilename. With those eight pages now.mdx, the next sync would write a second.mdcopy of each — two files with the same explicitslug, a duplicate route.<br>→<br/>is now applied as a sync-time transform, so the fix above isn't reverted by the next run.Duplicate API sidebar labels (
scripts/patch-api-info.js). Three generated operations share asummarywith another operation. Docusaurus derives i18n translation keys from sidebar labels, so a duplicate breaksdocusaurus write-translationsoutright — which is how these surfaced. The specs are themselves synced/generated and the plugin regenerates the pages on every run, so the fix goes in the existing patch script as an explicit keyed map. Both the page frontmatter and the separatelabelin the generatedsidebar.tsneed patching;sidebar.tsis what Docusaurus actually reads.CLAUDE.mdrecords the rule. The old guidance — use.mdwhen a page has no JSX, rename only when adding a partial or<Tabs>— is now backwards:<NT>is JSX, so a.mdpage physically cannot carry one, and the tagging pass globs**/*.mdx, meaning a stray.mdpage is skipped with no error. Rewritten as an.mdx-only rule, with the two consequences that turned up as real build failures here (MDX parsing, and the preprocessor being gated on the extension) and the requirement that scripts writing pages pin the extension too. Also fixes the staleindex.mdtopichead reference and the layout table's page row.Verified
npm run build— green for bothenandja. Only warnings are pre-existing and unrelated (two unreadable_paligoSVGs,docusaurus-plugin-llmsdescription length).node scripts/check-links-source.js— clean, 631 files.node scripts/patch-api-info.jsre-run over the patched tree — no diff, idempotent.python3 scripts/sync_mcp_docs.pyagainst a real sync — reapplies both<br/>, produces no stray.mdfiles.<NT>end-to-end. Temporarily tagged one page in the four placements most likely to break, built, then reverted. All render as<span translate="no">, none leak as escaped literals, and — the one that mattered — a heading anchor is unchanged:## Changing your <NT>project settings</NT>still emitsid="changing-your-project-settings", confirming thecheck-links-source.jsfix matches Docusaurus's real behavior.:::note[First <NT>workspace</NT>]) ✅<GlossTerm>✅Deliberately not here
/ja/discoverable while ~440 of its pages are still English. Both belong with the locale-switch work.localization/,i18n/ja/. The pipeline PR.Follow-up found while testing (out of scope, separate PR)
sync_mcp_docs.py'srewrite_internal_links()still emits/en/-prefixed targets, so a sync run reintroduces eight links that 51f565b stripped repo-wide. Those break under any non-default locale (/ja/en/...). Pre-existing onmainand unrelated to the rename, so left alone here.🤖 Generated with Claude Code