Hướng dẫn một số bước cơ bản để setup đa ngôn ngữ i18n cho ứng dụng của bạn.
Link thư viện: https://react.i18next.com/guides/quick-start
Link demo online: https://codesandbox.io/s/react-i18n-c0yrc4?file=/src/App.tsx
1. Tạo ứng dụng React cơ bản
- Tạo một folder với tên
react-i18n-app
- Mở cmd và gõ:
npx create-react-app .
- Đợi một lúc để ứng dụng được khởi tạo
- Trong cmd đó ta gõ tiếp:
cd react-i18n-app
- Cài đặt hai package để hỗ trợ đa ngôn ngữ:
npm install react-i18next i18next
- Khởi chạy ứng dụng:
npm start
2. Giao diện ban đầu
- Mở file bên dưới và thêm thư viện bootstrap để css cho nhanh
1 2 3 4 5 6 7 | <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>link</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css<span class="token punctuation">"</span></span> <span class="token attr-name">rel</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>stylesheet<span class="token punctuation">"</span></span> <span class="token attr-name">integrity</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ<span class="token punctuation">"</span></span> <span class="token attr-name">crossorigin</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>anonymous<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span> |
- Code giao diện tí nhỉ
1 2 3 4 5 6 7 8 9 10 11 12 13 | <span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">function</span> <span class="token function">App</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span>div className<span class="token operator">=</span><span class="token string">"container text-center"</span><span class="token operator">></span> <span class="token operator"><</span>h1 className<span class="token operator">=</span><span class="token string">"my-3"</span><span class="token operator">></span>React i18n<span class="token operator"><</span><span class="token operator">/</span>h1<span class="token operator">></span> <span class="token operator"><</span>button className<span class="token operator">=</span><span class="token string">"btn btn-primary me-2"</span><span class="token operator">></span>Change language <span class="token constant">EN</span> <span class="token operator">-</span> <span class="token constant">VI</span><span class="token operator"><</span><span class="token operator">/</span>button<span class="token operator">></span> <span class="token operator"><</span>span className<span class="token operator">=</span><span class="token string">"badge rounded-pill text-bg-danger me-1"</span><span class="token operator">></span>Search<span class="token operator"><</span><span class="token operator">/</span>span<span class="token operator">></span> <span class="token operator"><</span>span className<span class="token operator">=</span><span class="token string">"badge rounded-pill text-bg-danger me-1"</span><span class="token operator">></span>Cancel<span class="token operator"><</span><span class="token operator">/</span>span<span class="token operator">></span> <span class="token operator"><</span>span className<span class="token operator">=</span><span class="token string">"badge rounded-pill text-bg-danger me-1"</span><span class="token operator">></span>Delete<span class="token operator"><</span><span class="token operator">/</span>span<span class="token operator">></span> <span class="token operator"><</span>span className<span class="token operator">=</span><span class="token string">"badge rounded-pill text-bg-danger me-1"</span><span class="token operator">></span>Save<span class="token operator"><</span><span class="token operator">/</span>span<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>div<span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> |
- Giao diện sẽ được cơ bản như này
- Mong muốn khi click vào button
Change language EN - VI
sẽ đổi text của bốn label tương ứng
3. Tạo các file ngôn ngữ Anh – Việt
- Tạo file tiếng Anh
1 2 3 4 5 6 7 8 9 10 11 | <span class="token punctuation">{</span> <span class="token property">"common"</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"button"</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"search"</span><span class="token operator">:</span> <span class="token string">"Search"</span><span class="token punctuation">,</span> <span class="token property">"cancel"</span><span class="token operator">:</span> <span class="token string">"Cancel"</span><span class="token punctuation">,</span> <span class="token property">"delete"</span><span class="token operator">:</span> <span class="token string">"Delete"</span><span class="token punctuation">,</span> <span class="token property">"save"</span><span class="token operator">:</span> <span class="token string">"Save"</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
- Tạo file tiếng Việt
1 2 3 4 5 6 7 8 9 10 11 | <span class="token punctuation">{</span> <span class="token property">"common"</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"button"</span><span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"search"</span><span class="token operator">:</span> <span class="token string">"Tìm kiếm"</span><span class="token punctuation">,</span> <span class="token property">"cancel"</span><span class="token operator">:</span> <span class="token string">"Hủy"</span><span class="token punctuation">,</span> <span class="token property">"delete"</span><span class="token operator">:</span> <span class="token string">"Xóa"</span><span class="token punctuation">,</span> <span class="token property">"save"</span><span class="token operator">:</span> <span class="token string">"Lưu"</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
4. Config ngôn ngữ
- Để tiện theo dõi thì mình tạo file riêng để config ngôn ngữ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <span class="token keyword">import</span> i18next <span class="token keyword">from</span> <span class="token string">'i18next'</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> initReactI18next <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'react-i18next'</span> <span class="token keyword">import</span> translationEN <span class="token keyword">from</span> <span class="token string">'../locales/en/translation.json'</span> <span class="token keyword">import</span> translationVI <span class="token keyword">from</span> <span class="token string">'../locales/vi/translation.json'</span> <span class="token keyword">const</span> resources <span class="token operator">=</span> <span class="token punctuation">{</span> en<span class="token operator">:</span> <span class="token punctuation">{</span> translation<span class="token operator">:</span> translationEN <span class="token punctuation">}</span><span class="token punctuation">,</span> vi<span class="token operator">:</span> <span class="token punctuation">{</span> translation<span class="token operator">:</span> translationVI <span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> i18next<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>initReactI18next<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">init</span><span class="token punctuation">(</span><span class="token punctuation">{</span> lng<span class="token operator">:</span> <span class="token string">'en'</span><span class="token punctuation">,</span> <span class="token comment">// if you're using a language detector, do not define the lng option</span> debug<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span> resources <span class="token punctuation">}</span><span class="token punctuation">)</span> |
- Load file này vào trong file index luôn
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <span class="token keyword">import</span> <span class="token string">'./config-translation'</span> <span class="token comment">// <=== thêm here</span> <span class="token keyword">import</span> React <span class="token keyword">from</span> <span class="token string">'react'</span> <span class="token keyword">import</span> ReactDOM <span class="token keyword">from</span> <span class="token string">'react-dom/client'</span> <span class="token keyword">import</span> <span class="token string">'./index.css'</span> <span class="token keyword">import</span> App <span class="token keyword">from</span> <span class="token string">'./App'</span> <span class="token keyword">import</span> reportWebVitals <span class="token keyword">from</span> <span class="token string">'./reportWebVitals'</span> <span class="token keyword">const</span> root <span class="token operator">=</span> ReactDOM<span class="token punctuation">.</span><span class="token function">createRoot</span><span class="token punctuation">(</span>document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'root'</span><span class="token punctuation">)</span><span class="token punctuation">)</span> root<span class="token punctuation">.</span><span class="token function">render</span><span class="token punctuation">(</span> <span class="token operator"><</span>React<span class="token punctuation">.</span>StrictMode<span class="token operator">></span> <span class="token operator"><</span>App <span class="token operator">/</span><span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>React<span class="token punctuation">.</span>StrictMode<span class="token operator">></span> <span class="token punctuation">)</span> <span class="token comment">// If you want to start measuring performance in your app, pass a function</span> <span class="token comment">// to log results (for example: reportWebVitals(console.log))</span> <span class="token comment">// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals</span> <span class="token function">reportWebVitals</span><span class="token punctuation">(</span><span class="token punctuation">)</span> |
5. Hiển thị
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 | <span class="token keyword">import</span> <span class="token punctuation">{</span> useTranslation <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">"react-i18next"</span><span class="token punctuation">;</span> <span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">function</span> <span class="token function">App</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">const</span> <span class="token punctuation">{</span> t <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token function">useTranslation</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">className</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>container text-center<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h1</span> <span class="token attr-name">className</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>my-3<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token plain-text">React i18n</span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h1</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>button</span> <span class="token attr-name">className</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>btn btn-primary me-2<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token plain-text">Change language EN - VI</span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>button</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>span</span> <span class="token attr-name">className</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>badge rounded-pill text-bg-danger me-1<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token punctuation">{</span><span class="token function">t</span><span class="token punctuation">(</span><span class="token string">"common.button.search"</span><span class="token punctuation">)</span><span class="token punctuation">}</span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>span</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>span</span> <span class="token attr-name">className</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>badge rounded-pill text-bg-danger me-1<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token punctuation">{</span><span class="token function">t</span><span class="token punctuation">(</span><span class="token string">"common.button.cancel"</span><span class="token punctuation">)</span><span class="token punctuation">}</span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>span</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>span</span> <span class="token attr-name">className</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>badge rounded-pill text-bg-danger me-1<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token punctuation">{</span><span class="token function">t</span><span class="token punctuation">(</span><span class="token string">"common.button.delete"</span><span class="token punctuation">)</span><span class="token punctuation">}</span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>span</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>span</span> <span class="token attr-name">className</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>badge rounded-pill text-bg-danger me-1<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token punctuation">{</span><span class="token function">t</span><span class="token punctuation">(</span><span class="token string">"common.button.save"</span><span class="token punctuation">)</span><span class="token punctuation">}</span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>span</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span> <span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> |
6. Click chuyển ngôn ngữ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <span class="token keyword">import</span> <span class="token punctuation">{</span> useTranslation <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'react-i18next'</span> <span class="token keyword">import</span> <span class="token punctuation">{</span> useState <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'react'</span> <span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">function</span> <span class="token function">App</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">const</span> <span class="token punctuation">{</span> t<span class="token punctuation">,</span> i18n <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token function">useTranslation</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">const</span> <span class="token punctuation">[</span>currentLanguage<span class="token punctuation">,</span> setCurrentLanguage<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useState</span><span class="token punctuation">(</span><span class="token string">'en'</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>button</span> <span class="token attr-name">className</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>btn btn-primary me-2<span class="token punctuation">"</span></span> <span class="token attr-name">onClick</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token function">setCurrentLanguage</span><span class="token punctuation">(</span>currentLanguage <span class="token operator">===</span> <span class="token string">"en"</span> <span class="token operator">?</span> <span class="token string">"vi"</span> <span class="token operator">:</span> <span class="token string">"en"</span><span class="token punctuation">)</span> i18n<span class="token punctuation">.</span><span class="token function">changeLanguage</span><span class="token punctuation">(</span>currentLanguage <span class="token operator">===</span> <span class="token string">"en"</span> <span class="token operator">?</span> <span class="token string">"vi"</span> <span class="token operator">:</span> <span class="token string">"en"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">}</span></span> <span class="token punctuation">></span></span><span class="token plain-text"> Change language EN - VI </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>button</span><span class="token punctuation">></span></span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> |
7. Demo
Demo online tại đây: https://codesandbox.io/s/react-i18n-c0yrc4?file=/src/App.tsx