Definition
Locale-aware routing is a routing model where the user's chosen language (ko/en/ja) is reflected consistently across all internal URLs and client-side navigation.
With next-intl and localePrefix: "always", URLs always look like /ko/til or /en/knowledge/.... Paths without a prefix — such as /til — are 301-redirected by middleware to the default locale (e.g. /ko/til).
Why it matters
Content may exist in en/ja, but if the header, sitemap, and cards use plain next/link pointing at /til, every click from /en sends users through middleware to /ko/til, resetting language choice each time. That is a routing contract violation, not a translation quality issue.
By contrast, Link and useRouter from @/i18n/navigation automatically include the current locale in hrefs. Sampling SSR HTML href values quickly catches bare-path regressions.
How it works
- Middleware: With
localePrefix: "always", detect bare pathnames and redirect to the default locale. - i18n Link:
href="/til"renders as/en/til(based on current locale). - Plain next/link:
href="/til"stays bare → middleware 301 →/ko/til. - Language switcher: Use
routing.localesas the single source for dropdown, sitemap, and message keys. - Programmatic nav: Use the i18n router for
router.pushandreplace. Works alongsidestartTransitionand view transitions. - Markdown body links: Apply locale prefix conversion in the remark pipeline (separate from app shell Link).
Practical application
- Grep content-nav, footer, list cards, and breadcrumbs; remove internal
next/linkusage. - Replace per-page copy-pasted untranslated fallback with
getLocalizedDocumentOrRedirecthelper + tests. - After prod
next start,curl/en/...HTML and count internal hrefs — target zero bare paths. - Pass active locale as query param or header to load-more and relations APIs.
- Add an ESLint custom rule or codemod to flag new
from "next/link"imports undersrc/.
Trade-offs
| Choice | Pros | Cons |
|---|---|---|
| localePrefix always | Language visible in URL; clear caching/sharing | Forces i18n API for every internal link |
| localePrefix as-needed | Shorter default-locale URLs | ko vs en/ja URL shapes differ |
| Plain Link + manual prefix | Familiar | Omissions cause 301 and locale loss |
| Redirect fallback (ko) | Guarantees readable content | URL locale changes |
When not to use
- External sites,
mailto:, and absolute URLs — plain<a>ornext/linkwith full URL is locale-agnostic. - API routes and static assets — no locale segment.
localePrefix: "never"policy — different premise from this document's always assumption.
Common mistakes
- Converting only the header to i18n
Linkwhile 12 content-nav spots still use plainnext/link. - Adding locale prefix only on the client while SSR HTML stays bare → SEO and no-JS users land on ko.
- Expecting view transitions on
router.back()— popstate is synchronous, so VT is unsupported (use explicit URLpush). - Shipping markdown body links like
../knowledge/...without a locale conversion pipeline.
Related concepts
- multilingual-content-locale-suffix — content locale axis
- hierarchical-document-navigation — list → detail depth
- ssr-hydration-mismatch — SSR HTML and client href alignment