10c14f0c12
* Translate docs into zh-CN, zh-TW, es (Mintlify i18n)
- docs.json navigation restructured into navigation.languages (en default
+ zh / zh-TW / es), group/tab labels translated per locale, page paths
prefixed with the locale dir
- 79 English pages × 3 locales = 237 translated .mdx under docs/{zh,zh-TW,es}/,
mirroring the English tree (scripts/build-docs-langs.py regenerates the nav)
- Preserved verbatim: code fences, MDX component/prop names, imports, URLs,
API/SQL/env names, brand names, openapi API Reference (shared), and the
data-for-agents blocks (English on purpose)
- Adds scripts/check-docs-i18n-parity.sh and documents the whole flow in the
insforge-dev docs skill (DOCS_I18N.md, mirrored to .claude/.codex)
Verified: parity check green (79×3), code-fence counts byte-match source on
spot checks, docs.json valid, zh-TW uses Taiwan vocabulary.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011pR7GMy3FRotoNgKZHSF2Q
* Fix kotlin-sdk-installation snippet: translate body, drop bogus frontmatter
A sub-delegated translation had left this snippet's prose English and added
frontmatter the source snippet doesn't have. Body now translated in all
three locales; structure matches source (no frontmatter); code fences
byte-match.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011pR7GMy3FRotoNgKZHSF2Q
* Address docs review: re-translate truncated pages, translate .md deploy guides, harden tooling
Fixes John-bot's two Critical findings on #1693:
- Content loss: re-translated 11 pages the haiku pass had truncated
(partnership was 720 lines/68 fences cut to 81 lines/0; also mcp-setup,
oauth-server, rest/database, realtime, razorpay, sites, webscraper,
nuxt/vue/svelte). Redone with a stronger model; each verified at exact
fence parity and >=85% line parity vs source. Also caught hallucinated
Partner Program content and literal placeholder lines from the first pass.
- Dead nav links: translated the 5 .md deployment guides (aws, azure, gcp,
containarium, security-guide) into all 3 locales; nav now prefixes them
to real files.
- Tooling (findings 3/4): parity check now validates against docs.json nav
(covers .md, catches dangling links); build-docs-langs.py is idempotent
(derives tabs from the en entry, skips prefixing pages with no translated
file) and its label map is externalized.
Verified: nav parity green (78 pages x 4 langs resolve), strict fence+line
audit clean across all nav pages.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011pR7GMy3FRotoNgKZHSF2Q
* Fix docs CI: prettier-format locale files, exclude them from Vale spellcheck
- Ran prettier --write over all translated .md/.mdx + docs.json (lint-and-format
was failing on formatting); fence parity re-verified intact.
- .vale.ini: disable Vale.Spelling for zh/zh-TW/es trees — the English speller
flags every translated word as a misspelling (that was the vale-spellcheck
failure). Localized prose is validated by native review instead.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011pR7GMy3FRotoNgKZHSF2Q
* Force-add the .agents/.claude DOCS_I18N.md skill mirrors
They're gitignored (global ~/.gitignore ignores .claude; the .agents copy
was missed), so only the .codex copy had committed — sync-skills --check
failed in CI seeing the canonical .agents copy absent. Existing skill files
are force-added the same way. All three mirrors now tracked and in sync.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011pR7GMy3FRotoNgKZHSF2Q
* Broaden Vale spellcheck exclusion to repo-root-prefixed locale globs
The hosted Mintlify vale-spellcheck kept failing though the docs/-relative
disable works locally — likely runs vale from the repo root, where zh/**
doesn't match docs/zh/**. Add docs/{zh,zh-TW,es}/** variants so the
Vale.Spelling=NO disable applies regardless of working directory.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011pR7GMy3FRotoNgKZHSF2Q
* Address docs re-review: drop dead snippet copies, strengthen parity, utf-8
- Dropped docs/{zh,zh-TW,es}/snippets/* — pages import snippets by absolute
path (/snippets/x.mdx → always English), so translated copies were dead
files. Snippet includes stay English (documented in DOCS_I18N.md).
- check-docs-i18n-parity.sh now truly verifies coverage: every nav path
resolves, every non-en nav entry is locale-prefixed (catches English
fallback), and every English nav page has all 3 locale translations.
- build-docs-langs.py reads/writes docs.json with explicit encoding='utf-8'
(safe under LC_ALL=C) and uses with-open handles.
Locale codes (zh / zh-TW) kept: Mintlify's internationalization guide lists
zh, zh-Hans, zh-CN for Simplified and zh-Hant, zh-TW for Traditional as
accepted — both our codes are valid.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011pR7GMy3FRotoNgKZHSF2Q
* Rename Traditional Chinese locale zh-TW -> zh-Hant (Mintlify schema requirement)
Ran Mintlify's own CLI (`mint dev`) to settle the locale-code question John-bot
raised: the docs.json schema enum is en|cn|zh|zh-Hans|zh-Hant|es|... — `zh` is
valid for Simplified, but `zh-TW` is REJECTED; Traditional Chinese must be
`zh-Hant`. (The Mintlify web i18n guide that listed zh-TW as accepted is wrong;
the CLI schema is authoritative. John-bot was right to flag it.)
- Renamed docs/zh-TW/ -> docs/zh-Hant/ (80 files) via git mv
- Updated docs.json nav, docs-langs-labels.json, build-docs-langs.py LOCALES,
check-docs-i18n-parity.sh, .vale.ini globs, and DOCS_I18N.md
- `mint dev` now passes config validation (previously errored on zh-TW enum);
parity green; broken-links clean in locale trees
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011pR7GMy3FRotoNgKZHSF2Q
* docs skill: fix stray zh-TW->zh-Hant in fan-out note
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011pR7GMy3FRotoNgKZHSF2Q
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
63 lines
2.2 KiB
Python
63 lines
2.2 KiB
Python
#!/usr/bin/env python3
|
|
"""Regenerate docs.json navigation.languages from the English (default) tree.
|
|
|
|
Idempotent: reads tabs from navigation.tabs if present (first run) or from the
|
|
en/default language entry (subsequent runs), then rebuilds all locale entries.
|
|
"""
|
|
import json, copy, os
|
|
|
|
DOCS = os.path.join(os.path.dirname(__file__), '..', 'docs')
|
|
CFG = os.path.join(DOCS, 'docs.json')
|
|
LOCALES = ['zh', 'zh-Hant', 'es']
|
|
|
|
d = json.load(open(CFG, encoding='utf-8'))
|
|
nav = d['navigation']
|
|
if 'tabs' in nav:
|
|
base_tabs = nav['tabs']
|
|
glob = nav.get('global')
|
|
else:
|
|
langs = nav['languages']
|
|
en = next(l for l in langs if l.get('default') or l['language'] == 'en')
|
|
# strip the en/ prefix back off (en uses bare paths already, so just copy)
|
|
base_tabs = copy.deepcopy(en['tabs'])
|
|
glob = nav.get('global')
|
|
|
|
LABELS = json.load(open(os.path.join(os.path.dirname(__file__), 'docs-langs-labels.json'), encoding='utf-8'))
|
|
|
|
def resolves(path):
|
|
p = os.path.join(DOCS, path)
|
|
return os.path.exists(p + '.mdx') or os.path.exists(p + '.md')
|
|
|
|
def transform(node, loc):
|
|
if isinstance(node, str):
|
|
prefixed = f"{loc}/{node}"
|
|
# Skip prefixing a page that has no translated file yet (avoid dead nav
|
|
# links); fall back to the English page so the entry still resolves.
|
|
return prefixed if resolves(prefixed) else node
|
|
if isinstance(node, list):
|
|
return [transform(x, loc) for x in node]
|
|
if isinstance(node, dict):
|
|
out = {}
|
|
for k, v in node.items():
|
|
if k in ('tab', 'group'):
|
|
out[k] = LABELS[loc].get(v, v)
|
|
elif k in ('pages', 'groups'):
|
|
out[k] = [transform(x, loc) for x in v]
|
|
else:
|
|
out[k] = copy.deepcopy(v)
|
|
return out
|
|
return copy.deepcopy(node)
|
|
|
|
languages = [{'language': 'en', 'default': True, 'tabs': copy.deepcopy(base_tabs)}]
|
|
for loc in LOCALES:
|
|
languages.append({'language': loc, 'tabs': [transform(t, loc) for t in base_tabs]})
|
|
|
|
nav_out = {'languages': languages}
|
|
if glob is not None:
|
|
nav_out['global'] = glob
|
|
d['navigation'] = nav_out
|
|
with open(CFG, 'w', encoding='utf-8') as fh:
|
|
json.dump(d, fh, ensure_ascii=False, indent=2)
|
|
fh.write('\n')
|
|
print(f"docs.json rebuilt: {len(languages)} languages")
|