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';

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

阅读 413
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 的国际化。

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

2 个回答

按需动态加载:

// 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组件国际化

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