@ui18n/react
Version: 
⚛️ Smart React internationalization with hooks, Server Components, and concurrent features - built for React 18+
772 lines (652 loc) • 18.2 kB
Markdown
# @ui18n/react
🌍 **React集成包** - 为React应用提供智能国际化支持
[](https://badge.fury.io/js/%40ui18n%2Freact)
[](https://www.typescriptlang.org/)
[](https://reactjs.org/)
## 状态与范围
- 稳定内容(Stable):核心 UI 组件、上下文与常规 Hooks/插件。
- 实验接口(Incubating):Translator 依赖注入(ExperimentalTranslatorProvider、useTranslator)。用于“代码层切换后端适配器”,不提供界面化切换。接口可能演进,详见:
  - packages/react/docs/INCUBATING_TRANSLATOR.md
  - 选择与稳定性说明:docs/UI_PACKAGES_OVERVIEW.md
- 若仅需“语言入口 UI”,推荐使用独立稳定包 @ui18n/selector-react(不绑定后端)。
## ✨ 特性
- 🎯 **React专用设计** - 完美集成React生态系统
- 🪝 **强大的Hooks** - `useUI18n`, `useTranslation` 等
- 🧩 **智能UI组件** - 完全可定制的`<LanguageSelector>`组件
- 🔄 **Context支持** - 全局状态管理,避免prop drilling
- ⚡ **性能优化** - 智能缓存,批量翻译,懒加载
- 🎨 **TypeScript完整支持** - 类型安全的翻译体验
- 🔌 **插件化架构** - 无障碍、移动端、主题等可选功能模块
- 🌍 **智能语言检测** - 自动识别用户系统语言并预填充
- 📱 **移动端优化** - 响应式设计,触摸手势,底部弹出选择器
## 🚀 快速开始
### 安装
```bash
npm install @ui18n/react @ui18n/core
# 或
yarn add @ui18n/react @ui18n/core
# 或
pnpm add @ui18n/react @ui18n/core
```
### 基础使用
```tsx
import React from 'react';
import { UI18nProvider, useUI18n, LanguageSelector } from '@ui18n/react';
import { createUI18n } from '@ui18n/core';
// 1. 创建UI18n实例(自托管模式)
const ui18n = createUI18n({
  defaultLanguage: 'zh-CN',
  aiProvider: {
    type: 'openai',  // 支持多种AI提供商
    apiKey: 'your-openai-api-key'
  }
});
// 2. 应用根组件
function App() {
  return (
    <UI18nProvider ui18n={ui18n}>
      <HomePage />
    </UI18nProvider>
  );
}
// 3. 使用智能语言选择器
function HomePage() {
  const { t, currentLanguage } = useUI18n();
  const [welcome, setWelcome] = React.useState('');
  const [intro, setIntro] = React.useState('');
  
  React.useEffect(() => {
    // t() 返回 Promise,需要异步处理
    t('欢迎使用UI18n').then(setWelcome);
    t('这是一个智能国际化解决方案').then(setIntro);
  }, [currentLanguage]);
  
  return (
    <div>
      {/* 智能语言选择器 - 支持中英文按钮 + 搜索框 */}
      <LanguageSelector
        defaultLanguages={['zh-CN', 'en']}
        showSearchBox={true}
        autoDetectSystemLanguage={true}
      />
      
      <h1>{welcome}</h1>
      <p>{intro}</p>
      <p>当前语言: {currentLanguage}</p>
    </div>
  );
}
export default App;
```
## Incubating:Translator 依赖注入(代码层切换适配器)
仅用于通过“代码选择适配器 A/B”实现后端可插拔,不提供界面化切换。完整说明见 packages/react/docs/INCUBATING_TRANSLATOR.md。
最小用法示例(片段):
```tsx
import { ExperimentalTranslatorProvider, useTranslator } from '@ui18n/react';
const adapterA = { translate: async ({ text, to }: any) => (to === 'zh-CN' ? '你好,世界' : `[A:${to}] ${text}`) };
const adapterB = { translate: async ({ text, to }: any) => (to === 'zh-CN' ? '世界你好' : `[B:${to}] ${text}`) };
// 代码层选择一个适配器(示例固定为 A)
const translator = adapterA;
function App() {
  return (
    <ExperimentalTranslatorProvider translator={translator} initialLanguage="en">
      <Inner />
    </ExperimentalTranslatorProvider>
  );
}
function Inner() {
  const { translate } = useTranslator();
  // ...
}
```
提示:如果你只需要“语言入口 UI”,请优先选择稳定的 @ui18n/selector-react,详见 docs/UI_PACKAGES_OVERVIEW.md。
## 完全自定义UI
```tsx
import React from 'react';
import { LanguageSelector } from '@ui18n/react';
function CustomLanguageSelector() {
  return (
    <LanguageSelector
      defaultLanguages={['zh-CN', 'en']}
      showSearchBox={true}
      className="my-custom-selector"
      
      // 自定义语言按钮渲染
      renderLanguageButton={(lang, onClick) => (
        <button 
          className="my-custom-button"
          onClick={onClick}
        >
          {lang === 'zh-CN' ? '中文' : 'English'}
        </button>
      )}
      
      // 自定义搜索框渲染
      renderSearchBox={(props) => (
        <input
          {...props}
          className="my-custom-search"
          placeholder="搜索语言..."
        />
      )}
    />
  );
}
```
## 🔌 插件架构
UI18n React包提供了强大的插件系统,让你可以按需加载功能模块:
### 无障碍插件
```tsx
import { useAccessibility } from '@ui18n/react';
function AccessibleLanguageSelector() {
  const { handleKeyDown, getAriaProps, getContrastClass } = useAccessibility({
    enableKeyboardNavigation: true,
    enableScreenReader: true,
    enableHighContrast: true,
    ariaLabels: {
      languageSelector: '语言选择器',
      searchBox: '搜索语言',
      languageButton: (lang) => `选择${lang}语言`
    }
  });
  return (
    <div className={getContrastClass()} {...getAriaProps('selector')}>
      <LanguageSelector />
    </div>
  );
}
```
### 移动端插件
```tsx
import { useMobile } from '@ui18n/react';
function MobileLanguageSelector() {
  const { 
    isMobile, 
    getMobileClasses, 
    BottomSheet,
    isBottomSheetOpen,
    setIsBottomSheetOpen 
  } = useMobile({
    enableMobileAdaptation: true,
    mobileBreakpoint: 768,
    enableTouchGestures: true,
    useBottomSheet: true
  });
  return (
    <div className={getMobileClasses()}>
      {isMobile ? (
        <BottomSheet>
          <LanguageSelector />
        </BottomSheet>
      ) : (
        <LanguageSelector />
      )}
    </div>
  );
}
```
### 主题插件
```tsx
import { ThemeProvider, useTheme, getThemeStyles } from '@ui18n/react';
function ThemedApp() {
  return (
    <ThemeProvider
      theme="auto"  // 'light' | 'dark' | 'auto'
      colors={{
        primary: '#3b82f6',
        secondary: '#6b7280',
        background: '#ffffff',
        text: '#1f2937',
        border: '#e5e7eb'
      }}
      fonts={{
        family: 'system-ui, sans-serif',
        size: '14px'
      }}
    >
      <ThemedLanguageSelector />
    </ThemeProvider>
  );
}
function ThemedLanguageSelector() {
  const { currentTheme, colors, fonts } = useTheme();
  
  return (
    <div 
      className={`ui18n-theme-${currentTheme}`}
      style={getThemeStyles(colors, fonts)}
    >
      <LanguageSelector />
    </div>
  );
}
```
## 📚 API文档
### Hooks
#### `useUI18n()`
主要的国际化Hook,提供完整的翻译功能。
```tsx
const {
  ui18n,              // UI18n实例
  t,                  // 翻译函数(简写)
  translate,          // 翻译函数
  currentLanguage,    // 当前语言
  switchLanguage,     // 切换语言
  isLoading          // 加载状态
} = useUI18n();
```
#### `useTranslation(text, options?)`
单个文本翻译Hook。
```tsx
const { 
  translatedText, 
  isLoading, 
  error 
} = useTranslation('你好世界', {
  targetLanguage: 'en',
  enableCache: true
});
```
### 组件
#### `<LanguageSelector>` - 智能语言选择器
完全可定制的语言选择组件,支持四大核心功能:
**1. 中英文按钮 + 智能搜索框**
```tsx
<LanguageSelector
  defaultLanguages={['zh-CN', 'en']}  // 默认显示的语言按钮
  showSearchBox={true}                // 显示智能搜索框
  autoDetectSystemLanguage={true}     // 智能预填充系统语言
/>
```
**2. 完全自定义渲染**
```tsx
<LanguageSelector
  defaultLanguages={['zh-CN', 'en', 'ja']}
  showSearchBox={true}
  className="my-selector"
  
  // 自定义语言按钮
  renderLanguageButton={(lang, onClick) => (
    <button className="custom-btn" onClick={onClick}>
      {lang === 'zh-CN' ? '中文' : lang === 'en' ? 'English' : '日本語'}
    </button>
  )}
  
  // 自定义搜索框
  renderSearchBox={(props) => (
    <input
      {...props}
      className="custom-search"
      placeholder="搜索语言..."
    />
  )}
/>
```
**3. 渐进式配置**
```tsx
// 最简配置
<LanguageSelector />
// 中等配置
<LanguageSelector
  defaultLanguages={['zh-CN', 'en', 'ja', 'ko']}
  showSearchBox={true}
/>
// 完全自定义
<LanguageSelector
  defaultLanguages={['zh-CN', 'en']}
  showSearchBox={true}
  autoDetectSystemLanguage={true}
  className="my-custom-selector"
  renderLanguageButton={(lang, onClick) => (
    <MyCustomButton language={lang} onClick={onClick} />
  )}
  renderSearchBox={(props) => (
    <MyCustomSearchBox {...props} />
  )}
/>
```
**4. 插件集成**
```tsx
import { LanguageSelector } from '@ui18n/react';
import { useAccessibility, useMobile, ThemeProvider } from '@ui18n/react';
function EnhancedLanguageSelector() {
  const { getMobileClasses, BottomSheet } = useMobile({
    enableMobileAdaptation: true,
    useBottomSheet: true
  });
  
  const { getAriaProps, handleKeyDown } = useAccessibility({
    enableKeyboardNavigation: true,
    enableScreenReader: true
  });
  return (
    <ThemeProvider theme="auto">
      <div className={getMobileClasses()} {...getAriaProps('selector')}>
        <BottomSheet>
          <LanguageSelector
            defaultLanguages={['zh-CN', 'en']}
            showSearchBox={true}
            autoDetectSystemLanguage={true}
          />
        </BottomSheet>
      </div>
    </ThemeProvider>
  );
}
```
#### Props接口
```tsx
interface LanguageSelectorProps {
  /** 默认显示的语言按钮 */
  defaultLanguages?: SupportedLanguage[];
  /** 是否显示搜索框 */
  showSearchBox?: boolean;
  /** 是否自动检测系统语言 */
  autoDetectSystemLanguage?: boolean;
  /** 自定义CSS类名 */
  className?: string;
  /** 自定义语言按钮渲染 */
  renderLanguageButton?: (
    language: SupportedLanguage,
    onClick: () => void
  ) => React.ReactNode;
  /** 自定义搜索框渲染 */
  renderSearchBox?: (props: {
    value: string;
    onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
    onFocus: () => void;
    onBlur: () => void;
  }) => React.ReactNode;
}
```
### Provider
#### `<UI18nProvider>`
全局状态提供者,必须包裹在应用根部。
```tsx
<UI18nProvider 
  ui18n={ui18nInstance}
  fallback={<div>初始化中...</div>}
>
  <App />
</UI18nProvider>
```
## 🎯 高级用法
### 1. 智能语言检测与预填充
```tsx
import { LanguageSelector } from '@ui18n/react';
function SmartLanguageSelector() {
  return (
    <LanguageSelector
      defaultLanguages={['zh-CN', 'en']}
      showSearchBox={true}
      autoDetectSystemLanguage={true}  // 自动检测系统语言并预填充搜索框
    />
  );
}
```
### 2. 企业级多功能集成
```tsx
import { 
  LanguageSelector, 
  ThemeProvider, 
  useAccessibility, 
  useMobile 
} from '@ui18n/react';
function EnterpriseLanguageSelector() {
  const { getMobileClasses, BottomSheet, isMobile } = useMobile({
    enableMobileAdaptation: true,
    mobileBreakpoint: 768,
    useBottomSheet: true
  });
  
  const { getAriaProps, handleKeyDown, getContrastClass } = useAccessibility({
    enableKeyboardNavigation: true,
    enableScreenReader: true,
    enableHighContrast: true
  });
  return (
    <ThemeProvider theme="auto" colors={{ primary: '#007bff' }}>
      <div className={`${getMobileClasses()} ${getContrastClass()}`}>
        <BottomSheet>
          <LanguageSelector
            defaultLanguages={['zh-CN', 'en', 'ja', 'ko']}
            showSearchBox={true}
            autoDetectSystemLanguage={true}
            {...getAriaProps('selector')}
            
            renderLanguageButton={(lang, onClick) => (
              <button
                className="enterprise-lang-btn"
                onClick={onClick}
                onKeyDown={(e) => handleKeyDown(e, onClick)}
                {...getAriaProps('button', lang)}
              >
                {lang === 'zh-CN' ? '中文' : 
                 lang === 'en' ? 'English' : 
                 lang === 'ja' ? '日本語' : '한국어'}
              </button>
            )}
          />
        </BottomSheet>
      </div>
    </ThemeProvider>
  );
}
```
### 3. 渐进式配置示例
```tsx
// 阶段1:最简配置(30秒上手)
function BasicSetup() {
  return <LanguageSelector />;
}
// 阶段2:添加搜索功能
function WithSearch() {
  return (
    <LanguageSelector
      defaultLanguages={['zh-CN', 'en']}
      showSearchBox={true}
    />
  );
}
// 阶段3:智能检测
function WithSmartDetection() {
  return (
    <LanguageSelector
      defaultLanguages={['zh-CN', 'en']}
      showSearchBox={true}
      autoDetectSystemLanguage={true}
    />
  );
}
// 阶段4:完全自定义
function FullyCustomized() {
  return (
    <LanguageSelector
      defaultLanguages={['zh-CN', 'en']}
      showSearchBox={true}
      autoDetectSystemLanguage={true}
      className="my-custom-selector"
      renderLanguageButton={(lang, onClick) => (
        <MyCustomButton language={lang} onClick={onClick} />
      )}
      renderSearchBox={(props) => (
        <MyCustomSearchBox {...props} />
      )}
    />
  );
}
```
### 4. 响应式移动端适配
```tsx
import { useMobile, LanguageSelector } from '@ui18n/react';
function ResponsiveLanguageSelector() {
  const { 
    isMobile, 
    getMobileClasses, 
    BottomSheet,
    isBottomSheetOpen,
    setIsBottomSheetOpen 
  } = useMobile({
    enableMobileAdaptation: true,
    mobileBreakpoint: 768,
    useBottomSheet: true
  });
  return (
    <div className={getMobileClasses()}>
      {isMobile ? (
        <>
          <button onClick={() => setIsBottomSheetOpen(true)}>
            选择语言
          </button>
          <BottomSheet>
            <LanguageSelector
              defaultLanguages={['zh-CN', 'en']}
              showSearchBox={true}
            />
          </BottomSheet>
        </>
      ) : (
        <LanguageSelector
          defaultLanguages={['zh-CN', 'en']}
          showSearchBox={true}
        />
      )}
    </div>
  );
}
```
### 5. 无障碍功能集成
```tsx
import { useAccessibility, LanguageSelector } from '@ui18n/react';
function AccessibleLanguageSelector() {
  const { handleKeyDown, getAriaProps, getContrastClass } = useAccessibility({
    enableKeyboardNavigation: true,
    enableScreenReader: true,
    enableHighContrast: true,
    ariaLabels: {
      languageSelector: '语言选择器',
      searchBox: '搜索语言',
      languageButton: (lang) => `选择${lang}语言`
    }
  });
  return (
    <div className={getContrastClass()} {...getAriaProps('selector')}>
      <LanguageSelector
        defaultLanguages={['zh-CN', 'en']}
        showSearchBox={true}
        renderLanguageButton={(lang, onClick) => (
          <button
            onClick={onClick}
            onKeyDown={(e) => handleKeyDown(e, onClick)}
            {...getAriaProps('button', lang)}
          >
            {lang === 'zh-CN' ? '中文' : 'English'}
          </button>
        )}
        renderSearchBox={(props) => (
          <input
            {...props}
            {...getAriaProps('search')}
          />
        )}
      />
    </div>
  );
}
```
## 🔧 配置选项
```tsx
import { createUI18n } from '@ui18n/core';
import { UI18nProvider } from '@ui18n/react';
// 自托管模式配置
const ui18n = createUI18n({
  // 基础配置
  defaultLanguage: 'zh-CN',
  fallbackLanguage: 'en',
  
  // AI提供商配置(自托管模式)
  aiProvider: {
    type: 'openai',  // 支持 openai、claude、qwen 等
    apiKey: process.env.REACT_APP_OPENAI_API_KEY,
    timeout: 10000,
    retries: 3
  },
  
  // 缓存配置
  cache: {
    enabled: true,
    type: 'memory',
    maxSize: 1000,
    persistent: true // 使用localStorage持久化
  }
});
// 云端服务模式配置(可选)
const cloudUI18n = createUI18n({
  defaultLanguage: 'zh-CN',
  serviceMode: 'cloud',
  userKey: 'your-user-key',
  
  // 云端服务特定配置
  cloudConfig: {
    endpoint: 'http://localhost:3000/api',
    timeout: 15000,
    retries: 2
  }
});
// React应用中使用
function App() {
  return (
    <UI18nProvider ui18n={ui18n}>
      <YourApp />
    </UI18nProvider>
  );
}
```
### 插件配置
```tsx
import { 
  LanguageSelector,
  ThemeProvider,
  useAccessibility,
  useMobile
} from '@ui18n/react';
// 主题配置
function ThemedApp() {
  return (
    <ThemeProvider
      theme="auto"  // 'light' | 'dark' | 'auto'
      colors={{
        primary: '#3b82f6',
        secondary: '#6b7280',
        background: '#ffffff',
        text: '#1f2937',
        border: '#e5e7eb'
      }}
      fonts={{
        family: 'system-ui, sans-serif',
        size: '14px'
      }}
    >
      <App />
    </ThemeProvider>
  );
}
// 无障碍配置
const accessibilityConfig = {
  enableKeyboardNavigation: true,
  enableScreenReader: true,
  enableHighContrast: false,
  ariaLabels: {
    languageSelector: '语言选择器',
    searchBox: '搜索语言',
    languageButton: (lang) => `选择${lang}语言`
  }
};
// 移动端配置
const mobileConfig = {
  enableMobileAdaptation: true,
  mobileBreakpoint: 768,
  enableTouchGestures: true,
  useBottomSheet: true
};
```
## 🎨 样式定制
(略,保持原文档后续样式与性能章节内容)
## 🔗 相关链接
- Incubating 说明:packages/react/docs/INCUBATING_TRANSLATOR.md
- UI 包选择与稳定性:docs/UI_PACKAGES_OVERVIEW.md
- 核心包文档:../core/README.md
- Vue集成包:../vue/README.md
- CLI工具:../cli/README.md
- GitHub仓库:https://github.com/iron-wayne/UI18N-OSS
## 📄 许可证
MIT License - 详见 [LICENSE](../../LICENSE) 文件。
## 🤝 贡献
欢迎贡献代码!请查看 [贡献指南](../../CONTRIBUTING.md)。
---