{"id":31693748,"url":"https://github.com/mdvorak/lingui-react-router","last_synced_at":"2025-10-08T15:53:05.479Z","repository":{"id":316390491,"uuid":"1063156552","full_name":"mdvorak/lingui-react-router","owner":"mdvorak","description":"Integration between Lingui and React Router app","archived":false,"fork":false,"pushed_at":"2025-10-03T11:12:35.000Z","size":358,"stargazers_count":1,"open_issues_count":4,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-10-03T13:11:15.897Z","etag":null,"topics":["i18n","lingui","react","react-router"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mdvorak.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-09-24T08:40:39.000Z","updated_at":"2025-10-03T11:10:11.000Z","dependencies_parsed_at":"2025-09-28T11:35:20.227Z","dependency_job_id":null,"html_url":"https://github.com/mdvorak/lingui-react-router","commit_stats":null,"previous_names":["mdvorak/lingui-react-router"],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/mdvorak/lingui-react-router","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdvorak%2Flingui-react-router","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdvorak%2Flingui-react-router/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdvorak%2Flingui-react-router/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdvorak%2Flingui-react-router/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mdvorak","download_url":"https://codeload.github.com/mdvorak/lingui-react-router/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdvorak%2Flingui-react-router/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278487456,"owners_count":25995185,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-05T02:00:06.059Z","response_time":54,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["i18n","lingui","react","react-router"],"created_at":"2025-10-08T15:52:56.386Z","updated_at":"2025-10-08T15:53:05.474Z","avatar_url":"https://github.com/mdvorak.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# lingui-react-router\n\nIntegration between [Lingui](https://lingui.dev/) and [React Router](https://reactrouter.com/) with\nlocale-aware routing, server middleware, and a streamlined client bootstrap for SSR-ready apps.\n\n## Features\n\n- i18n-aware route config helpers to generate routes per locale from a single source of truth.\n- Server middleware to detect, normalize, and initialize locale with SSR support and locale-aware\n  redirects.\n- Client bootstrap to preload the initial catalog before hydration to avoid flicker or missing\n  messages.\n- Runtime hooks and a locale-aware Link that automatically prefixes paths with the active request\n  locale.\n\n## Requirements\n\n- React ^19\n- React Router ^7.9\n- Lingui ^5.5\n- Node.js \u003e= 20\n\n## Installation\n\nInstall the package plus required peer dependencies in the app.\nThese examples assume Vite and Lingui's Vite plugin for optimal DX and SSR support.\n\n```shell\n# Install required and peer dependencies\nnpm install -S react react-dom react-router isbot\nnpm install -S @lingui/core @lingui/react\nnpm install -D @react-router/dev @lingui/cli @lingui/conf @lingui/vite-plugin vite-plugin-babel-macros\n# For Typescript, add\nnpm install -D typescript tsx vite-tsconfig-paths @types/react @types/react-dom\n# Install this library\nnpm install -S lingui-react-router\n```\n\n## Quick start\n\n1) Configure vite and react router\n\nEnable React Router, Lingui, and macros in Vite for SSR and catalog compilation during development.\nPath alias resolution via tsconfigPaths is recommended for clean imports and consistent\nserver/client builds.\n\n ```typescript\n // vite.config.ts\nimport {lingui} from \"@lingui/vite-plugin\"\nimport {reactRouter} from \"@react-router/dev/vite\"\nimport {linguiRouterPlugin} from \"lingui-react-router/plugin\"\nimport {defineConfig} from \"vite\"\nimport macrosPlugin from \"vite-plugin-babel-macros\"\nimport tsconfigPaths from \"vite-tsconfig-paths\"\n\nexport default defineConfig({\n  plugins: [\n    reactRouter(),\n    macrosPlugin(),\n    lingui(),\n    linguiRouterPlugin(),\n    tsconfigPaths(),\n  ],\n})\n ```\n\nEnable SSR and v8-style middleware in the React Router config to support server-side i18n\ninitialization and redirects.\nThis aligns server middleware with the app's route modules and the I18nApp layout for consistent SSR\nhydration.\nConfigure prerendering for localized routes if needed.\n\n ```ts\n// react-router.config.ts\nimport type {Config} from \"@react-router/dev/config\"\nimport linguiConfig from \"./lingui.config\"\n\nconst {locales} = linguiConfig\nconst langPrerender = [\"hello\"] // Add your localized paths here\n\nexport default {\n  future: {\n    v8_middleware: true,\n  },\n  prerender: [...langPrerender.flatMap(path =\u003e locales.map(lang =\u003e `/${lang}/${path}`))],\n} satisfies Config\n ```\n\n2) Add server middleware and wrap the app with I18nApp in the root layout route module.\n   The middleware sets up the server-side i18n context, and the I18nApp provides hydration-safe i18n\n   on the client and server.\n\n```tsx\n// app/root.tsx\nimport {useLingui} from \"@lingui/react/macro\"\nimport {I18nApp} from \"lingui-react-router\"\nimport {localeMiddleware} from \"lingui-react-router/server\"\nimport {type ReactNode} from \"react\"\nimport {Links, Meta, Outlet, Scripts, ScrollRestoration} from \"react-router\"\n\nexport const middleware = [localeMiddleware]\n\nfunction RootLayout({children}: { children: ReactNode }) {\n  const {i18n} = useLingui()\n\n  return (\n    \u003chtml lang={i18n.locale}\u003e\n    \u003chead\u003e\n      \u003cmeta charSet=\"utf-8\"/\u003e\n      \u003cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1\"/\u003e\n      \u003cMeta/\u003e\n      \u003cLinks/\u003e\n    \u003c/head\u003e\n    \u003cbody\u003e\n    {children}\n    \u003cScrollRestoration/\u003e\n    \u003cScripts/\u003e\n    \u003c/body\u003e\n    \u003c/html\u003e\n  )\n}\n\nexport function Layout({children}: { children: ReactNode }) {\n  return (\n    \u003cI18nApp\u003e\n      \u003cRootLayout\u003e{children}\u003c/RootLayout\u003e\n    \u003c/I18nApp\u003e\n  )\n}\n\nexport default function App() {\n  return \u003cOutlet/\u003e\n}\n```\n\n3) Bootstrap the client by preloading the initial locale before hydrating the router.\n   This ensures the correct messages are available at first paint and avoids hydration warnings.\n\n```tsx\n// app/entry.client.tsx\nimport {loadInitialLocale} from \"lingui-react-router/client\"\nimport {startTransition, StrictMode} from \"react\"\nimport {hydrateRoot} from \"react-dom/client\"\nimport {HydratedRouter} from \"react-router/dom\"\n\nstartTransition(async () =\u003e {\n  await loadInitialLocale(location.pathname)\n\n  hydrateRoot(\n    document,\n    \u003cStrictMode\u003e\n      \u003cHydratedRouter/\u003e\n    \u003c/StrictMode\u003e\n  )\n})\n```\n\n4) Generate localized routes from the i18n config with localeRoutes helpers.\n   Define the default root and locale-scoped routes in a single config to keep paths maintainable.\n\n   ```ts\n   // app/routes.ts\n   import { index, type RouteConfig } from \"@react-router/dev/routes\"\n   import { localeRoutes } from \"lingui-react-router/routes\"\n   import linguiConfig from \"../lingui.config\"\n\n   const locale = localeRoutes(linguiConfig)\n\n   export default [\n     index(\"./routes/_index.tsx\"),\n     ...locale.index(\"./routes/_index.tsx\"),\n     ...locale.route(\"hello\", \"./routes/hello.tsx\"),\n   ] satisfies RouteConfig\n   ```\n\n5) Use the locale-aware link and runtime hooks for current locale, request locale, and config.\n   LocaleLink automatically prefixes the active locale and should receive locale-less paths for\n   correctness.\n\n```tsx\nimport {LocaleLink, usePathLocale, config} from \"lingui-react-router\"\n\nfunction Header() {\n  const {locale, requestLocale} = usePathLocale()\n  return (\n    \u003cnav\u003e\n      \u003cLocaleLink to=\"/hello\"\u003eHello\u003c/LocaleLink\u003e\n      \u003cspan\u003eActive: {locale} (from URL: {requestLocale || \"-\"})\u003c/span\u003e\n      \u003cspan\u003eSupported: {config.locales.join(\", \")}\u003c/span\u003e\n    \u003c/nav\u003e\n  )\n}\n```\n\nNotes about LocaleLink:\n\n- Pass locale-less paths such as `to=\"/hello\"` or an object pathname without a locale, and the\n  locale prefix will be added automatically based on the current request locale.\n- If the current URL has no locale segment (e.g., the default root), LocaleLink renders a normal\n  Link without modification to preserve expected navigation.\n\n6) Access server-side i18n and locale-aware redirects in loaders and actions with `useLinguiServer`.\n   Redirects thrown from this helper are automatically prefixed with the current locale for\n   consistent UX and SEO.\n\n   ```tsx\n   // app/routes/hello.tsx\n   import { msg } from \"@lingui/react/macro\"\n   import { data, useLoaderData } from \"react-router\"\n   import { useLinguiServer } from \"lingui-react-router/server\"\n\n   export function loader() {\n     const { _, redirect } = useLinguiServer()\n\n     // Example of localized redirect\n     if (someCondition) {\n       throw redirect(\"/login\")\n     }\n\n     const message = _(msg`Hello, World!`)\n     return data({ message })\n   }\n\n   export default function Hello() {\n     const { message } = useLoaderData()\n\n     return (\n       \u003cdiv\u003e\n         \u003ch1\u003e{message}\u003c/h1\u003e\n       \u003c/div\u003e\n     )\n   }\n   ```\n\n## API summary\n\n- `I18nApp`: wraps the application and synchronizes the i18n instance across server and client\n  boundaries for SSR.\n- `localeMiddleware`: detects locale from the URL, normalizes paths, initializes i18n, and enables\n  locale-aware redirects.\n- `loadInitialLocale`: preloads the correct catalog on the client before hydration based on the\n  initial path.\n- `localeRoutes`: generates localized route entries and helpers for index and child routes from a\n  single i18n config.\n- `LocaleLink`: a Link drop-in that prefixes locale automatically; always pass locale-less paths to\n  ensure correct URL generation.\n- `usePathLocale`: runtime hook for the active locale, requestLocale, and path information.\n- `useLinguiServer`: loader/action helper with i18n instance, request locale, localized redirect,\n  and convenience values like pathnamePrefix.\n\n## Development\n\nRun a full build and test to ensure catalogs, SSR, and middleware work together in the target\nenvironment.\nUse a modern Node.js runtime and verify Vite plugins are active to compile and load catalogs in dev\nand prod.\n\n```\npnpm build\npnpm test\n```\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmdvorak%2Flingui-react-router","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmdvorak%2Flingui-react-router","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmdvorak%2Flingui-react-router/lists"}