国际化 (I18n)

@ant-design/agentic-ui 提供了完整的国际化解决方案,支持中英文切换,自动检测用户语言偏好,并与 Ant Design 的国际化系统无缝集成。

核心特性

  • 🌍 多语言支持:内置中文和英文语言包
  • 🔄 自动检测:智能检测用户浏览器语言设置
  • 💾 持久化:自动保存用户语言选择到 localStorage
  • 🎨 集成 Ant Design:与 Ant Design ConfigProvider 同步
  • 🎯 类型安全:完整的 TypeScript 类型定义
  • 🔌 易于扩展:支持自定义语言包

快速开始

基础使用

import { I18nProvide, useLanguage } from '@ant-design/agentic-ui';

// 1. 在应用根组件中使用 I18nProvide
function App() {
  return (
    <I18nProvide>
      <YourComponents />
    </I18nProvide>
  );
}

// 2. 在子组件中使用 useLanguage Hook
function YourComponent() {
  const { locale, language, setLanguage, toggleLanguage } = useLanguage();

  return (
    <div>
      <p>{locale.welcome}</p>
      <button onClick={toggleLanguage}>
        {language === 'zh-CN' ? 'Switch to English' : '切换到中文'}
      </button>
    </div>
  );
}

API 文档

I18nProvide

国际化提供者组件,为整个应用提供国际化功能。

Props

属性说明类型默认值版本
children子组件ReactNode--
locale自定义语言包typeof cnLabels--
defaultLanguage默认语言'zh-CN' | 'en-US''zh-CN'-
autoDetect是否自动检测语言booleantrue-

示例

import { I18nProvide } from '@ant-design/agentic-ui';

// 基本使用
<I18nProvide>
  <App />
</I18nProvide>

// 指定默认语言
<I18nProvide defaultLanguage="en-US">
  <App />
</I18nProvide>

// 关闭自动检测
<I18nProvide autoDetect={false} defaultLanguage="zh-CN">
  <App />
</I18nProvide>

useLanguage Hook

语言切换 Hook,提供语言状态和切换方法。

返回值

属性说明类型默认值版本
language当前语言代码'zh-CN' | 'en-US'--
locale当前语言的标签对象LocalKeys--
setLanguage设置语言的方法(language: 'zh-CN' | 'en-US') => void--
toggleLanguage切换中英文的方法() => void--
isChinese是否为中文boolean--
isEnglish是否为英文boolean--

示例

import { useLanguage } from '@ant-design/agentic-ui';

function LanguageSwitcher() {
  const {
    language,
    locale,
    setLanguage,
    toggleLanguage,
    isChinese,
    isEnglish,
  } = useLanguage();

  return (
    <div>
      {/* 显示当前语言 */}
      <p>当前语言: {language}</p>

      {/* 使用语言包中的文本 */}
      <h1>{locale.welcome}</h1>
      <p>{locale.description}</p>

      {/* 切换语言 */}
      <button onClick={toggleLanguage}>{locale.switchLanguage}</button>

      {/* 设置特定语言 */}
      <button onClick={() => setLanguage('en-US')}>English</button>
      <button onClick={() => setLanguage('zh-CN')}>中文</button>

      {/* 条件渲染 */}
      {isChinese && <div>这是中文内容</div>}
      {isEnglish && <div>This is English content</div>}
    </div>
  );
}

工具函数

detectUserLanguage

自动检测用户语言偏好。

import { detectUserLanguage } from '@ant-design/agentic-ui';

const language = detectUserLanguage();
console.log(language); // 'zh-CN' 或 'en-US'

检测优先级:

  1. localStorage 中保存的用户选择
  2. Ant Design ConfigProvider 的 locale
  3. 浏览器语言设置
  4. 默认语言(中文)

getLocaleByLanguage

根据语言代码获取对应的语言包。

import { getLocaleByLanguage } from '@ant-design/agentic-ui';

const locale = getLocaleByLanguage('zh-CN');
console.log(locale.welcome); // '欢迎'

saveUserLanguage

保存用户语言选择到 localStorage。

import { saveUserLanguage } from '@ant-design/agentic-ui';

saveUserLanguage('en-US');

compileTemplate

编译模板字符串,支持变量替换。

import { compileTemplate } from '@ant-design/agentic-ui';

// 基本使用
const message = compileTemplate('你好,${name}!', { name: '世界' });
console.log(message); // '你好,世界!'

// 缺少变量时显示占位符
const message2 = compileTemplate('你好,${name}!');
console.log(message2); // '你好,[name]!'

// 实际应用场景
const { locale } = useLanguage();
const taskMessage = compileTemplate(locale.inProgressTask, {
  taskName: '数据分析',
});
console.log(taskMessage); // '正在进行数据分析任务'

语言包

内置语言包

import { cnLabels, enLabels } from '@ant-design/agentic-ui';

// 中文语言包
console.log(cnLabels.welcome); // '欢迎'

// 英文语言包
console.log(enLabels.welcome); // 'Welcome'

常用文本标签

键名中文英文
welcome欢迎Welcome
copy复制Copy
copySuccess复制成功Copied successfully
delete删除Delete
cancel取消Cancel
confirm确认Confirm
edit编辑Edit
preview预览Preview
expand展开Expand
collapse收起Collapse
bold加粗Bold
italic斜体Italic
undo撤销Undo
redo重做Redo

完整的语言包列表请参考源代码中的 locales.ts 文件。

自定义语言包

你可以扩展或覆盖默认语言包:

import { I18nProvide, cnLabels } from '@ant-design/agentic-ui';

// 扩展语言包
const customLocale = {
  ...cnLabels,
  customKey: '自定义文本',
  anotherKey: '另一个文本',
};

function App() {
  return (
    <I18nProvide locale={customLocale}>
      <YourComponents />
    </I18nProvide>
  );
}

与 Ant Design 集成

I18nProvide 会自动与 Ant Design 的 ConfigProvider 同步语言设置。

import { ConfigProvider } from 'antd';
import zhCN from 'antd/locale/zh_CN';
import enUS from 'antd/locale/en_US';
import { I18nProvide, useLanguage } from '@ant-design/agentic-ui';

function App() {
  const { language } = useLanguage();
  const antdLocale = language === 'zh-CN' ? zhCN : enUS;

  return (
    <ConfigProvider locale={antdLocale}>
      <I18nProvide>
        <YourComponents />
      </I18nProvide>
    </ConfigProvider>
  );
}

完整的集成示例

import { ConfigProvider, Button } from 'antd';
import zhCN from 'antd/locale/zh_CN';
import enUS from 'antd/locale/en_US';
import { I18nProvide, useLanguage } from '@ant-design/agentic-ui';

function AppContent() {
  const { language, locale, toggleLanguage } = useLanguage();

  return (
    <div>
      <h1>{locale.welcome}</h1>
      <Button onClick={toggleLanguage}>{locale.switchLanguage}</Button>
    </div>
  );
}

function App() {
  return (
    <I18nProvide>
      <ConfigProviderWrapper>
        <AppContent />
      </ConfigProviderWrapper>
    </I18nProvide>
  );
}

function ConfigProviderWrapper({ children }) {
  const { language } = useLanguage();
  const antdLocale = language === 'zh-CN' ? zhCN : enUS;

  return <ConfigProvider locale={antdLocale}>{children}</ConfigProvider>;
}

实战示例

1. 语言切换按钮

import { Button } from 'antd';
import { useLanguage } from '@ant-design/agentic-ui';
import { GlobalOutlined } from '@ant-design/icons';

function LanguageSwitcher() {
  const { language, toggleLanguage } = useLanguage();

  return (
    <Button icon={<GlobalOutlined />} onClick={toggleLanguage}>
      {language === 'zh-CN' ? 'English' : '中文'}
    </Button>
  );
}

2. 多语言表单

import { Form, Input, Button } from 'antd';
import { useLanguage } from '@ant-design/agentic-ui';

function LoginForm() {
  const { locale } = useLanguage();

  return (
    <Form>
      <Form.Item
        label={locale.username}
        name="username"
        rules={[{ required: true, message: locale.usernameRequired }]}
      >
        <Input placeholder={locale.usernamePlaceholder} />
      </Form.Item>

      <Form.Item
        label={locale.password}
        name="password"
        rules={[{ required: true, message: locale.passwordRequired }]}
      >
        <Input.Password placeholder={locale.passwordPlaceholder} />
      </Form.Item>

      <Form.Item>
        <Button type="primary" htmlType="submit">
          {locale.login}
        </Button>
      </Form.Item>
    </Form>
  );
}

3. 动态消息提示

import { message } from 'antd';
import { useLanguage, compileTemplate } from '@ant-design/agentic-ui';

function useNotification() {
  const { locale } = useLanguage();

  const showSuccess = (name: string) => {
    const msg = compileTemplate(locale.saveSuccess, { name });
    message.success(msg);
  };

  const showError = (errorMsg: string) => {
    const msg = compileTemplate(locale.errorOccurred, { error: errorMsg });
    message.error(msg);
  };

  return { showSuccess, showError };
}

// 使用
function MyComponent() {
  const { showSuccess, showError } = useNotification();

  const handleSave = async () => {
    try {
      // 保存逻辑
      showSuccess('用户数据');
    } catch (error) {
      showError(error.message);
    }
  };

  return <Button onClick={handleSave}>保存</Button>;
}

4. 条件渲染内容

import { useLanguage } from '@ant-design/agentic-ui';

function Documentation() {
  const { isChinese, isEnglish } = useLanguage();

  return (
    <div>
      {isChinese && (
        <div>
          <h1>中文文档</h1>
          <p>这是中文内容...</p>
        </div>
      )}

      {isEnglish && (
        <div>
          <h1>English Documentation</h1>
          <p>This is English content...</p>
        </div>
      )}
    </div>
  );
}

5. 语言选择器组件

import { Select } from 'antd';
import { useLanguage } from '@ant-design/agentic-ui';

function LanguageSelector() {
  const { language, setLanguage, locale } = useLanguage();

  const languages = [
    { value: 'zh-CN', label: '简体中文' },
    { value: 'en-US', label: 'English' },
  ];

  return (
    <Select
      value={language}
      onChange={setLanguage}
      options={languages}
      style={{ width: 120 }}
      aria-label={locale.selectLanguage}
    />
  );
}

最佳实践

1. 统一语言管理

创建一个统一的语言管理 Hook:

import { useLanguage, compileTemplate } from '@ant-design/agentic-ui';

export function useI18n() {
  const { locale, language, setLanguage, toggleLanguage } = useLanguage();

  // 包装 compileTemplate 方法
  const t = (key: keyof typeof locale, variables?: Record<string, string>) => {
    const template = locale[key];
    return variables ? compileTemplate(template, variables) : template;
  };

  return {
    t,
    locale,
    language,
    setLanguage,
    toggleLanguage,
  };
}

// 使用
function MyComponent() {
  const { t } = useI18n();

  return (
    <div>
      <h1>{t('welcome')}</h1>
      <p>{t('inProgressTask', { taskName: '数据分析' })}</p>
    </div>
  );
}

2. 类型安全的语言包

import type { LocalKeys } from '@ant-design/agentic-ui';

// 扩展语言包类型
interface CustomLocale extends LocalKeys {
  customKey: string;
  anotherKey: string;
}

const customCnLabels: CustomLocale = {
  ...cnLabels,
  customKey: '自定义文本',
  anotherKey: '另一个文本',
};

3. 懒加载语言包

对于大型应用,可以懒加载语言包:

import { useState, useEffect } from 'react';
import { I18nProvide } from '@ant-design/agentic-ui';

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

  useEffect(() => {
    // 动态加载语言包
    import('./locales/custom-locale').then((module) => {
      setLocale(module.default);
    });
  }, []);

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

  return (
    <I18nProvide locale={locale}>
      <YourComponents />
    </I18nProvide>
  );
}

4. 测试国际化功能

import { render, screen } from '@testing-library/react';
import { I18nProvide } from '@ant-design/agentic-ui';
import MyComponent from './MyComponent';

describe('MyComponent i18n', () => {
  it('应该显示中文文本', () => {
    render(
      <I18nProvide defaultLanguage="zh-CN" autoDetect={false}>
        <MyComponent />
      </I18nProvide>,
    );

    expect(screen.getByText('欢迎')).toBeInTheDocument();
  });

  it('应该显示英文文本', () => {
    render(
      <I18nProvide defaultLanguage="en-US" autoDetect={false}>
        <MyComponent />
      </I18nProvide>,
    );

    expect(screen.getByText('Welcome')).toBeInTheDocument();
  });
});

5. 性能优化

使用 useMemo 优化语言相关的计算:

import { useMemo } from 'react';
import { useLanguage } from '@ant-design/agentic-ui';

function DataTable() {
  const { locale } = useLanguage();

  // 缓存列配置,避免重复计算
  const columns = useMemo(
    () => [
      { title: locale.name, dataIndex: 'name' },
      { title: locale.age, dataIndex: 'age' },
      { title: locale.address, dataIndex: 'address' },
    ],
    [locale],
  );

  return <Table columns={columns} />;
}

常见问题

1. 如何添加新的语言?

目前仅支持中英文,如需添加其他语言:

// 创建新的语言包
const jpLabels = {
  welcome: 'ようこそ',
  // ... 其他标签
};

// 扩展类型定义
type Language = 'zh-CN' | 'en-US' | 'ja-JP';

2. 如何持久化语言选择?

语言选择会自动保存到 localStorage,键名为 agentic-ui-language。

// 手动读取
const savedLanguage = localStorage.getItem('agentic-ui-language');

// 手动设置
localStorage.setItem('agentic-ui-language', 'en-US');

3. 如何覆盖默认语言检测?

设置 autoDetect={false} 并指定 defaultLanguage:

<I18nProvide autoDetect={false} defaultLanguage="en-US">
  <App />
</I18nProvide>

4. useLanguage 必须在 I18nProvide 内使用吗?

是的,useLanguage 必须在 I18nProvide 组件内部使用,否则会抛出错误。

// ❌ 错误用法
function App() {
  const { locale } = useLanguage(); // 会报错
  return <div>{locale.welcome}</div>;
}

// ✅ 正确用法
function App() {
  return (
    <I18nProvide>
      <Content />
    </I18nProvide>
  );
}

function Content() {
  const { locale } = useLanguage(); // 正确
  return <div>{locale.welcome}</div>;
}

注意事项

  1. Context 嵌套:确保 I18nProvide 在组件树的顶层
  2. 性能考虑:语言切换会触发组件重渲染,注意使用 useMemo 优化
  3. SSR 支持:服务端渲染时注意 localStorage 的访问
  4. 类型安全:使用 TypeScript 确保语言包的类型安全
  5. 测试环境:测试环境默认使用英文,可通过 autoDetect={false} 修改

相关链接