You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何减少React+TypeScript项目中useTranslation()的重复调用

优化 React + TypeScript + i18next 多语言实现方案

首先要明确:i18next 本身是全局状态管理,当你在任意位置调用 i18n.changeLanguage() 后,所有使用 t() 函数的组件都会自动重新渲染并加载对应语言文本,完全不需要每个组件都重复编写 useEffect 监听语言变化——这是你当前冗余代码的核心原因。

下面是几种具体的优化方案:

方案1:全局统一管理语言切换,组件仅按需获取t函数

这是最常用的优化方式,把语言切换逻辑集中在全局组件(比如头部语言选择器),业务组件只需要简单获取翻译函数即可。

  1. 编写全局语言选择器
// components/LanguageSelector.tsx
import { useTranslation } from 'react-i18next';

type SupportedLang = 'en' | 'jp' | 'fr';

const LanguageSelector = () => {
  const { i18n } = useTranslation();

  const switchLanguage = (lng: SupportedLang) => {
    i18n.changeLanguage(lng);
    // 可选:把用户偏好语言存入localStorage,下次打开自动恢复
    localStorage.setItem('preferred-lang', lng);
  };

  return (
    <div className="language-selector">
      <button onClick={() => switchLanguage('en')}>English</button>
      <button onClick={() => switchLanguage('jp')}>日本語</button>
      <button onClick={() => switchLanguage('fr')}>Français</button>
    </div>
  );
};

export default LanguageSelector;
  1. 业务组件简化写法
// components/ExampleComponent.tsx
import { useTranslation } from 'react-i18next';

const ExampleComponent = () => {
  const { t } = useTranslation(); // 仅需这一行

  return (
    <div>
      <h1>{t('hello-world')}</h1>
      <p>{t('welcome-message')}</p>
    </div>
  );
};

export default ExampleComponent;
  1. (可选)初始化时加载用户偏好语言
// App.tsx
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import enJson from './assets/locales/en.json';
import jpJson from './assets/locales/jp.json';
import frJson from './assets/locales/fr.json';

// 从localStorage读取保存的语言,默认用英文
const savedLang = localStorage.getItem('preferred-lang') as 'en' | 'jp' | 'fr' || 'en';

i18n.use(initReactI18next).init({
  debug: true,
  resources: {
    en: { translation: enJson },
    jp: { translation: jpJson },
    fr: { translation: frJson },
  },
  lng: savedLang,
  fallbackLng: false,
  returnEmptyString: false,
  interpolation: { escapeValue: false },
});

方案2:封装自定义Hook,统一组件内语言逻辑

如果少数组件需要独立控制语言(场景少见),可以把重复的逻辑封装成自定义Hook:

// hooks/useLocalization.ts
import { useState, useEffect } from 'react';
import { useTranslation } from 'react-i18next';

type SupportedLang = 'en' | 'jp' | 'fr';

export const useLocalization = (initialLang?: SupportedLang) => {
  const { t, i18n } = useTranslation();
  const [lang, setLang] = useState<SupportedLang>(initialLang || i18n.language as SupportedLang);

  useEffect(() => {
    if (lang !== i18n.language) {
      i18n.changeLanguage(lang);
    }
  }, [lang, i18n]);

  return { t, lang, setLang };
};

组件使用时直接调用:

// components/ExampleComponent.tsx
import { useLocalization } from '../hooks/useLocalization';

const ExampleComponent = () => {
  const { t, setLang } = useLocalization();

  return (
    <div>
      <h1>{t('hello-world')}</h1>
      <button onClick={() => setLang('jp')}>切换为日语</button>
    </div>
  );
};

方案3:使用高阶组件(HOC)批量注入翻译能力

如果你习惯HOC写法,可以封装一个HOC给组件注入t和i18n:

// hoc/withTranslation.ts
import React from 'react';
import { useTranslation, UseTranslationResponse } from 'react-i18next';

type WithTranslationProps = UseTranslationResponse;

export const withTranslation = <P extends object>(Component: React.ComponentType<P & WithTranslationProps>) => {
  return (props: P) => {
    const translationProps = useTranslation();
    return <Component {...props} {...translationProps} />;
  };
};

使用方式:

// components/ExampleComponent.tsx
import React from 'react';
import { withTranslation, WithTranslationProps } from '../hoc/withTranslation';

type ExampleProps = WithTranslationProps;

const ExampleComponent: React.FC<ExampleProps> = ({ t }) => {
  return <h1>{t('hello-world')}</h1>;
};

export default withTranslation(ExampleComponent);

额外优化:给t函数添加TypeScript类型提示

为避免翻译key拼写错误,可以基于locale JSON生成类型,让t函数支持自动补全和类型检查:

// types/locales.ts
import enJson from '../assets/locales/en.json';

// 基于英文JSON生成翻译key的类型
type TranslationKeys = keyof typeof enJson;

declare module 'react-i18next' {
  interface CustomTypeOptions {
    defaultNS: 'translation';
    resources: {
      translation: typeof enJson;
    };
  }
}

将这个类型文件加入tsconfig.json的include数组,之后在使用t()时,输入不存在的key会直接触发TypeScript报错。

内容的提问来源于stack exchange,提问作者shinchan97

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 17:19:02