Setup đa ngôn ngữ i18n trong ReactJS
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õ: 
npm create vite@latest - Select a framework: 
React - Select a variant: 
Javascript - Use rolldown-vite: 
No - Install with npm and start now? 
Yes - Đợi một lúc để ứng dụng được khởi tạo
 - 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
 
<link
  href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css"
  rel="stylesheet"
  integrity="sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ"
  crossorigin="anonymous"
/>
- Code giao diện tí nhỉ
 
import './App.css'
export default function App() {
  return (
    <div className="container text-center">
      <h1 className="my-3">React i18n</h1>
      <button className="btn btn-primary me-2">Change language EN - VI</button>
      <span className="badge rounded-pill text-bg-danger me-1">Search</span>
      <span className="badge rounded-pill text-bg-danger me-1">Cancel</span>
      <span className="badge rounded-pill text-bg-danger me-1">Delete</span>
      <span className="badge rounded-pill text-bg-danger me-1">Save</span>
    </div>
  )
}
- Giao diện sẽ được cơ bản như này
 

- Mong muốn khi click vào button 
Change language EN - VIsẽ đổi text của bốn label bên cạnh 
3. Tạo các file ngôn ngữ Anh - Việt
- Tạo file tiếng Anh
 
{
  "common": {
    "button": {
      "search": "Search",
      "cancel": "Cancel",
      "delete": "Delete",
      "save": "Save"
    }
  }
}
- Tạo file tiếng Việt
 
{
  "common": {
    "button": {
      "search": "Tìm kiếm",
      "cancel": "Hủy",
      "delete": "Xóa",
      "save": "Lưu"
    }
  }
}
4. Config ngôn ngữ
- Để tiện theo dõi thì mình tạo file riêng để config ngôn ngữ
 
import i18next from 'i18next'
import { initReactI18next } from 'react-i18next'
import translationEN from '../locales/en/translation.json'
import translationVI from '../locales/vi/translation.json'
const resources = {
  en: { translation: translationEN },
  vi: { translation: translationVI }
};
i18next.use(initReactI18next).init({
  lng: 'en', // if you're using a language detector, do not define the lng option
  debug: true,
  resources
})
- Load file này vào trong file index luôn
 
import './config-translation' // <=== thêm here
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import './index.css'
import App from './App.jsx'
createRoot(document.getElementById('root')).render(
  <StrictMode>
    <App />
  </StrictMode>,
)
5. Hiển thị
import { useTranslation } from "react-i18next";
import './App.css'
export default function App() {
  const { t } = useTranslation();
  return (
    <div className="container text-center">
      <h1 className="my-3">React i18n</h1>
      <button className="btn btn-primary me-2">Change language EN - VI</button>
      <span className="badge rounded-pill text-bg-danger me-1">
        {t("common.button.search")}
      </span>
      <span className="badge rounded-pill text-bg-danger me-1">
        {t("common.button.cancel")}
      </span>
      <span className="badge rounded-pill text-bg-danger me-1">
        {t("common.button.delete")}
      </span>
      <span className="badge rounded-pill text-bg-danger me-1">
        {t("common.button.save")}
      </span>
    </div>
  );
}
6. Click chuyển ngôn ngữ
Thêm sự kiện onClick để chuyển ngôn ngữ
import { useTranslation } from 'react-i18next'
import './App.css'
import { useState } from 'react'
export default function App() {
  const { t, i18n } = useTranslation()
  const [currentLanguage, setCurrentLanguage] = useState('en')
  return (
    <div className="container text-center">
      <h1 className="my-3">React i18n</h1>
      <button
        className="btn btn-primary me-2"
        onClick={() => {
          setCurrentLanguage(currentLanguage === "en" ? "vi" : "en")
          i18n.changeLanguage(currentLanguage === "en" ? "vi" : "en")
        }}
      >
        Change language EN - VI
      </button>
      <span className="badge rounded-pill text-bg-danger me-1">
        {t("common.button.search")}
      </span>
      <span className="badge rounded-pill text-bg-danger me-1">
        {t("common.button.cancel")}
      </span>
      <span className="badge rounded-pill text-bg-danger me-1">
        {t("common.button.delete")}
      </span>
      <span className="badge rounded-pill text-bg-danger me-1">
        {t("common.button.save")}
      </span>
    </div>
  )
}
7. Demo
Demo online tại đây: https://codesandbox.io/s/react-i18n-c0yrc4?file=/src/App.tsx
All Rights Reserved