Intlayer
Use this skill when work touches Intlayer i18n, especially Intlayer 9.4 (intlayer@9.4.1 line) with TanStack Start (@tanstack/react-start) via intlayer + react-intlayer + vite-intlayer.
Pin intlayer / react-intlayer / vite-intlayer to the same 9.4.x. Do not mix 9.0.x docs or packages with 9.4 APIs (getIntlayerAsync, analytics, compiler.enabled: "build-only", proxy auto mode).
Workflow
- Inspect the local Intlayer + Start shape before changing code:
- Package versions for
intlayer,react-intlayer,vite-intlayer,@tanstack/react-start,@tanstack/react-router(all Intlayer packages must match). - Config:
intlayer.config.tslocales,routing.mode,routing.enableProxy,routing.storage,content.contentDir,dictionary.importMode,dictionary.fill,compiler.enabled,build.optimize/minify/purge,editor,analytics,ai,plugins. - Vite:
intlayer()plugin (proxy.ignore, optionalcompatCallers),tanstackStart({ router: { routeFileIgnorePattern } }). - Routes:
src/routes/__root.tsxshell +IntlayerProvider,src/routes/{-$locale}/layout withvalidatePrefix. - Content:
*.content.{ts,tsx,js,json,...}dictionaries and generated.intlayer/output. - Navigation: reject
LocalizedLink,useLocalizedNavigate, and any other Link/navigate wrappers — use native TanStack Router APIs only.
- Package versions for
- Refresh docs when the task depends on latest behavior, 9.4 APIs, CMS/editor/analytics, or package drift. Start from source-map.md.
- For install, config, Vite plugin, provider, and TypeScript includes, use setup-tanstack-start.md.
- For
intlayer.config.tsknobs (routing, dictionary, compiler, build, editor, analytics, AI, plugins), use configuration.md. - For content declarations, node helpers, collections/variants, formatters, and
useIntlayer, use content-dictionaries.md. - For locale routing, native links/navigate, SSR
getLocale/getIntlayerAsync, SEOhead, sitemap, and 404s, use routing-ssr-seo.md. - For CLI, fill, CMS, visual editor, live sync, MCP, and
@intlayer/analytics, use cli-cms-ai.md. - For compiler extraction, bundle optimize/minify/purge, import modes, compat adapters, and
syncJSON, use compiler-compat.md. - Prefer
bun/bunxin command examples. Prefer the official Start guide over Next.js or Solid Start docs — but do not copy Intlayer'sLocalizedLink/useLocalizedNavigateexamples; use native TanStack RouterLink/useNavigateinstead.
Implementation Judgment
- TanStack Start uses
intlayer+react-intlayer+vite-intlayer. Do not install or copy APIs fromnext-intlayer/next-intlayer/serverorsolid-intlayer. There is notanstack-intlayerpackage. - Next.js 9.4 merges
IntlayerClientProvider/IntlayerServerProviderintoIntlayerProvider. Start already usesIntlayerProviderfromreact-intlayer. Do not introduce the deprecated Next split providers. - Locale detection/redirect is the Vite
intlayer()proxy, not a TanStack Router middleware API.routing.enableProxyisundefined(auto) by default in 9.4 config: proxy runs; dev/preview stay URL-driven (ignore stored locale); production uses full storage-driven redirects. Settrueto force storage-driven redirects everywhere;falseto disable the proxy. - No Link/navigate wrappers. Do not create, keep, or recommend
LocalizedLink,useLocalizedNavigate, or any component/hook that wraps TanStackLink/useNavigateto inject locale. Use nativeLinkanduseNavigatewith fulltopaths (/{-$locale}/...) andparams.localefromgetPrefix(locale).localePrefix. On review/migrate, delete existing wrappers and rewrite call sites. - Always set
routeFileIgnorePatternfor.content.*so content files are not treated as routes. - Match the locale route slot to
routing.mode:{-$locale}forprefix-no-default; prefer$localeforprefix-all; remove the slot forno-prefix/search-params. - Client UI:
useIntlayer/useLocalefromreact-intlayer. Locale-aware formatters:react-intlayer/format. Server functions,head, loaders, and non-React code:getIntlayerAsync/getLocalefromintlayer(9.4+). Use syncgetIntlayeronly when a merged all-locales dictionary is acceptable. - In
beforeLoad, validate locale fromparams.localeviavalidatePrefix— not from cookies/headers (the proxy already handled request locale). - Co-locate
.content.*with features. Setcontent.contentDirexplicitly for Start apps undersrc(config default is["."], not a Next-style./app). compiler.enableddefaults tofalse. Values:false|true|"build-only"(skip in dev). Bundled proxy/compiler live insideintlayer()— do not require separateintlayerProxy()/intlayerCompiler()unless plugin order demands it.- For production SSR that needs the locale proxy, keep
vite-intlayeravailable at runtime (move out ofdevDependencieswhen the proxy runs in production). - For HTML attributes (
alt,title,aria-label), use.value,.toString(), orString(...)on content nodes. - Discriminants:
plural/enu(quantity),cond(boolean),gender,select(any other string — 9.1). Do not index a content object with a runtime key (node[status]); callnode(status)so the compiler can minify/purge. - Collections share
key+item. Variants usevariant: string | object(9.1 merged former dynamic records into object variants). Selectors:{ locale, item, variant }. Resolution order: variant → item. - Do not enable
build.minifywhileeditor.enabledis true (ignored).importMode/ minify / purge requirebuild.optimize(default true in production).
Verification
Prefer the repo's existing checks. For meaningful Intlayer + Start work, include the relevant subset:
- Typecheck with
.intlayer/**/*.tsincluded and route tree regenerated. - Locale smoke: default locale (no prefix or prefixed), alternate locales, invalid prefix → 404 redirect, locale switcher.
- Navigation smoke: in-app links and programmatic navigate keep the current locale; switcher updates
params.localewithout wrapper components. - SSR smoke: first HTML
lang/dir, cookie/Accept-Languageproxy redirects, server functiongetLocale+getIntlayerAsync. - Head/metadata smoke: async
headusesgetIntlayerAsyncso only the requested locale chunk loads. - Content smoke: missing keys, attribute string rendering, collections/variants/
plural/enu/selectwhen used. - CLI:
bunx intlayer buildandbunx intlayer test(alias ofcontent test) when dictionaries change. - Sitemap/prerender smoke when changing localized SEO routes.
- If CMS/editor/analytics are in scope: live sync,
push/pull, andeditor.clientIdfor analytics attribution.
Report which checks ran, which did not, and any version-sensitive assumptions that remain.