---
title: "Language route prefixes — short ISO codes with legacy redirects"
type: quick-fix
date: 2026-06-04
---

# Language route prefixes — short ISO codes with legacy redirects

## Bug
Localized URLs used full English names (`/chinese`, `/japanese`, `/korean`, `/vietnamese`, `/indonesian`, `/malay`). Per the broadcast in WeChat (screenshot), they need to be short ISO-style codes (`/cn`, `/ja`, `/ko`, `/vi`, `/id`, `/ms`).

## Root Cause
The mapping is sourced from one place — `src/languageRoutes.ts` `localizedHomeRoutes` — and that array hard-coded the long names.

## Fix
- Rename every localized prefix in `localizedHomeRoutes` to its short code.
- Add `legacyLanguageRedirects` (the old → new map) and render client redirects in `App.tsx` so links previously shared (`/chinese`, `/malay/browse?post=42`, etc.) keep landing on the right destination. The redirect preserves sub-path, query string, and hash.
- Refresh doc-comment examples (`/malay/...`) in unrelated files so future readers don't get confused.
- Update `languageRoutes.test.ts` to assert the new mapping.

### Files Modified
- `src/languageRoutes.ts` — paths swapped to short codes; added `legacyLanguageRedirects`; refreshed doc-comment examples.
- `src/languageRoutes.test.ts` — expectations updated to short codes; test description renamed accordingly.
- `src/App.tsx` — added `LegacyLangRedirect` component (uses `useParams`/`useLocation`) and rendered `<Route>` pairs (`/old` and `/old/*`) for each entry in `legacyLanguageRedirects`.
- `src/i18n.tsx`, `src/components/FigmaBanner.tsx`, `src/layouts/PublicLayout.tsx`, `src/useLocalizedPath.ts` — doc-comment example paths updated for consistency.

## Verification
- `npx tsc --noEmit` — clean.
- `npm run format` then `npm run format:check` — clean.
- `npm test` — 49/49 passing (includes the updated `languageRoutes.test.ts`).
- Expected runtime behavior:
  - `/cn`, `/ja`, `/ko`, `/vi`, `/id`, `/ms` (and their nested routes) resolve to localized pages.
  - `/chinese`, `/japanese`, `/korean`, `/vietnamese`, `/indonesian`, `/malay` (and their nested routes) redirect via React Router `<Navigate replace />` to the new short-code equivalents, preserving `?query` and `#hash`.

## Notes
- Server-side considerations: this works for SPA navigation because BrowserRouter handles all paths client-side. Any reverse-proxy/CDN rule that hardcoded the long names should be reviewed (e.g. nginx rewrites, prerender configs). The `nginx.conf` and Gitea deploy workflow only reference `index.html`, so no server-side path rules to update here.
- If the SEO sitemap / canonical URLs are generated elsewhere, those should also pick up the new prefixes.
- `legacyLanguageRedirects` is intentionally kept distinct from `localizedHomeRoutes` so we can sunset it later by deleting the export and the corresponding routes block in `App.tsx`.
