API 参考

useModernI18n

useModernI18n 是插件提供的 React Hook,用于在组件中访问国际化状态和操作。

返回值

字段类型说明
languagestring当前语言代码
changeLanguage(lang: string) => Promise<void>切换语言
supportedLanguagesstring[]支持的语言列表(来自 localeDetection.languages
isLanguageSupported(lang: string) => boolean检查语言是否在支持列表中
isResourcesReadyboolean当前语言的翻译资源是否已加载完成
i18nInstanceI18nInstancei18next 实例(用于高级场景)

基本用法

import { useModernI18n } from '@modern-js/plugin-i18n/runtime';
import { useTranslation } from 'react-i18next';

function LanguageSwitcher() {
  const { language, changeLanguage, supportedLanguages } = useModernI18n();
  const { t } = useTranslation();

  return (
    <div>
      <p>{t('welcome')}</p>
      {supportedLanguages.map(lang => (
        <button
          key={lang}
          onClick={() => changeLanguage(lang)}
          disabled={lang === language}
        >
          {lang}
        </button>
      ))}
    </div>
  );
}

changeLanguage

切换语言时会依次执行:

  1. 更新 i18next 实例的语言
  2. 更新浏览器缓存(Cookie / LocalStorage,取决于 caches 配置)
  3. 更新 URL 路径前缀(如果启用了 localePathRedirect

changeLanguage 是异步函数,使用时需要 await

await changeLanguage('zh');

isResourcesReady

在自定义后端场景中,翻译资源需要异步加载,可以用 isResourcesReady 防止在资源未就绪时渲染:

function MyComponent() {
  const { isResourcesReady } = useModernI18n();
  const { t } = useTranslation();

  if (!isResourcesReady) {
    return <div>加载翻译中...</div>;
  }

  return <div>{t('content')}</div>;
}

isResourcesReady 会检查:i18n 实例是否已初始化、当前语言是否有资源正在加载、所有必需命名空间是否已加载完成。

带语言前缀的路由链接组件。

Props

Prop类型必填说明
tostring目标路径,不需要包含语言前缀
childrenReact.ReactNode链接内容
replaceboolean使用 history.replace 而非 push
stateany传递给目标路由的状态
其他 Link props继承自 @modern-js/runtime/routerLink 组件

用法

import { I18nLink } from '@modern-js/plugin-i18n/runtime';

<I18nLink to="/about">关于</I18nLink>
<I18nLink to="/contact" replace>联系</I18nLink>
<I18nLink to="/profile" state={{ from: 'home' }}>个人中心</I18nLink>

Runtime 插件 API

i18n 插件会在 onBeforeRender 钩子的 context 上挂载 changeLanguagei18nInstance,供其他 Runtime 插件使用:

import type { RuntimePlugin } from '@modern-js/runtime';

const myPlugin = (): RuntimePlugin => ({
  name: 'my-plugin',
  setup: api => {
    api.onBeforeRender(async context => {
      if (!context.changeLanguage) return; // 确保 i18n 插件已加载

      const lang = detectLangFromRequest(context);
      const supported = context.i18nInstance?.options?.supportedLngs ?? [];

      if (supported.includes(lang)) {
        try {
          await context.changeLanguage(lang);
        } catch (e) {
          console.error('Language change failed:', e);
        }
      }
    });
  },
});

注意事项:

  • 确保 i18n 插件在使用 context.changeLanguage 的插件之前注册
  • changeLanguage 在服务端不会更新 URL 路径,需要配合路由插件或手动处理

类型定义

I18nInstance

插件使用的 i18next 实例类型(i18next i18n 类型的子集,仅列出插件实际使用的字段):

interface I18nInstance {
  language: string;
  isInitialized: boolean;
  init: (options?: I18nInitOptions) => void | Promise<void>;
  changeLanguage: (lang: string) => void | Promise<void>;
  use: (plugin: any) => void;
  createInstance: (options?: I18nInitOptions) => I18nInstance;
  options?: {
    backend?: BackendOptions;
    supportedLngs?: string[];
    [key: string]: any;
  };
}

I18nSdkLoader

自定义后端加载函数的类型:

type I18nSdkLoader = (options: I18nSdkLoadOptions) => Promise<Resources>;

interface I18nSdkLoadOptions {
  lng?: string;      // 单个语言代码
  ns?: string;       // 单个命名空间
  lngs?: string[];   // 多个语言代码
  nss?: string[];    // 多个命名空间
  all?: boolean;     // 加载所有资源
}

type Resources = {
  [lng: string]: {
    [ns: string]: Record<string, any>;
  };
};

LanguageDetectorOptions

interface LanguageDetectorOptions {
  order?: string[];
  lookupQuerystring?: string;   // 默认 'lng'
  lookupCookie?: string;        // 默认 'i18next'
  lookupLocalStorage?: string;  // 默认 'i18nextLng'
  lookupSession?: string;
  lookupHeader?: string;        // 默认 'accept-language'
  lookupFromPathIndex?: number; // 默认 0
  caches?: false | string[];
  cookieMinutes?: number;       // 默认 525600(1年)
  cookieExpirationDate?: Date;
  cookieDomain?: string;
}

与 react-i18next 集成

插件完全兼容 react-i18next,两套 API 可以混用:

  • useTranslation(react-i18next):获取 t() 函数做翻译,这是最常用的 Hook
  • useModernI18n(插件提供):获取语言切换、支持列表、资源加载状态等插件层面的状态

大多数组件只需要 useTranslation,只有涉及语言切换或需要检查加载状态时才需要 useModernI18n

import { useTranslation } from 'react-i18next';
import { useModernI18n } from '@modern-js/plugin-i18n/runtime';

function App() {
  const { t } = useTranslation();                          // 翻译文本
  const { language, changeLanguage } = useModernI18n();    // 语言切换

  return (
    <div>
      <h1>{t('welcome')}</h1>
      <button onClick={() => changeLanguage('zh')}>中文</button>
      <button onClick={() => changeLanguage('en')}>English</button>
    </div>
  );
}

也可以通过 useModernI18n 获取 i18next 实例后直接调用 react-i18next 之外的能力:

const { i18nInstance } = useModernI18n();

// 动态添加翻译资源
i18nInstance.addResourceBundle('zh', 'translation', { key: '值' }, true, true);