antd 如何做动态国际化?

我看到大部分的国际化只有中文和英文切换,都是提前加载了这2个语言的翻译。假如我需要支持的语种是不确定的。请问还是全部加载过来json吗?

import enUS from 'antd/es/locale/en_US';
import zhCN from 'antd/es/locale/zh_CN';
import dayjs from 'dayjs';
import 'dayjs/locale/en';
import 'dayjs/locale/zh-cn';

等,这样首页加载内容会变很慢吗?

阅读 2.1k
avatarAI BotBETA

回答

antd 中实现动态国际化时,如果你需要支持的语种是不确定的,不建议一次性加载所有语言的 JSON 文件。这样做会导致首页加载内容变慢,尤其是当语言文件较大且数量较多时。

相反,你可以采用以下方法来动态加载所需的语言文件:

  1. 按需加载语言文件

    • 根据用户的语言选择,动态地从服务器加载对应的语言文件。
    • 可以使用 fetch 或其他网络请求库来加载语言文件。
  2. 使用代码分割

    • 如果你使用的是像 Webpack 这样的模块打包工具,可以利用代码分割功能来拆分语言文件。
    • 这样,只有当用户需要某种语言时,才会加载对应的语言文件。
  3. 延迟加载

    • 在用户选择语言后,再进行语言文件的加载,而不是在页面初始化时就加载所有语言文件。
  4. 缓存机制

    • 实现语言文件的缓存,以便在用户再次访问时能够快速加载。

以下是一个简单的示例,展示了如何动态加载 antd 的语言文件:

import { ConfigProvider } from 'antd';

// 假设你有一个函数可以根据用户选择的语言来获取对应的语言文件
async function loadLocale(language) {
  const response = await fetch(`/path/to/locale/${language}.json`);
  const localeData = await response.json();
  return localeData;
}

// 根据用户选择的语言动态设置 Ant Design 的国际化
async function setAntdLocale(language) {
  try {
    const localeData = await loadLocale(language);
    ReactDOM.render(
      <ConfigProvider locale={localeData}>
        <App />
      </ConfigProvider>,
      document.getElementById('root')
    );
  } catch (error) {
    console.error('Failed to load locale:', error);
  }
}

// 示例:用户选择英语
setAntdLocale('en_US');

在这个示例中,loadLocale 函数会根据提供的语言代码从服务器加载对应的语言文件,并返回语言数据。然后,setAntdLocale 函数会使用这些数据来设置 ConfigProviderlocale 属性,从而实现 Ant Design 的国际化。

注意:在实际应用中,你可能需要根据具体的项目结构和需求来调整这个示例。

3 个回答

按需动态加载:

// i18n.js
import { createContext, useContext } from 'react';

export const I18nContext = createContext(null);

// 动态加载语言包
export async function loadLocale(lang) {
  let antdLocale;
  
  switch(lang) {
    case 'en':
      antdLocale = await import('antd/es/locale/en_US');
      await import('dayjs/locale/en');
      break;
    case 'zh':
      antdLocale = await import('antd/es/locale/zh_CN'); 
      await import('dayjs/locale/zh-cn');
      break;
    // 其他
    default:
      // 默认英语
      antdLocale = await import('antd/es/locale/en_US');
      await import('dayjs/locale/en');
  }
  
  return antdLocale.default;
}

// App.js
import { useState, useEffect } from 'react';
import { ConfigProvider } from 'antd';
import { I18nContext, loadLocale } from './i18n';

function App() {
  const [locale, setLocale] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const currentLang = navigator.language.split('-')[0];
    
    loadLocale(currentLang).then(localeData => {
      setLocale(localeData);
      setLoading(false);
    });
  }, []);

  if (loading) {
    return <div>Loading...</div>;
  }

  return (
    <I18nContext.Provider value={{ locale, setLocale }}>
      <ConfigProvider locale={locale}>
        {/* 应用内容 */}
      </ConfigProvider>
    </I18nContext.Provider>
  );
}

或者用分包加载:

// locales/index.js
const locales = {
  async loadLocale(lang) {
    try {
      // 动态导入语言包
      const module = await import(`./chunks/${lang}.js`);
      return module.default;
    } catch (err) {
      console.error(`Failed to load locale ${lang}`, err);
      const fallback = await import('./chunks/en.js');
      return fallback.default;
    }
  }
};

export default locales;

// locales/chunks/en.js
import antdLocale from 'antd/es/locale/en_US';
import 'dayjs/locale/en';

export default {
  antd: antdLocale,
  messages: {
    // 自定义文案
  }
};

// 使用
function LanguageSelector() {
  const { setLocale } = useContext(I18nContext);
  
  const handleChange = async (lang) => {
    const localeData = await locales.loadLocale(lang);
    setLocale(localeData.antd);
  };
  
  return (
    <Select onChange={handleChange}>
      <Option value="en">English</Option>
      <Option value="zh">中文</Option>
    </Select>
  );
}

将每种语言的翻译内容分别存储在不同的 JSON 文件中。例如,创建 locales 文件夹,并在其中添加 en.json 和 zh.json 等文件,按需加载。

组件国际化可以参考这篇文章
React + i18next + antd组件国际化

解决思路:

  1. 利用动态导入(Dynamic Import)技术,根据用户选择的语言,仅在需要时加载相应的语言包,避免一次性加载所有语言包。
  2. 使用异步加载机制,将语言包的加载延迟到用户实际需要切换语言时,减少首页加载时间。
  3. 存储用户选择的语言信息,例如使用 localStoragesessionStorage,以便在页面刷新或重新访问时记住用户的语言偏好。

实现代码:

import React, { useState, useEffect } from 'react';
import { ConfigProvider } from 'antd';
import dayjs from 'dayjs';


function App() {
  const [locale, setLocale] = useState(null);


  useEffect(() => {
    const storedLocale = localStorage.getItem('userLocale');
    if (storedLocale) {
      importLocale(storedLocale);
    } else {
      // 默认为英文
      importLocale('en_US');
    }
  }, []);


  const importLocale = async (lang) => {
    try {
      let antdLocale, dayjsLocale;
      if (lang === 'zh_CN') {
        antdLocale = await import('antd/es/locale/zh_CN');
        dayjsLocale = await import('dayjs/locale/zh-cn');
        dayjs.locale(dayjsLocale.default);
      } else if (lang === 'en_US') {
        antdLocale = await import('antd/es/locale/en_US');
        dayjsLocale = await import('dayjs/locale/en');
        dayjs.locale(dayjsLocale.default);
      }
      // 可以添加更多语言支持
      setLocale(antdLocale.default);
      localStorage.setItem('userLocale', lang);
    } catch (error) {
      console.error('Failed to import locale:', error);
    }
  };


  const changeLanguage = async (lang) => {
    await importLocale(lang);
  };


  return (
    <div>
      <button onClick={() => changeLanguage('zh_CN')}>中文</button>
      <button onClick={() => changeLanguage('en_US')}>English</button>
      {locale && (
        <ConfigProvider locale={locale}>
          {/* 此处放置你的应用程序内容 */}
          <h1>Hello, World!</h1>
        </ConfigProvider>
      )}
    </div>
  );
}


export default App;

代码解释:

  • useState 用于存储当前选择的语言包对应的 locale 对象,初始状态为 null
  • useEffect 会在组件挂载时执行,检查 localStorage 中是否存储了用户之前选择的语言,如果有则加载该语言,若没有则默认加载英文。
  • importLocale 函数使用 async/await 进行异步导入,根据传入的语言代码(如 zh_CNen_US),动态导入相应的 antd 语言包和 dayjs 语言包,并更新 dayjs 的语言设置。同时,将导入的 antd 语言包存储在 locale 状态中,并将语言信息存储在 localStorage 中。
  • changeLanguage 函数允许用户点击按钮时切换语言,调用 importLocale 函数加载相应语言包。
  • return 语句中,提供了两个按钮,用于切换语言,点击按钮会调用 changeLanguage 函数。当 locale 不为 null 时,使用 ConfigProvider 组件将当前选择的语言包传递给 antd 组件,使应用程序内容实现国际化。

使用说明:

  1. 将上述代码保存为一个 React 组件文件,例如 App.js
  2. 确保你的项目中已经安装了 antddayjs 依赖,可以使用 npmyarn 安装,例如 npm install antd dayjs
  3. 运行你的 React 应用程序,例如使用 npm startyarn start
  4. 当用户点击相应的语言切换按钮时,会动态加载对应的语言包,避免了一次性加载多个语言包造成的首页加载缓慢问题。

通过这种方式,你可以根据用户的实际需求动态加载语言包,而不是在首页加载时将所有可能的语言包都加载进来,提高了应用程序的性能,尤其是在需要支持多种语言时,避免了不必要的资源加载,同时保证了国际化的灵活性。

需要注意的是,在添加更多语言支持时,需要扩展 importLocale 函数中的逻辑,根据不同的语言代码添加相应的导入语句,并更新 dayjs 的语言设置。此外,你可以根据需要存储用户语言偏好的不同位置,如 sessionStorage 或其他存储方式,修改 localStorage 的使用部分。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏