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

i18next切换语言时,组件外常量翻译未同步更新的问题

问题原因

组件外部定义的PERMISSION_OPTIONS是在模块加载阶段就执行了i18next.t生成翻译文本,属于一次性计算的静态值。切换语言时,这个常量不会重新执行翻译逻辑,所以内容不会更新。而组件内部通过useTranslation获取的t函数,会在语言切换时触发组件重新渲染,自动拉取当前语言的翻译内容,因此能正常更新。

解决方案

方案一:将常量移至组件内部,用useMemo缓存

把选项定义放在组件内部,通过useMemo监听语言变化,触发重新生成翻译后的选项:

import React from "react"
import { useTranslation } from "react-i18next"

export const UsersAdministration: React.FC = () => {
  const { t, i18n } = useTranslation()

  // 语言变化时重新生成选项
  const PERMISSION_OPTIONS = React.useMemo(() => [
    {
      value: [PERMISSION_ADMIN_VALUE, PERMISSION_DEFAULT_VALUE],
      label: t("users.adminAndOperatorOptionLabel", { ns: "admin" }),
    },
    {
      value: [PERMISSION_USER_API_VALUE],
      label: t("users.userApiOptionLabel", { ns: "admin" }), // 修正原代码key重复问题
    },
  ], [t, i18n.language]) // 依赖语言状态,变化时重新计算

  const [permissionsFilter, setPermissionsFilter] = React.useState(PERMISSION_OPTIONS[0])

  return(
    <>
      <p>{t("title", { ns: "admin" })}</p>
      <p>{PERMISSION_OPTIONS[0].label}</p> {/* 现在语言切换会同步更新 */}
    </>
  )
}

方案二:封装成函数,按需调用

如果需要在多个组件复用选项逻辑,可封装成函数,每次使用时传入当前的t函数:

// 工具函数(可单独放文件或组件内部)
export const getPermissionOptions = (t: any) => [
  {
    value: [PERMISSION_ADMIN_VALUE, PERMISSION_DEFAULT_VALUE],
    label: t("users.adminAndOperatorOptionLabel", { ns: "admin" }),
  },
  {
    value: [PERMISSION_USER_API_VALUE],
    label: t("users.userApiOptionLabel", { ns: "admin" }),
  },
]

// 组件内使用
export const UsersAdministration: React.FC = () => {
  const { t } = useTranslation()
  const permissionOptions = getPermissionOptions(t)
  
  const [permissionsFilter, setPermissionsFilter] = React.useState(permissionOptions[0])

  return(
    <>
      <p>{t("title", { ns: "admin" })}</p>
      <p>{permissionOptions[0].label}</p>
    </>
  )
}

额外优化:语言选择器状态同步

原LanguageSelector中手动维护的currentLanguage状态容易和实际语言不同步,可直接从i18n实例获取:

import React from "react"
import clsx from "clsx"
import { useTranslation } from "react-i18next"

export const countries: { [key: string]: string } = {
    fr: "fr-FR",
    en: "en-GB",
}

export const LanguageSelector: React.FC<LanguageSelectorProps> = () => {
    const { t, i18n } = useTranslation()

    // 直接从i18n获取当前语言,无需手动维护state
    const currentLanguage = i18n.language.substring(0, 2)

    const changeLanguage = (lng: string) => {
        // 传入完整语言码,匹配i18n配置
        i18n.changeLanguage(countries[lng])
    }

    const availableCountries = Object.keys(countries)

    return (
        <div className={clsx("c-language-selector")}>
            <form>
                <label htmlFor="countrySelector" aria-label="Select country">
                    <select
                        id="countrySelector"
                        value={currentLanguage}
                        onChange={(event) => changeLanguage(event.target.value)}
                    >
                        {availableCountries.map((country) => (
                            <option key={country} value={country}>
                                {t(`availableTranslatedCountries.${country}`)}
                            </option>
                        ))}
                    </select>
                </label>
            </form>
        </div>
    )
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 06:20:45