frontend-internationalization-best-practices

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Internationalization Best Practices

国际化最佳实践

Guidelines for building a React Router i18n setup with
remix-i18next
. Focuses on middleware detection, locale storage, type safety, and client/server synchronization.
本指南介绍如何使用
remix-i18next
搭建React Router国际化配置,重点涵盖中间件检测、语言环境存储、类型安全以及客户端/服务端同步。

When to Apply

适用场景

  • Adding i18n to a React Router app
  • Wiring
    remix-i18next
    middleware
  • Implementing language switching or locale detection
  • Serving locale resources from
    /api/locales
  • 为React Router应用添加国际化功能
  • 配置
    remix-i18next
    中间件
  • 实现语言切换或语言环境检测
  • 通过
    /api/locales
    提供语言环境资源

Rules Summary

规则摘要

Setup & Middleware (CRITICAL)

配置与中间件(关键)

setup-middleware - @rules/setup-middleware.md

setup-middleware - @rules/setup-middleware.md

Configure
createI18nextMiddleware
and type-safe resources.
ts
export const [i18nextMiddleware, getLocale, getInstance] =
  createI18nextMiddleware({
    detection: {
      supportedLanguages: ["es", "en"],
      fallbackLanguage: "en",
      cookie: localeCookie,
    },
    i18next: { resources },
    plugins: [initReactI18next],
  });
配置
createI18nextMiddleware
和类型安全的资源文件。
ts
export const [i18nextMiddleware, getLocale, getInstance] =
  createI18nextMiddleware({
    detection: {
      supportedLanguages: ["es", "en"],
      fallbackLanguage: "en",
      cookie: localeCookie,
    },
    i18next: { resources },
    plugins: [initReactI18next],
  });

locales-structure - @rules/locales-structure.md

locales-structure - @rules/locales-structure.md

Define locale resources per language and re-export.
ts
// app/locales/en/translation.ts
export default { title: "Example" };
按语言定义语言环境资源并重新导出。
ts
// app/locales/en/translation.ts
export default { title: "Example" };

Namespaces (HIGH)

命名空间(重要)

namespaces-strategy - @rules/namespaces-strategy.md

namespaces-strategy - @rules/namespaces-strategy.md

Use a single namespace for small apps; multiple namespaces for large apps.
ts
// Large app: common + route namespaces
export default { common, home, notFound };
小型应用使用单一命名空间;大型应用使用多命名空间。
ts
// 大型应用:通用 + 路由命名空间
export default { common, home, notFound };

Locale Detection & Persistence (CRITICAL)

语言环境检测与持久化(关键)

locale-detection - @rules/locale-detection.md

locale-detection - @rules/locale-detection.md

Prefer cookie/session for speed, with DB as source of truth.
ts
export const [i18nextMiddleware, getLocale] = createI18nextMiddleware({
  detection: { cookie: localeCookie, fallbackLanguage: "en" },
});
优先使用Cookie/会话以提升速度,数据库作为可信数据源。
ts
export const [i18nextMiddleware, getLocale] = createI18nextMiddleware({
  detection: { cookie: localeCookie, fallbackLanguage: "en" },
});

language-switcher - @rules/language-switcher.md

language-switcher - @rules/language-switcher.md

Store locale in cookie/session and keep it in sync.
ts
return data(
  { locale },
  { headers: { "Set-Cookie": await localeCookie.serialize(locale) } },
);
将语言环境存储在Cookie/会话中并保持同步。
ts
return data(
  { locale },
  { headers: { "Set-Cookie": await localeCookie.serialize(locale) } },
);

Client & Server Integration (CRITICAL)

客户端与服务端集成(关键)

root-locale-sync - @rules/root-locale-sync.md

root-locale-sync - @rules/root-locale-sync.md

Send locale to the UI and sync
<html lang dir>
.
tsx
export async function loader({ context }: Route.LoaderArgs) {
  let locale = getLocale(context);
  return data(
    { locale },
    { headers: { "Set-Cookie": await localeCookie.serialize(locale) } },
  );
}
将语言环境传递至UI并同步
<html lang dir>
属性。
tsx
export async function loader({ context }: Route.LoaderArgs) {
  let locale = getLocale(context);
  return data(
    { locale },
    { headers: { "Set-Cookie": await localeCookie.serialize(locale) } },
  );
}

entry-client-init - @rules/entry-client-init.md

entry-client-init - @rules/entry-client-init.md

Initialize i18next client with
htmlTag
detection.
ts
i18next.init({ detection: { order: ["htmlTag"], caches: [] } });
通过
htmlTag
检测初始化i18next客户端。
ts
i18next.init({ detection: { order: ["htmlTag"], caches: [] } });

entry-server-provider - @rules/entry-server-provider.md

entry-server-provider - @rules/entry-server-provider.md

Reuse the middleware instance in SSR with
I18nextProvider
.
tsx
<I18nextProvider i18n={getInstance(routerContext)}>
  <ServerRouter context={entryContext} url={request.url} />
</I18nextProvider>
在SSR中通过
I18nextProvider
复用中间件实例。
tsx
<I18nextProvider i18n={getInstance(routerContext)}>
  <ServerRouter context={entryContext} url={request.url} />
</I18nextProvider>

Resource Routes & Caching (HIGH)

资源路由与缓存(重要)

locales-resource-route - @rules/locales-resource-route.md

locales-resource-route - @rules/locales-resource-route.md

Serve
/api/locales/:lng/:ns
with validation and cache headers.
ts
return data(namespaces[ns.data], { headers });
提供
/api/locales/:lng/:ns
接口并添加验证和缓存头。
ts
return data(namespaces[ns.data], { headers });

UI Usage (MEDIUM)

UI使用(中等)

use-bound-t-in-loader - @rules/use-bound-t-in-loader.md

use-bound-t-in-loader - @rules/use-bound-t-in-loader.md

Use the bound
t()
in loaders and
useTranslation
in components.
ts
let t = getInstance(context).getFixedT(locale);
在加载器中使用绑定的
t()
,在组件中使用
useTranslation
ts
let t = getInstance(context).getFixedT(locale);

Not Found (MEDIUM)

404页面处理(中等)

not-found-i18n - @rules/not-found-i18n.md

not-found-i18n - @rules/not-found-i18n.md

Provide a 404 route so middleware runs and translations load.
提供404路由以确保中间件运行并加载翻译内容。