diff --git a/.cursor/rules/localization-workflow.mdc b/.cursor/rules/localization-workflow.mdc index 85b9a3a..be3f664 100644 --- a/.cursor/rules/localization-workflow.mdc +++ b/.cursor/rules/localization-workflow.mdc @@ -14,7 +14,7 @@ alwaysApply: true - `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. +- Keep OpenAPI specs under repo-root `openapi/` (not under locale folders). Endpoint and webhook MDX must use Mintlify’s form `openapi: openapi/.yml ` or `openapi: openapi/.yml webhook `. Do not translate the `openapi:` line. - English **nav titles** for those pages come from OpenAPI **`summary`** via `scripts/sync-openapi-titles.mjs` (`npm run translate:sync-openapi-titles`). It runs at the start of `translate:generate` and on the translate-on-main workflow. Lingo translates the `title` field for target locales; the script only fills a missing target `title` with English (bootstrap)—it does not overwrite existing translations. - Mintlify custom heading IDs use markdown `## Title {#slug}` (see Mintlify docs). Slugs are aligned from English source root files via `scripts/sync-heading-anchors.mjs`. Never translate or alter `{#…}`; sync runs after Lingo in PIT/CI. Do not merge heading-count drift between source root and target locales without fixing structure first. - For Mintlify `` components that may be deep-linked, always set explicit `id` values (do not rely on title-derived hashes) and keep those `id`s identical across locales. diff --git a/.github/workflows/validate-translations.yml b/.github/workflows/validate-translations.yml index cb9ce9c..f9e03bc 100644 --- a/.github/workflows/validate-translations.yml +++ b/.github/workflows/validate-translations.yml @@ -6,7 +6,7 @@ on: paths: - "docs.json" - "i18n.json" - - "openapi.yml" + - "openapi/**" - "package.json" - "account/**" - "admin-api/**" diff --git a/README.md b/README.md index ac53779..d910e7b 100644 --- a/README.md +++ b/README.md @@ -60,13 +60,13 @@ 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 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-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. `/features/points` → `/es/features/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/`. 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. +- **`openapi/`**: Split OpenAPI 3.1 specs at the **repository root** (for example `openapi/application.yml`, `openapi/admin.yml`). API and webhook pages reference a spec explicitly in frontmatter, for example `openapi: openapi/application.yml get /users/{id}` or `openapi: openapi/application.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 the referenced spec 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. - `scripts/validate-glossary-csv.mjs`: Validates glossary schema and duplicate canonical keys. Prefer `npm run lingo:validate-glossary`. @@ -92,7 +92,7 @@ Use `npm run