# i18n 介紹
### i18n的命名由來
基於他們的英文單字長度過長,常被簡稱成i18n(18意味著在「internationalization」這個單字中,去掉i和n有18個字母)
### 使用i18n的原因
**i18n就是國際化**
國際化意味著產品有適用於任何地方的「潛力」;在地化則是為了更適合於「特定」地方的使用。
對一項產品來說,國際化只需做一次,但在地化則要針對不同的區域各做一次。這兩者之間是互補的,並且兩者合起來才能讓一個系統適用於各地。
## 如何使用
**1.安裝 i18next 和 react-i18next**
> i18next 是提供所有翻譯功能的核心,而react-i18next 則為與 react / react native 一起使用提供了一些額外的功能。
>
**2.新增i18n.js**
```
import i18n from "i18next";
import { initReactI18next } from "react-i18next";
const resources = {
en: {
translation: {
"Welcome to React": "Welcome to React and react-i18next"
}
},
fr: {
translation: {
"Welcome to React": "Bienvenue à React et react-i18next"
}
}
};
i18n
.use(initReactI18next)
.init({
resources, //引入語言檔
lng: "en", //預設語言
fallbackLng: 'en', //若當前語言沒有對應的翻譯則使用這個語言
interpolation: {
escapeValue: false //是否要讓字詞 escaped 來防止 xss 攻擊,因為 React.js 已經做了,這裡設成 false
}
});
export default i18n;
```
補充:
XSS => 跨網站指令碼(英語:Cross-site scripting,通常簡稱為:XSS)是一種網站應用程式的安全漏洞攻擊,是代碼注入的一種。它允許惡意使用者將程式碼注入到網頁上,其他使用者在觀看網頁時就會受到影響
**3.新增字典檔**
* 手動輸入
> 把json檔放在 /public/locales/{語言名稱}/translation.json
* 從後端輸入
> i18next-http-backend 利用這個套件可以從後端傳入字典檔
* 使用官方套件自動掃描並翻譯
> https://www.i18next.com/overview/plugins-and-utils#extraction-tools
**4.在index.js的檔案裡面引入 i18n.js**
```
import './i18n.js'
```
**5.有四種方式可以翻譯文字**
* useTranslation(hook)
> 最常用到的
> 適用於函數組件
```
import React from 'react';
import { useTranslation } from 'react-i18next';
export function MyComponent() {
//t是拿來翻譯文件的
//i18n是用來做一些操作,例如:changeLanguage()切換語言、language獲取當前語言
const { t, i18n } = useTranslation();
return <p>{t('my translated text')}</p>
}
```
* withTranslation(HOC)
> 適用於類組件 (class or function)
```
import React from 'react';
import { withTranslation } from 'react-i18next';
function MyComponent({ t, i18n }) {
return <p>{t('my translated text')}</p>
}
export default withTranslation()(MyComponent);
```
* Translation(render prop)
> 適用於需要在 render 方法中獲取翻譯函數的情況。通過 Translation 組件,可以通過 render prop 的方式將翻譯函數傳遞給子組件,可以簡化程式碼並減少了在整個應用程序中傳遞翻譯函數的複雜性
```
import React from 'react';
import { Translation } from 'react-i18next';
export function MyComponent() {
return (
<Translation>
{t => (
<div>
<Header />
</div>
)}
</Translation>
)
}
```
* Trans
> 大多情況下不需使用
> Trans 提供了一種更直觀和便捷的方式來組織和處理多個文本段
```
import { Trans } from 'react-i18next';
function MyComponent({ person, messages }) {
const { name } = person;
const count = messages.length;
return (
<Trans i18nKey="userMessagesUnread" count={count}>
Hello <strong title={t('nameTitle')}>{{name}}</strong>, you have {{count}} unread message. <Link to="/msgs">Go to messages</Link>.
</Trans>
);
}
```
en.json
```
"nameTitle": "This is your name",
"userMessagesUnread_one": "Hello <1>{{name}}</1>, you have {{count}} unread message. <5>Go to message</5>.",
"userMessagesUnread_other": "Hello <1>{{name}}</1>, you have {{count}} unread messages. <5>Go to messages</5>.",
```
## 使用者手動切換語言
可以使用changeLanguage這個function做按鈕讓使用者自行選擇語言
```
function App ({ t }) {
const changeLanguage = (lng) => {
i18n.changeLanguage(lng);
}
return (
<div>
<button onClick={() => changeLanguage('de')}>de</button>
<button onClick={() => changeLanguage('en')}>en</button>
<h1>{t('Welcome to React')}</h1>
</div>
)
}
```
## 複數
根據輸入的值決定要顯示什麼文字
.json
```
{
"key_one": "item",
"key_other": "items",
"keyWithCount_one": "{{count}} item",
"keyWithCount_other": "{{count}} items"
}
```
sample
```
i18next.t('key', {count: 0}); // -> "items"
i18next.t('key', {count: 1}); // -> "item"
i18next.t('key', {count: 5}); // -> "items"
i18next.t('key', {count: 100}); // -> "items"
i18next.t('keyWithCount', {count: 0}); // -> "0 items"
i18next.t('keyWithCount', {count: 1}); // -> "1 item"
i18next.t('keyWithCount', {count: 5}); // -> "5 items"
i18next.t('keyWithCount', {count: 100}); // -> "100 items"
```
可以另外裝套件修改範圍
## 幾個常見的套件
官方有提供很多套件可以使用
https://www.i18next.com/overview/plugins-and-utils
1.i18next-browser-languagedetector 從使用者的瀏覽器取得語言
2.i18next-http-backend 讓語言檔透過 XMLHttpRequest 或 the fetch API 來載入
## 參考資料
大推 https://www.youtube.com/watch?v=2ai86BH6ok4
https://react.i18next.com/