i18next、react-i18next实现国际化
简单使用
i18n.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| import i18n from "i18next";
import { initReactI18next } from "react-i18next";
i18n.use(initReactI18next).init({
resources: {
en: {
translation: {
React: "Welcome to React and react-i18next",
Vue: "Welcome to Vue",
},
},
},
lng: "en",
fallbackLng: "en",
interpolation: {
escapeValue: false,
},
});
export default i18n;
|
在入口文件引入
使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| import React from "react";
import { useTranslation } from "react-i18next";
export default function Home() {
const { t } = useTranslation();
console.log(t("Vue"));
return <h2>{t("Vue")}</h2>;
}
|
使用i18next-http-backend
插件
yarn add i18next-http-backend --dev
在 public 下面创建 locales 目录,在这个目录下创建和语言缩写对应的文件夹,其中放置 translation.json 文件。这个命名是约定好的,backend 插件会去按照这个路径请求资源文件。
i18n.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import Backend from "i18next-http-backend";
i18n
.use(Backend)
.use(initReactI18next)
.init({
lng: "en",
fallbackLng: "en",
interpolation: {
escapeValue: false,
},
});
export default i18n;
|
public/locales/en/translation.json
1 2 3 4 5 6 7
| {
"React": "Welcome to React",
"Vue": "Welcome to Vue"
}
|
##语言切换
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| import { Translation, useTranslation } from "react-i18next";
import "./App.css";
function App() {
const { t, i18n } = useTranslation();
const changeLanguage = (lng) => {
i18n.changeLanguage(lng);
};
return (
<>
<h1>{t("Vue")}</h1>
<button onClick={() => changeLanguage("en")}>en</button>
<button onClick={() => changeLanguage("zh")}>zh</button>
</>
);
}
export default App;
|
从上面的例子中能看出使用i18next-http-backend
的好处:翻译资源能做到按需加载。而不使用的时候,暂时还没找到能实现按需加载的办法。即使将翻译资源分离开,最后还是得import
进来,最后就一块打包了。
模块
i18next的namespace
可以实现将翻译资源分模块。这样子就能实现一个较好的按需加载,尤其是大项目里翻译资源非常多的时候。
i18n.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import Backend from "i18next-http-backend";
i18n
.use(Backend)
.use(initReactI18next)
.init({
lng: "en",
fallbackLng: "en",
interpolation: {
escapeValue: false,
},
defaultNS: "common",
backend: {
loadPath: "/locales/{{lng}}/{{ns}}.json",
},
});
export default i18n;
|
App.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
| import { useTranslation } from "react-i18next";
import { useState } from "react";
import "./App.css";
function App() {
const { t, i18n } = useTranslation();
const changeLanguage = (lng) => {
i18n.changeLanguage(lng);
};
const [show, setShow] = useState(false);
const addPart = () => {
i18n.loadNamespaces("addPart", (err) => {
if (!err) {
setShow(true);
}
});
};
return (
<>
<h1>{t("React")}</h1>
<button onClick={() => changeLanguage("en")}>en</button>
<button onClick={() => changeLanguage("zh")}>zh</button>
<button onClick={() => changeLanguage("fr")}>fr</button>
<button onClick={() => addPart()}>addPart</button>
{/* 也能使用t("addPart:name")的形式 */}
{show && <h1>{t("name", { ns: "addPart" })}</h1>}
</>
);
}
export default App;
|
loadNamespaces
时,不只是加载当前语言的,而且还会加载fallbackLng
的,应该是是保险之类的原因。上面的例子fallbackLng
是en
,当前语言为zh
时,添加新模块就加载了zh
和en
的对应模块。
当当前语言就是fallbackLng
时,则不会多加载。
完善
上面其实还是有一个问题,当加载某种语言的翻译资源时,默认都会加载translation.json
,而该文件实际并没有内容
猜测是因为没有设置ns
,而默认的ns
可能是translation
。
i18n.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import Backend from "i18next-http-backend";
i18n
.use(Backend)
.use(initReactI18next)
.init({
fallbackLng: "zh",
ns: ['common'],
defaultNS: 'common',
interpolation: {
escapeValue: false,
},
backend: {
loadPath: "/locales/{{lng}}/{{ns}}.json",
}
});
export default i18n;
|