diff --git a/.cursor/rules/localization-workflow.mdc b/.cursor/rules/localization-workflow.mdc index 6cba1e6..08be1c0 100644 --- a/.cursor/rules/localization-workflow.mdc +++ b/.cursor/rules/localization-workflow.mdc @@ -9,8 +9,8 @@ alwaysApply: true - Keep all locale navigation in `docs.json` under `navigation.languages`; do not reintroduce `navigation.global` or top-level `navbar`. - Keep SEO metatags in English unless explicitly requested otherwise. - Do not translate code snippets, inline code, URLs, route slugs, or API identifiers. -- Shared media lives under repo-root `assets/`. Default-language pages are at repo-root section paths (for example `
/.mdx`) and targets are under locale directories (for example `es/
/.mdx`), so relative `src` paths must account for each file depth. `scripts/localize-internal-links.mjs` rewrites markdown `](/...)` and JSX `href="/..."` only: for target locales, bare paths get that locale prefix and paths prefixed with another locale are re-prefixed to the active locale; for source/default processing, locale prefixes are stripped back to root paths. It does not change media `src` or snippet imports. -- `scripts/localize-component-imports.mjs` rewrites MDX import paths that reference `/components/*.jsx` so each locale page imports its own locale components (for whichever locale is being processed). +- Shared media lives under repo-root `assets/`. Default-language pages are at repo-root section paths (for example `
/.mdx`) and targets are under locale directories (for example `es/
/.mdx`), so relative `src` paths need one more `../` under each locale segment than in English. `scripts/localize-internal-links.mjs` rewrites markdown `](/...)` and JSX `href="/..."` only (absolute navigation paths). Relative repo-root `assets/` `src` and MDX `import` paths are normalized by `scripts/localize-mdx-paths.mjs` after Lingo. +- `scripts/localize-mdx-paths.mjs` rewrites: `/components/*.jsx` for the active locale; `from ".../snippets/..."`; and JSX `src=".../assets/..."` so `../` depth matches the file’s path. Run after Lingo in `translate:generate` and translate-on-main; CI checks via `translate:localize-mdx-paths:check`. - Shared MDX snippets live under repo-root `snippets/` (not per-locale). Import with relative paths from each page; do not add shared MDX snippets to Lingo `i18n.json` buckets unless you intend to translate them. - Locale-aware React components that can contain text live under `components/*.jsx` for default language and `/components/*.jsx` for targets, and are manually maintained per locale (do not add them to Lingo `i18n.json` buckets; do not keep these in shared `snippets/`). - Keep a **single** OpenAPI document at repo-root `openapi.yml` (not under `en/` or `es/`). Endpoint and webhook MDX must use Mintlify’s form `openapi: openapi.yml ` or `openapi: openapi.yml webhook `. Do not translate the `openapi:` line. diff --git a/.github/workflows/translate-on-main.yml b/.github/workflows/translate-on-main.yml index 956e849..f2e1b03 100644 --- a/.github/workflows/translate-on-main.yml +++ b/.github/workflows/translate-on-main.yml @@ -70,8 +70,8 @@ jobs: node scripts/translate-docs-json.mjs --target "$locale" echo "Localizing internal links for $locale" node scripts/localize-internal-links.mjs --target "$locale" - echo "Localizing component imports for $locale" - node scripts/localize-component-imports.mjs --target "$locale" + echo "Localizing MDX paths (components, snippets, assets) for $locale" + node scripts/localize-mdx-paths.mjs --target "$locale" done - name: Sync Mintlify heading anchors diff --git a/.github/workflows/validate-translations.yml b/.github/workflows/validate-translations.yml index d78c7bd..cb9ce9c 100644 --- a/.github/workflows/validate-translations.yml +++ b/.github/workflows/validate-translations.yml @@ -54,8 +54,8 @@ jobs: - name: Ensure internal links are locale-localized run: npm run translate:localize-links:check - - name: Ensure component imports are locale-localized - run: npm run translate:localize-component-imports:check + - name: Ensure localized MDX paths are correct + run: npm run translate:localize-mdx-paths:check - name: Ensure fragile link fragments are not used run: npm run translate:validate-links diff --git a/README.md b/README.md index 7e4e8d0..e00077b 100644 --- a/README.md +++ b/README.md @@ -59,11 +59,11 @@ Notes: - `lingo/glossary.csv`: Terms that must stay fixed or use specific translations. - `lingo/brand-voice.md`: Single brand voice used for all locales. - `scripts/translate-docs-json.mjs`: Translates language-specific `docs.json` navigation labels directly in the source-of-truth `docs.json`. Prefer `npm run translate:docs-json -- --target `. -- `scripts/localize-internal-links.mjs`: Rewrites internal absolute **navigation** links in each locale’s MDX for whatever locale is being processed (`--target`, `--all`, or default targets): bare paths get that locale’s prefix (e.g. `/platform/points` → `/es/platform/points` when processing `es/`), and any path already prefixed with **another** locale from `i18n.json` (`en`, `es`, future `fr`, etc.) is re-prefixed to the active locale (so `/en/...` or stale `/es/...` on a `fr/` page become `/fr/...`). Longer codes are matched first (e.g. `en-US` before `en`). It does **not** change relative image or video `src` paths, MDX/JSX **import** paths, or shared **MDX snippets**; those must be correct in source so all locales stay aligned. Prefer `npm run translate:localize-links --` with `--target`, `--all`, or `--all --check`. -- `scripts/localize-component-imports.mjs`: Rewrites MDX `import ... from "...//components/...jsx"` paths so they match the active locale being processed (`--target`, `--all`, or default targets). This keeps locale pages importing locale-local components after PIT/CI translation. +- `scripts/localize-internal-links.mjs`: Rewrites internal absolute **navigation** links in each locale’s MDX for whatever locale is being processed (`--target`, `--all`, or default targets): bare paths get that locale’s prefix (e.g. `/platform/points` → `/es/platform/points` when processing `es/`), and any path already prefixed with **another** locale from `i18n.json` (`en`, `es`, future `fr`, etc.) is re-prefixed to the active locale (so `/en/...` or stale `/es/...` on a `fr/` page become `/fr/...`). Longer codes are matched first (e.g. `en-US` before `en`). It does **not** change relative image or video `src` paths or MDX `import` paths (those are normalized by `scripts/localize-mdx-paths.mjs` after translation: components, `snippets/`, and repo-root `assets/`). Prefer `npm run translate:localize-links --` with `--target`, `--all`, or `--all --check`. +- `scripts/localize-mdx-paths.mjs`: Rewrites MDX paths for locale docs: (1) `...//components/...jsx` for the active locale, (2) `import ... ".../snippets/..."` depth to repo-root `snippets/`, and (3) JSX `src=".../assets/..."` depth to repo-root `assets/` (Lingo copies English relative paths). Use `--target`, `--all`, or default targets; `translate:generate` and translate-on-main run it after Lingo. - **Shared MDX snippets (`snippets/*.mdx`)**: Reusable MDX blocks stay in repo-root `snippets/` (not per-locale). Import them with relative paths from each page (for example `../../snippets/foo.mdx` from `locale/
/.mdx`, or more `../` segments for deeper pages). They are excluded from Lingo buckets in `i18n.json` so they stay English and identical everywhere. - **Localized React components (`components/*.jsx` for default language, `/components/*.jsx` for targets)**: UI components that can contain locale text are stored per locale (for example `components/rate-limit-badge.jsx`, `es/components/rate-limit-badge.jsx`) and manually maintained per locale (not translated by PIT/CI automation). -- **Media paths**: Default-language pages live at repo root paths like `
/.mdx` and target locales live under `/
/.mdx`; shared files sit in repo-root `assets/`. Keep relative media paths correct for each file depth. +- **Media paths**: Default-language pages live at repo root paths like `
/.mdx` and target locales live under `/
/.mdx`; shared files sit in repo-root `assets/`. Prefer relative `src="../assets/..."` (or more `../`) from English source; `scripts/localize-mdx-paths.mjs` rewrites `assets/` `src` depth for each target locale file. - **`openapi.yml`**: One OpenAPI 3.1 spec at the **repository root** (alongside `docs.json`). API and webhook pages reference it explicitly in frontmatter, for example `openapi: openapi.yml get /users/{id}` or `openapi: openapi.yml webhook points.changed`. Do not duplicate the YAML under locale folders; Lingo must not alter `openapi:` lines. - **`scripts/sync-openapi-titles.mjs`**: Copies each operation/webhook **`summary`** from `openapi.yml` into the English page’s **`title:`** frontmatter (Mintlify’s default when `title` is omitted). Target locales get an English `title` only if missing (bootstrap); run **`npm run translate:generate`** so Lingo translates those titles. Runs automatically at the start of `translate:generate` and in translate-on-main before Lingo. - `scripts/sync-heading-anchors.mjs`: Writes Mintlify [custom heading IDs](https://www.mintlify.com/docs/create/text#custom-heading-ids) as **`## Title {#slug}`** markdown. Slugs match Mintlify’s auto rules from the **English** title so hashes like `#pro-plan` stay stable across locales. Run `npm run translate:sync-anchors` after bulk heading edits; translation pipelines run it automatically (see **Heading anchors and Lingo** below). The script can also migrate one-line **`

`** left from older tooling back to `{#slug}` syntax. @@ -82,13 +82,13 @@ Use `npm run