Chrome扩展:React-i18next初始化后无法读取Chrome存储更新语言
问题描述
我正在用React、TypeScript和i18next开发Chrome扩展,将用户偏好语言存储在Chrome storage中。初始化时从存储获取语言并调用i18n.changeLanguage(),尽管语言切换看似成功,但组件仍渲染默认语言(vi-VN)。
相关代码文件
- i18n/index.ts:初始化i18next并读取存储中的语言
- i18n/settings.ts:定义i18next的语言、命名空间和配置选项
- index.tsx:包含语言切换按钮和翻译文本展示的主组件
- helper.tsx:渲染React组件的工具函数
复现步骤
- 安装扩展
- 选择与回退语言不同的语言(例如en-US)
- 观察UI仍显示回退语言(vi-VN)
- 点击对应语言的切换按钮(例如“切换为英语”)
- UI现在更新并显示正确语言
预期行为
UI应在初始加载时显示从Chrome存储获取的语言,无需手动切换。
实际行为
UI显示默认语言,直到手动触发语言切换。
疑问
- 我使用存储的语言初始化i18next的方式是否正确?如果不正确,更好的方式是什么?
- 为何调用
i18n.changeLanguage()后组件中的语言未更新? - 如何确保UI在初始加载时反映Chrome存储中的正确语言?
补充信息
- 已附上项目相关代码片段供参考
- i18n/index.ts中的控制台日志确认已从存储中获取到正确语言
使用技术栈
- Webpack
- ReactJs
- Typescript
- I18next
- React-i18next
代码片段
project/src/helper.tsx
import ReactDOM from 'react-dom/client'; import React from 'react'; export function renderReact( component: React.ReactNode, container?: HTMLElement, ) { if (!container) { container = document.createElement('div'); document.body.appendChild(container); } const root = ReactDOM.createRoot(container); root.render(<React.StrictMode>{component}</React.StrictMode>); }
project/src/index.tsx
import { useTranslation } from './i18n'; import { useState } from 'react'; const Home = () => { const { t, i18n } = useTranslation(); const [currentLanguage, setCurrentLanguage] = useState(i18n.language); /// 手动切换时能立即生效,工作正常 const handleChangeLanguage = async (newLanguage: string) => { setCurrentLanguage(newLanguage); await i18n.changeLanguage(newLanguage); await chrome.storage.sync.set({ language: newLanguage }); }; return ( <> Test: {t('s')} <div> <button className={cn('dl-bg-blue-900 dl-text-white dl-p-2 dl-rounded')} onClick={() => handleChangeLanguage('en-US')} > 切换为英语 </button> </div> <div> <button className={cn('dl-bg-blue-900 dl-text-white dl-p-2 dl-rounded')} onClick={() => handleChangeLanguage('vi-VN')} > 切换为越南语 </button> </div> </> ); } renderReact(<Home />);
project/src/i18n/index.ts
import i18n from 'i18next'; import resourcesToBackend from 'i18next-resources-to-backend'; import { defaultNS, getOptions, languages } from './settings'; import { initReactI18next, useTranslation as useTranslationOriginal, } from 'react-i18next'; i18n .use(initReactI18next) .use( resourcesToBackend((language: string, namespace: string) => require(`./locales/${language}/${namespace}.json`), ), ) .init({ ...getOptions(), }) .then(() => { chrome.storage.sync.get(['language'], (result: any) => { if (result.hasOwnProperty('language') && result.language) { console.log('i18n', result.language); // 输出: en-US i18n.changeLanguage(result.language); // 调用了语言切换,但index.tsx仍使用回退语言 } }); }); export function useTranslation( lng?: string, ns: string = defaultNS, options: any = {}, ) { const ret = useTranslationOriginal(ns, options); const { i18n } = ret; if ( lng && i18n.resolvedLanguage !== lng && Object.keys(languages).includes(lng) ) { i18n.changeLanguage(lng); } return ret; }
project/src/i18n/settings.ts
export const fallbackLng = 'vi-VN'; export const languages = { 'vi-VN': 'Vietnamese', 'en-US': 'English(US)', }; export const defaultNS = 'translation'; export function getOptions(lng = fallbackLng, ns = defaultNS) { return { // debug: true, supportedLngs: Object.keys(languages), fallbackLng, lng, fallbackNS: defaultNS, defaultNS, ns, }; }
project/src/i18n/locales/vi-VN/translation.json
{ "s": "Test Vietnamese" }
project/src/i18n/locales/en-US/translation.json
{ "s": "Test English" }
内容的提问来源于stack exchange,提问作者VQH DEV
相关产品推荐
相关产品推荐

