在 React 項目中配置 react-i18next 實現中英文切換,步驟如下:

一、安裝依賴

首先確保已安裝核心庫:

npm install react-i18next i18next i18next-http-backend  # 核心庫 + 加載語言文件的插件

二、配置 i18n

1. 創建語言文件

在 public 目錄下創建語言文件(推薦用 JSON 格式),結構如下:

public/
  locales/
    en/
      translation.json  # 英文翻譯
    zh/
      translation.json  # 中文翻譯

內容:

  • public/locales/en/translation.json
{
    "back": "Back",
    "createProject": "Create Project",
    "allStatus": "All Status",
    "labeling": "Labeling",
    "confirming": "Confirming",
    "completed": "Completed",
    "startDate": "Start Date",
    "endDate": "End Date",
    "searchPlaceholder": "Enter keywords to search...",
    "noProjects": "No data, you haven't created any projects yet!",
    "noFilteredProjects": "No projects match the filter criteria, please adjust the filters!",
    "loadingTip": "Loading...",
    "productType": "Product Type",
    "unknown": "Unknown",
    "confirmDelete": "Confirm Delete",
    "confirmDeleteContent": "Are you sure you want to delete this project?",
    "ok": "Confirm",
    "cancel": "Cancel",
    "deleteSuccess": "Delete Success",
    "deleteError": "Delete Failed",
    "productMaterial": "Product Material",
    "createBy": "Project Creator",
    "qualityUserName": "Quality User Name",
    "createTime": "Create Time",
    "edit": "Edit",
    "view": "View",
    "updateTime": "Update Time",
    "delete": "Delete",
    "totalProjects": "Total",
    "items": "Items",
    "createProjectModalTitle": "Create Project",
    "projectName": "Project Name",
    "drawingFiles": "Drawing Files",
    "uploadDrawingFiles": "Upload Drawing Files",
    "projectNameRequired": "Project name is required",
    "projectNameMaxLength": "Project name must be at most 50 characters",
    "projectNameWhitespace": "Project name cannot be only whitespace",
    "projectNamePlaceholder": "Enter project name",
    "drawingFilesRequired": "Drawing files are required",
    "fileFormatTip": "Supported formats: PDF, PNG, JPG. Maximum file size: 50MB. Maximum number of files: 5",
    "productTypeRequired": "Product type is required",
    "productTypeMaxLength": "Product type must be at most 20 characters",
    "productTypeWhitespace": "Product type cannot be only whitespace",
    "productTypePlaceholder": "Enter product type",
    "productMaterialRequired": "Product material is required",
    "productMaterialMaxLength": "Product material must be at most 20 characters",
    "productMaterialWhitespace": "Product material cannot be only whitespace",
    "productMaterialPlaceholder": "Enter product material",
    "vossPNRequired": "VOSS P/N is required",
    "vossPNWhitespace": "VOSS P/N cannot be only whitespace",
    "vossPNPlaceholder": "Enter VOSS P/N",
    "partDescriptionRequired": "Part description is required",
    "partDescriptionWhitespace": "Part description cannot be only whitespace",
    "partDescriptionPlaceholder": "Enter part description",
    "drawingVersionRequired": "Drawing version is required",
    "drawingVersionWhitespace": "Drawing version cannot be only whitespace",
    "drawingVersionPlaceholder": "Enter drawing version",
    "qualityManagerRequired": "Quality manager is required",
    "qualityManagerPlaceholder": "Select quality manager",
    "loadingQualityManager": "Loading quality manager...",
    "createProjectButton": "Create Project",
    "loadingQualityManagerError": "Failed to load quality manager",
    "qualityManagerInvalid": "Please select a valid quality manager",
    "drawingFileRequired": "Please upload at least one valid drawing file (ensure the file upload is complete)",
    "projectCreateSuccess": "Project created successfully!",
    "pleaseCompleteAllRequiredFields": "Please complete all required fields",
    "lastSaveTime": "Last Save Time",
    "projectManager": "Project Manager",
    "drawing": "Drawing",
    "draw": "Draw",
    "annotations": "Annotations",
    "viewReport": "View Report",
    "attachmentList": "Attachment List",
    "index": "Index",
    "screenshot": "Screenshot",
    "toleranceValue": "Value",
    "toleranceName": "Tolerance Name",
    "characteristicIdentifier": "Characteristic Identifier",
    "project": "Project",
    "normTolerance": "Normal Tolerance",
    "testingMethods": "Testing Methods",
    "testingRequirements": "Testing Requirements",
    "firstSamplingQuantity": "First Sampling Quantity",
    "afterFirstSamplingQuantity": "After First Sampling Quantity",
    "afterFirstSamplingFrequency": "After First Sampling Frequency",
    "supplierSelfTestRequirements": "Supplier Self-Test Requirements",
    "operation": "Operation",
    "ocrDetect": "OCR Detect",
    "initiateConfirmation": "Initiate Confirmation",
    "extractText": "Extract Text",
    "dragMode": "Drag Mode",
    "resetSelection": "Reset Selection",
    "boxSelectMode": "Box Select Mode",
    "singleAnnotation": "Single Annotation",
    "parsingImage": "Parsing Image",
    "confirmDeleteAnnotation": "Confirm Delete Annotation",
    "confirm": "Confirm"
}
  • public/locales/zh/translation.json
{
    "back": "返回",
    "createProject": "新建項目",
    "allStatus": "全部狀態",
    "labeling": "標註中",
    "confirming": "確認中",
    "completed": "已完成",
    "startDate": "開始日期",
    "endDate": "結束日期",
    "searchPlaceholder": "輸入關鍵字進行搜索...",
    "noProjects": "暫無數據,您還沒有創建過任何項目!",
    "noFilteredProjects": "沒有符合篩選條件的項目,請嘗試調整篩選條件!",
    "loadingTip": "加載中...",
    "productType": "產品類型",
    "unknown": "未知",
    "confirmDelete": "確認刪除",
    "confirmDeleteContent": "確定要刪除該項目嗎?",
    "ok": "確定",
    "cancel": "取消",
    "deleteSuccess": "刪除成功",
    "deleteError": "刪除失敗",
    "productMaterial": "產品材質",
    "createBy": "項目創建人",
    "qualityUserName": "質量負責人",
    "createTime": "創建時間",
    "edit": "編輯",
    "view": "查看",
    "updateTime": "更新時間",
    "delete": "刪除",
    "totalProjects": "共",
    "items": "條數據",
    "createProjectModalTitle": "新建項目",
    "projectName": "項目名稱",
    "drawingFiles": "圖紙文件",
    "uploadDrawingFiles": "選擇附件",
    "projectNameRequired": "請填寫項目名稱",
    "projectNameMaxLength": "項目名稱最多50個字符",
    "projectNameWhitespace": "項目名稱不能僅為空格",
    "projectNamePlaceholder": "請輸入項目名稱",
    "drawingFilesRequired": "請上傳圖紙文件",
    "fileFormatTip": "支持PDF、PNG、JPG格式,大小≤50MB的圖檔,一次性最多上傳5張",
    "productTypeRequired": "請填寫產品類型",
    "productTypeMaxLength": "產品類型最多20個字符",
    "productTypeWhitespace": "產品類型不能僅為空格",
    "productTypePlaceholder": "請輸入產品類型",
    "productMaterialRequired": "請填寫產品材質",
    "productMaterialMaxLength": "產品材質最多20個字符",
    "productMaterialWhitespace": "產品材質不能僅為空格",
    "productMaterialPlaceholder": "請輸入產品材質",
    "vossPNRequired": "請填寫VOSS P/N",
    "vossPNWhitespace": "VOSS P/N不能僅為空格",
    "vossPNPlaceholder": "請輸入VOSS P/N",
    "partDescriptionRequired": "請填寫Part description",
    "partDescriptionWhitespace": "Part description不能僅為空格",
    "partDescriptionPlaceholder": "請輸入Part description",
    "drawingVersionRequired": "請填寫Drawing Version",
    "drawingVersionWhitespace": "Drawing Version不能僅為空格",
    "drawingVersionPlaceholder": "請輸入Drawing Version",
    "qualityManagerRequired": "請選擇質量負責人",
    "qualityManagerPlaceholder": "請選擇質量負責人",
    "loadingQualityManager": "加載質量負責人中...",
    "createProjectButton": "立即創建",
    "loadingQualityManagerError": "加載質量負責人失敗",
    "qualityManagerInvalid": "請選擇有效的質量負責人",
    "drawingFileRequired": "請上傳至少一個有效的圖紙文件(確保文件上傳完成)",
    "projectCreateSuccess": "項目創建成功!",
    "pleaseCompleteAllRequiredFields": "請完善所有必填項信息",
    "lastSaveTime": "上次保存時間",
    "projectManager": "項目負責人",
    "drawing": "圖紙",
    "draw": "圖",
    "annotations": "標註點位",
    "viewReport": "查看基準書報表",
    "attachmentList": "附件清單",
    "index": "序號",
    "screenshot": "截圖",
    "toleranceValue": "數值",
    "toleranceName": "公差名稱",
    "characteristicIdentifier": "特性標識",
    "project": "項目",
    "normTolerance": "規範公差",
    "testingMethods": "檢驗手段",
    "testingRequirements": "福士來料檢驗要求",
    "firstSamplingQuantity": "首批抽樣數量",
    "afterFirstSamplingQuantity": "首批後抽樣數量",
    "afterFirstSamplingFrequency": "首批後抽樣頻次",
    "supplierSelfTestRequirements": "供方自檢要求",
    "operation": "操作",
    "ocrDetect": "AI標註氣泡",
    "initiateConfirmation": "發起確認",
    "extractText": "文字提取",
    "dragMode": "拖拽模式",
    "resetSelection": "重置框選",
    "boxSelectMode": "框選模式",
    "singleAnnotation": "單點標註",
    "parsingImage": "正在解析圖片",
    "confirmDeleteAnnotation": "是否確認刪除該標註?",
    "confirm": "確認"
}
2. 創建 i18n 配置文件

在 src 目錄下新建 i18n.js

import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import Backend from 'i18next-http-backend';

i18n
    .use(Backend) // 加載語言文件
    .use(initReactI18next)
    .init({
        fallbackLng: 'zh', // 默認語言
        debug: false,
        interpolation: {
            escapeValue: false, // 允許使用變量(如 {{total}})
        },
        // 配置語言文件路徑(默認會從 public/locales/{{lng}}/{{ns}}.json 加載)
        backend: {
            loadPath: '/locales/{{lng}}/{{ns}}.json'
        }
    });

export default i18n;
3. 在入口文件引入配置

在 src/main.jsx 中引入 i18n.js,確保初始化:

import './i18n';

三、在組件中使用

1. 基礎用法(翻譯文本)

使用 useTranslation 鈎子獲取翻譯函數:

import { useTranslation } from 'react-i18next';

function Home() {
  const { t } = useTranslation(); // t 是翻譯函數

  return (
    <div>
      <h1>{t('welcome')}</h1>
      <p>{t('description')}</p>
    </div>
  );
}

export default Home;
2. 切換語言

通過 i18n.changeLanguage 方法切換語言:

import { useTranslation } from 'react-i18next';

const HomePage = () => {
    const { t, i18n } = useTranslation();

    const changeLang = (lang) => {
        i18n.changeLanguage(lang); // 切換語言('en' 或 'zh')
    };

    return (
        <div className={styles['page-header']}>
        <div className={styles['header-content']}>
          <Button
            type="text"
            icon={<ArrowLeftOutlined />}
            onClick={handleBack}
            className={styles['back-button']}
          >
            {t('back')}
          </Button>
          <div className={styles['right-actions']}>
            <Dropdown
              menu={{
                items: [
                  {
                    key: 'zh',
                    label: '簡體中文'
                  },
                  {
                    key: 'en',
                    label: 'English'
                  }
                ],
                onClick: ({ key }) => {
                  changeLang(key);
                }
              }}
              placement="bottomRight"
            >
              <div className={styles.languageSwitcher}>
                <span className={styles.currentLang}>
                  {i18n.language === 'zh' ? '簡體中文' : 'English'}
                </span>
                <div className={styles.langIcon}>
                  <GlobalOutlined />
                </div>
              </div>
            </Dropdown>
            <Button
              type="primary"
              icon={<PlusOutlined />}
              onClick={() => setModalVisible(true)}
              className={styles['create-button']}
            >
              {t('createProject')}
            </Button>
          </div>
        </div>
        <div className={styles['divider-line']}></div>
      </div>
    )
}

export default HomePage;

效果

React 中 react-i18next 切換語言( 項目國際化 )_reacti18_#react.js

3.DatePicker 隨切換更新中英文(可選)

添加當前語言的狀態定義邏輯

import zhCN from 'antd/locale/zh_CN';
import enUS from 'antd/locale/en_US';
const [currentLang, setCurrentLang] = useState(i18n.language);

const changeLang = (lang) => {
    i18n.changeLanguage(lang); // 切換語言('en' 或 'zh')
    setCurrentLang(lang); // 更新當前語言狀態
  };
<ConfigProvider locale={currentLang === 'zh' ? zhCN : enUS}>
              <DatePicker.RangePicker
                size="large"
                value={timeFilter}
                onChange={handleTimeChange}
                placeholder={[t('startDate'), t('endDate')]}
                className={styles['time-filter']}
              />
            </ConfigProvider>

效果

React 中 react-i18next 切換語言( 項目國際化 )_reacti18_#i18next_02

四、進階配置(可選)

  1. 動態加載語言i18next-http-backend 會自動加載對應語言文件,無需手動引入。
  2. 保存語言偏好:配置 detection 中的 caches 後,語言選擇會保存在 localStorage 或 cookie 中,刷新頁面不會重置。
  3. 嵌套翻譯:語言文件支持嵌套結構,例如:
{
  "user": {
    "name": "姓名",
    "age": "年齡"
  }
}

使用時:t('user.name')

五、其餘子組件效果(按需實現即可)

其餘組件需要使用也是直接通過下方主要代碼實現

import { useTranslation } from 'react-i18next';


const { t } = useTranslation();


{t('productType')}

t 函數可以用於 DOM、實際函數中(例如:創建成功之後message.success(t('projectCreateSuccess'));或者message.error(t('pleaseCompleteAllRequiredFields'));......)按需修改即可

以下展示一個新建彈窗翻譯後的效果:

React 中 react-i18next 切換語言( 項目國際化 )_reacti18_#react.js_03

六、實現本地存儲

修改 i18n 文件

import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import Backend from 'i18next-http-backend';

i18n
    .use(Backend) // 加載語言文件
    .use(initReactI18next)
    .init({
        fallbackLng: 'zh',
        // 初始化時優先讀取本地存儲的語言,無則用默認中文
        lng: localStorage.getItem('selectedLang') || 'zh',
        debug: false,
        interpolation: {
            escapeValue: false,
        }
    });

export default i18n;

添加本地存儲邏輯

const [currentLang, setCurrentLang] = useState(localStorage.getItem('selectedLang') || i18n.language);

  const changeLang = (lang) => {
    i18n.changeLanguage(lang); // 切換語言('en' 或 'zh')
    setCurrentLang(lang); // 更新當前語言狀態
    localStorage.setItem('selectedLang', lang);
  };

  useEffect(() => {
    // 組件掛載時,讀取本地存儲語言並同步到 i18n 和 currentLang
    const storedLang = localStorage.getItem('selectedLang');
    if (storedLang) {
      i18n.changeLanguage(storedLang);
      setCurrentLang(storedLang);
    }
  }, [i18n]);



<span className={styles.currentLang}>
                  {currentLang === 'zh' ? '簡體中文' : 'English'}
                </span>

通過以上配置,即可實現 React 項目的中英文切換功能。核心是通過 t() 函數獲取翻譯文本,通過 i18n.changeLanguage() 切換語言。