Skip to content

locize/locize-react-router-example

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

React Router v7 framework-mode + Locize example

A minimal React Router v7 (framework mode) sample showing how to wire remix-i18next (v7.x, the RR-v7-targeting major) with Locize for server-side language detection plus client-side translation loading.

Stack: React Router 7.15 (framework mode, middleware enabled) · remix-i18next 7.5 · i18next 26 · react-i18next 17 · i18next-locize-backend 10 · locize 4.0.23 (with the SSR-safe isInIframe fix shipped today) · React 19 · Vite 7.

Migrating from Remix v2? See the companion locize-remix-i18next-example which stays on Remix v2 + remix-i18next 6.x for projects that haven't moved to React Router v7 framework mode yet.

Getting started

  1. Create a free account and a project at https://www.locize.com/?from=locize-react-router-example, then grab your project id (and an API key if you want saveMissing writes during local dev).
  2. Either edit app/locize.config.ts and package.json's downloadLocales/syncLocales scripts, or keep the shipped demo-project credentials to try it out first.
  3. Pre-bundle the translations: npm run downloadLocales — pulls the latest published JSON from Locize into app/locales/ (the JSON files there are committed as sane defaults so the example builds without a Locize account).
  4. npm install && npm run dev, then open http://localhost:3000.

How the Locize integration works

React Router v7's framework mode runs the same React tree on the server and on the client. We use different translation sources on each side to get the best of both:

Server side — app/middleware/i18next.ts

createI18nextMiddleware from remix-i18next/middleware (the new RR-v7 middleware pattern, opt-in via future.v8_middleware: true in react-router.config.ts) detects the locale from the request (cookie → URL param → Accept-Language) and seeds a per-request i18next instance.

Resources come from the statically-imported JSON in app/locales/index.ts — i.e. the JSON files in app/locales/ that locize download placed there at build time. No runtime calls to the Locize CDN from the server. This is important on serverless platforms (Vercel/Netlify/Cloudflare Workers) where each request would otherwise be a fresh cold-start re-download.

getLocale(context) and getInstance(context) (returned by createI18nextMiddleware) are how loaders and entry.server.tsx access what the middleware decided.

Client side — app/entry.client.tsx

After the SSR-rendered HTML reaches the browser, i18next initialises with i18next-locize-backend directly against the Locize CDN. This means content updates published in Locize show up on the next page view without a redeploy. The locize in-context editor plugin (append ?locize=true to the URL) and dev-only locize-lastused for unused-key tracking round out the integration.

hydrateRoot is wrapped in startTransition per React 19 + RR v7 guidance.

Pushing missing keys back — saveMissing

Set in app/entry.client.tsx via saveMissing: !isProduction. When i18next requests a key that the loaded JSON doesn't yet have, it pushes the key to Locize so translators can fill it in — analogous to a build-time extraction step, but live during dev.

locize@4.0.23 SSR safety

The locize package's isInIframe detection was fixed in 4.0.23 (changelog) to correctly return false in Node 20+ SSR builds. Prior versions incorrectly evaluated self !== top (since self is now globalThis in modern Node) and made locize believe it was inside the Locize editor iframe during SSR rendering. The fix matters anywhere React Router v7 renders on the server — i.e. always in framework mode.

Production safety

The write-enabled apiKey is hardcoded in app/locize.config.ts only because the demo project is intentionally public. For your own project, source the dev apiKey from a git-ignored env file (e.g. read from import.meta.env.VITE_LOCIZE_APIKEY in dev, omit in prod) and never ship a write-enabled key in production builds.

Scripts

Command What it does
npm run dev React Router dev server on http://localhost:3000
npm run build Production build into build/
npm start Run the production build via @react-router/serve
npm run typecheck react-router typegen && tsc
npm run downloadLocales locize download — pull translations into app/locales/
npm run syncLocales locize sync — two-way sync (dry-run by default)

Locize CDN endpoint

The example talks to the Pro CDN (api.locize.app) by default because the shipped demo project lives there. If your project is on the Standard CDN (api.lite.locize.app, the default for new Locize projects), set cdnType: 'standard' in app/locize.config.ts. See CDN types: Standard vs. Pro for the full comparison.

Related

About

React Router v7 framework-mode + remix-i18next + Locize example. Companion to locize-remix-i18next-example which stays on Remix v2.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors