# 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/