Files
multica/apps/docs/lib/locale-link.ts
Bohan Jiang 53a3b33c50 fix(docs): keep zh internal links inside the zh locale (#2179)
Markdown links like `[xx](/workspaces)` written in `*.zh.mdx` rendered
as bare `<a href="/workspaces">`, which Next's basePath rewrote to
`/docs/workspaces` and the docs middleware then routed to English —
silently kicking Chinese readers out of their locale on every internal
click.

Add a `LocaleLink` MDX `a` override that runs every internal href
through `prefixLocale(href, lang)` before passing it to `next/link`, and
wire a `DocsLocaleProvider` around the MDX body in both page entry
points so the override and `NumberedCard` know the active locale.
External links, in-page anchors, relative paths, already-prefixed
paths, and default-language pages are deliberately left untouched.

Closes the bug reported in https://github.com/multica-ai/multica/issues/2173.

Co-authored-by: multica-agent <github@multica.ai>
2026-05-07 01:21:57 +08:00

32 lines
1.3 KiB
TypeScript

import { i18n } from "./i18n";
// Add the active locale prefix to root-relative MDX links so internal
// navigation inside Chinese (or any non-default-language) docs stays in
// that language. Without this, `[xx](/workspaces)` written in a `*.zh.mdx`
// renders as `<a href="/workspaces">`, which Next's basePath rewrites to
// `/docs/workspaces` and the docs middleware then routes to English —
// leaking the reader out of their chosen locale.
//
// We deliberately do NOT touch:
// - external links (`https:`, `mailto:`, `tel:`, etc.)
// - in-page anchors (`#section`)
// - relative paths (`./foo`, `../bar`)
// - paths already prefixed with a known locale
// - the default language (URLs are intentionally prefix-less under
// `hideLocale: 'default-locale'`)
export function prefixLocale(href: string, lang: string): string {
if (!href) return href;
if (lang === i18n.defaultLanguage) return href;
if (/^[a-z][a-z0-9+.-]*:/i.test(href)) return href;
if (href.startsWith("#")) return href;
if (!href.startsWith("/")) return href;
const segments = href.split("/").filter(Boolean);
const first = segments[0];
if (first && (i18n.languages as readonly string[]).includes(first)) {
return href;
}
return href === "/" ? `/${lang}` : `/${lang}${href}`;
}