廊坊电子网站建设,wordpress二级开发,中小微企业纳税申报,电商网站开发pythonref: https://www.i18next.com/ i18next是一个用JavaScript编写的国际化框架。
i18next为您提供了一个完整的解决方案#xff0c;本地化您的产品从web端到移动端和桌面端。
在react项目中安i18next依赖#xff1a;
i18nextreact-i18nexti18next-browser-languagedetector本地化您的产品从web端到移动端和桌面端。
在react项目中安i18next依赖
i18nextreact-i18nexti18next-browser-languagedetector用于检测用户语言
npm install i18next react-i18next i18next-browser-languagedetector创建i18n.js文件
import i18n from i18next;
import { initReactI18next } from react-i18next;
import LanguageDetector from i18next-browser-languagedetector;i18n.use(LanguageDetector) // 检测用户语言.use(initReactI18next) // 将i18n实例传递给react-i18next.init({ // 初始化 i18nextdebug: true,fallbackLng: en,interpolation: {escapeValue: false, // React已经转义了},resources: {en: {translation: {// 此处放置翻译内容description: {part1: Edit 1src/App.js/1 and save to reload.,part2: Learn React}}},de: {translation: {description: {part1: Ändere 1src/App.js/1 und speichere um neu zu laden.,part2: Lerne React}}}}});export default i18n;在index.js中导入i18n.js
React18.0.0的版本
import React from react;
import { createRoot } from react-dom/client;
import ./index.css;
import App from ./App;// 导入 i18n (需要绑定)
import ./i18n;const root createRoot(document.getElementById(root))
root.render(React.StrictModeApp //React.StrictMode
);更早的版本
import React from react;
import ReactDOM from react-dom;
import ./index.css;
import App from ./App;// 导入 i18n (需要绑定)
import ./i18n;ReactDOM.render(React.StrictModeApp //React.StrictMode,document.getElementById(root)
);使用在第一个文本中使用了Trans组件在第二个文本中使用了useTranslation (hook) :
// App.js
import logo from ./logo.svg;
import ./App.css;
import { useTranslation, Trans } from react-i18next;function App() {const { t } useTranslation();return (div classNameAppheader classNameApp-headerimg src{logo} classNameApp-logo altlogo /pTrans i18nKeydescription.part1Edit codesrc/App.js/code and save to reload./Trans/paclassNameApp-linkhrefhttps://reactjs.orgtarget_blankrelnoopener noreferrer{t(description.part2)}/a/header/div);
}export default App;语言切换器
// App.jsx
...const lngs {en: { nativeName: English },de: { nativeName: Deutsch }
};function App() {
...img src{logo} classNameApp-logo altlogo /div{Object.keys(lngs).map((lng) (button key{lng} style{{ fontWeight: i18n.resolvedLanguage lng ? bold : normal }} typesubmit onClick{() i18n.changeLanguage(lng)}{lngs[lng].nativeName}/button))}/divpTrans i18nKeydescription.part1Edit codesrc/App.js/code and save to reload./Trans/p
...
}自i18next v21以来i18next. resolvedlanguage被设置为当前解析的语言并且可以用作主要使用的语言上例中有使用。
i18next.language vs. i18next.languages
i18next.language;
// 设置为当前检测或设置的语言i18next.languages;
// 设置为将用于查找翻译值的语言代码数组
// 设置语言后将使用新的语言代码填充此数组
// 除非被覆盖否则将使用该代码的不太特定的版本填充此数组以用于回退目的然后是回退语言列表// 初始化回退语言
i18next.init({fallbackLng: [es, fr, en-US, dev]
});
// 改变语言
i18next.changeLanguage(en-US-xx);
// 新语言和它的更一般的形式然后是回退
i18next.languages; // [en-US-xx, en-US, en, es, fr, dev]
// 再次改变语言
i18next.changeLanguage(de-DE);
// 不保留上一次设置的语言
i18next.languages; // [de-DE, de, es, fr, en-US, dev]处理复数和插值
示例计算语言变化的次数
// App.js
...
import { useState } from react;...function App() {...const [count, setCounter] useState(0);return (...div{Object.keys(lngs).map((lng) (button key{lng} style{{ fontWeight: i18n.resolvedLanguage lng ? bold : normal }} typesubmit onClick{() {i18n.changeLanguage(lng);setCounter(count 1);}}{lngs[lng].nativeName}/button))}/divpi{t(counter, { count })}/i/p...);
}export default App;拓展翻译源
// i18n.js
......resources: {en: {translation: {description: {part1: Edit 1src/App.js/1 and save to reload.,part2: Learn React},counter_one: Changed language just once,counter_other: Changed language already {{count}} times}},de: {translation: {description: {part1: Ändere 1src/App.js/1 und speichere um neu zu laden.,part2: Lerne React},counter_one: Die Sprache wurde erst ein mal gewechselt,counter_other: Die Sprache wurde {{count}} mal gewechselt}}}...i18next会根据count数值选择正确的复数格式了解更多 - Plurals 处理多种复数
// 翻译源:
{key_zero: zero,key_one: singular,key_two: two,key_few: few,key_many: many,key_other: other
}// 使用:
t(key, {count: 0}); // - zero
t(key, {count: 1}); // - singular
t(key, {count: 2}); // - two
t(key, {count: 3}); // - few
t(key, {count: 4}); // - few
t(key, {count: 5}); // - few
t(key, {count: 11}); // - many
t(key, {count: 99}); // - many
t(key, {count: 100}); // - other这些复数是用Intl API简化的。你可能需要Polyfill Intl.PluralRules的API如果它不可用它将退回到i18next JSON格式v3复数处理。
注变量名必须是count并且必须存在i18next.t(key, {count: 1});
polyfill 只需导入它以确保Intl.PluralRules在您的环境中可用:
npm install intl-pluralrulesimport intl-pluralrules如果Intl.PluralRules已经存在包含一个selectRange()方法并且支持多种语言环境那么将不会加载polyfill。
格式化
在i18next和Luxon的帮助下使用不同的日期格式来处理日期和时间。
npm install luxon创建一个Footer组件并在App.js中引用
import ./Footer.css;const Footer ({ t }) (div classNameFooterdiv{t(footer.date, { date: new Date() })}/div/div
);export default Footer;// 在App.js中引入并这样使用
// Footer t{t} /导入luxon并定义一个格式函数如文档中所述并添加新的翻译key:
...
import { DateTime } from luxon;....init({debug: true,fallbackLng: en,interpolation: {escapeValue: false,// format: (value, format, lng) { // 遗留使用方法// if (value instanceof Date) {// return DateTime.fromJSDate(value).setLocale(lng).toLocaleString(DateTime[format])// }// return value;// }},resources: {en: {translation: {...footer: {date: Today is {{date, DATE_HUGE}}}}},de: {translation: {...footer: {date: Heute ist {{date, DATE_HUGE}}}}}}});// 新的使用方法
i18n.services.formatter.add(DATE_HUGE, (value, lng, options) {return DateTime.fromJSDate(value).setLocale(lng).toLocaleString(DateTime.DATE_HUGE)
});export default i18n;English German Context
基于当前时间的特定问候信息即早上、晚上等。
创建一个getGreetingTime函数并使用结果作为页脚翻译的内容:
// Footer.jsx
import { DateTime } from luxon;
import ./Footer.css;const getGreetingTime (d DateTime.now()) {const split_afternoon 12; // 24小时制分配下午const split_evening 17; // 24小时制分配晚上const currentHour parseFloat(d.toFormat(hh));if (currentHour split_afternoon currentHour split_evening) {return afternoon;} else if (currentHour split_evening) {return evening;}return morning;
}const Footer ({ t }) (div classNameFooterdiv{t(footer.date, { date: new Date(), context: getGreetingTime() })}/div/div
);export default Footer;添加i18next-http-backend插件从服务器加载翻译和翻译key:
npm install i18next-http-backend...
import Backend from i18next-http-backend;i18n.use(Backend).use(LanguageDetector).use(initReactI18next).init({...resources: {en: {translation: {...footer: {date: Today is {{date, DATE_HUGE}},date_morning: Good morning! Today is {{date, DATE_HUGE}} | Have a nice day!,date_afternoon: Good afternoon! It\s {{date, DATE_HUGE}},date_evening: Good evening! Today was the {{date, DATE_HUGE}}}}},de: {translation: {...footer: {date: Heute ist {{date, DATE_HUGE}},date_morning: Guten Morgen! Heute ist {{date, DATE_HUGE}} | Wünsche einen schönen Tag!,date_afternoon: Guten Tag! Es ist {{date, DATE_HUGE}},date_evening: Guten Abend! Heute war {{date, DATE_HUGE}}}}}}});...效果 分离翻译和代码
在i18next-http-backend的帮助下将翻译从代码中分离出来并将它们放在专用的json文件中。
将翻译文件移动到public文件夹 移除翻译代码
import i18n from i18next;
import { initReactI18next } from react-i18next;
import LanguageDetector from i18next-browser-languagedetector;
import Backend from i18next-http-backend;
import { DateTime } from luxon;i18n.use(Backend).use(LanguageDetector).use(initReactI18next).init({debug: true,fallbackLng: en,interpolation: {escapeValue: false,// format: (value, format, lng) {// if (value instanceof Date) {// return DateTime.fromJSDate(value).setLocale(lng).toLocaleString(DateTime[format])// }// return value;// }}});i18n.services.formatter.add(DATE_HUGE, (value, lng, options) {return DateTime.fromJSDate(value).setLocale(lng).toLocaleString(DateTime.DATE_HUGE)
});export default i18n;现在翻译是异步加载的啦所以用一个Subspense组件包装你的应用来确保你防止以下错误:
Uncaught Error: App suspended while rendering, but no fallback UI was specified.
// App.jsx
import { Suspense } from react;function App() {...
}// 在这里app从页面捕获suspense以防翻译未加载完成
export default function WrappedApp() {return (Suspense fallback...is loadingApp //Suspense);
}如果你想支持一种新的语言你只需要创建一个新的文件夹和一个新的翻译json文件。这使您可以直接将翻译json发送给一些专业的翻译人员。或者如果您正在使用翻译管理系统您可以使用cli同步文件。
具体代码可在这里查看。
多个namespaces
将翻译拆分为多个文件使用在调用useTranslation时指定它
const { t } useTranslation([translation, common]);
// ...
// t(look.deep, { ns: common })[withTranslation](withTranslation (HOC) - react-i18next documentation)
withTranslation([translation, common])(MyComponent);
// ...
// t(look.deep, { ns: common })[Translation](Translation (render prop) - react-i18next documentation)
Translation ns{[translation, common]}
{(t) p{t(look.deep, { ns: common })}/p
}
/Translation