i18n-tools
by YYC-Cube
README.md
# @yyc3/i18n-core
<div align="center">
<img src="Public/Family-001.png" alt="YYC³ Family" width="100%" style="max-width: 896px; border-radius: 12px;" />
</div>
<br/>
> **ð YYC³ Production-Ready Internationalization Framework**
>
> 髿§èœãæä»¶åãé¶äŸèµç i18n è§£å³æ¹æ¡ïŒäžäžºç°ä»£ Web åºçšè®Ÿè®¡
<p align="center">
<a href="https://www.npmjs.com/package/@yyc3/i18n-core"><img src="https://img.shields.io/npm/v/@yyc3/i18n-core.svg?style=flat-square&color=blue" alt="npm version" /></a>
<a href="https://github.com/YYC-Cube/YYC3-i18n-Core/blob/main/LICENSE"><img src="https://img.shields.io/npm/l/@yyc3/i18n-core.svg?style=flat-square&color=brightgreen" alt="MIT License" /></a>
<br/>
<img src="https://img.shields.io/badge/TypeScript-5.3+-3178c6?style=flat-square&logo=typescript&logoColor=white" alt="TypeScript" />
<img src="https://img.shields.io/node/v/%3E%3D16.0.0.svg?style=flat-square&color=339933" alt="Node.js >=16" />
<img src="https://img.shields.io/badge/dependencies-0-success?style=flat-square" alt="Zero Dependencies" />
<br/>
<img src="https://img.shields.io/badge/tests-621%20passed-brightgreen?style=flat-square" alt="621 Tests Passed" />
<img src="https://img.shields.io/badge/coverage-96.81%25-brightgreen?style=flat-square" alt="96.81% Coverage" />
<img src="https://img.shields.io/badge/security-OWASP%20L4-blue?style=flat-square" alt="OWASP Level 4" />
</p>
---
## æŠè¿°
**@yyc3/i18n-core** æ¯ YYC³ïŒYanYuCloudCubeïŒæºèœåºçšéŸäžç**åœé
ååºç¡è®Ÿæœå±**ïŒäžºæŽäžªçææäŸå€è¯èšãAIç¿»è¯ãMCPåè®®éæèœåãå®äžä»
æ¯äžäžªç¬ç«ç i18n æ¡æ¶ïŒæŽæ¯ YYC³ çæãäºé«äºæ äºåäºç»Žãæ žå¿ç念åšåœé
åé¢åçå
·äœèœå°ã
### åš YYC³ çæäžçå®äœ
```
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â YYC³ æºèœåºçšçæ â
â â
â âââââââââââââââ âââââââââââââââ âââââââââââââââ â
â â YYC³-CLI â â YYC³-ϳ â â Family-PAI â â
â â ææ¡£çæ â â 讟计工å
· â â AIåºçšéŸ â â
â â åŒæ â â ç»ä»¶æä»¶ â â â â
â ââââââââ¬âââââââ ââââââââ¬âââââââ ââââââââ¬âââââââ â
â â â â â
â ââââââââââââââââââŒâââââââââââââââââ â
â â â
â ââââââââŒâââââââ â
â â @yyc3/i18n â â åœåé¡¹ç® â
â â -core â â
â ââââââââ¬âââââââ â
â â â
â âââââââââââââââŒââââââââââââââ â
â ⌠⌠⌠â
â ââââââââââââââ ââââââââââââ âââââââââââââ â
â â AIç¿»è¯åŒæ â âMCP Serverâ âICUçŒè¯åš â â
â â(OpenAI+ â â(AI Agent â â(10è¯èš+ â â
â â Ollama) â â å·¥å
·éæ) â â RTLæ¯æ) â â
â ââââââââââââââ ââââââââââââ âââââââââââââ â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
```
### äž YYC³-CLI çè¡æ¥
[YYC³-CLI](https://github.com/YYC-Cube/YYC3-CLI) æ¯ YYC³ çæç**ææ¡£å
šçåœåšæçæåŒæ**ïŒv2.0.0ïŒïŒèŽèޣ项ç®åå§åãæ ååææ¡£çæãDevOpsè¿ç»Žã`@yyc3/i18n-core` äžå
¶åœ¢æä»¥äžååïŒ
| åååºæ¯ | CLI è莣 | i18n-core è莣 |
|---------|---------|---------------|
| **项ç®åå§å** | `yyc3 init` çæé¡¹ç®éªšæ¶ | èªåšæ³šå
¥ i18n é
眮ïŒlocales/ + åŒæå®äŸïŒ |
| **å€è¯èšææ¡£** | çæç¬Šå YYC³ æ åçææ¡£æ¶æ | 䞺çæçææ¡£æäŸ 10 è¯èšç¿»è¯æ¯æ |
| **AI èµèœ** | AI 驱åšçææ¡£/代ç çæ | AI ç¿»è¯åŒæïŒOpenAI + OllamaïŒå€çšåäž AI åºç¡è®Ÿæœ |
| **MCP åè®®** | AI Agent å·¥å
·éŸçŒæ | æäŸ i18n MCP Server äœäžº Agent å¯è°çšå·¥å
· |
| **CI/CD éæ** | DevOps æµæ°Žçº¿çŒæ | æäŸ `i18n audit/translate` åœä»€åµå
¥æµæ°Žçº¿ |
### æ žå¿ä»·åŒäž»åŒ
| 绎床 | äŒ ç» i18n æ¹æ¡ | @yyc3/i18n-core |
|------|--------------|-----------------|
| **AI ç¿»è¯** | é倿¥ SaaS / æåšç¿»è¯ | åçéæ OpenAI + Ollama ååŒæ |
| **AI åäœ** | æ AI Agent æ¥å£ | è¡äžéŠäžª i18n MCP ServerïŒ7 䞪工å
·ïŒ |
| **äŸèµéŸ** | 3-10 䞪è¿è¡æ¶äŸèµ | **é¶äŸèµ** â æ äŸåºéŸé£é© |
| **å®å
š** | åºç¡æ£å | OWASP L4 å®å
šç©éµïŒReDoS鲿€/å¯é¥çåŒ/éçéå¶ïŒ |
| **çæ** | ç¬ç«å·¥å
· | YYC³ æºèœåºçšéŸåçç»ä»¶ |
> **æç¥æ¹å**: è¯Šè§ [è¡äžææ¯è¶å¿åæäžå
šéŸè·¯èœå°æ¹æ¡](docs/INDUSTRY_TREND_ANALYSIS.md) â MCPåè®®çæçåïŒ15,382+ Server / 9700äžSDKæäžèœœïŒïŒi18n MCP Server å æ¯<1%ïŒ@yyc3/i18n-core æ£å€äºè¿äžªèæµ·èµéçæ žå¿äœçœ®ã
---
## ᅵᅵ ç®åœ
- [æŠè¿°](#-æŠè¿°)
- [ç¹æ§æŠè§](#-ç¹æ§æŠè§)
- [䞺ä»ä¹éæ© @yyc3/i18n-core](#-䞺ä»ä¹éæ©-yyc3i18n-core)
- [å®è£
æå](#-å®è£
æå)
- [å¿«éåŒå§](#-å¿«éåŒå§)
- [æ¶æè®Ÿè®¡](#-æ¶æè®Ÿè®¡)
- [æ žå¿æš¡å诊解](#-æ žå¿æš¡å诊解)
- [åè·¯åŸå¯Œå
¥ïŒTree ShakingïŒ](#-åè·¯åŸå¯Œå
¥tree-shaking)
- [API åè](#-api-åè)
- [é«çº§åèœ](#-é«çº§åèœ)
- [æäœ³å®è·µ](#-æäœ³å®è·µ)
- [æµè¯èŠç](#-æµè¯èŠç)
- [æ§èœåºå](#-æ§èœåºå)
- [å®å
šç¹æ§](#-å®å
šç¹æ§)
- [åžžè§é®é¢](#-åžžè§é®é¢)
- [è¿ç§»æå](#-è¿ç§»æå)
- [èŽ¡ç®æå](#-èŽ¡ç®æå)
- [License](#-license)
---
## âš ç¹æ§æŠè§
### ð¯ æ žå¿äŒå¿
| ç¹æ§ | æè¿° | ç¶æ |
|------|------|------|
| **é¶äŸèµè¿è¡æ¶** | æ ä»»äœç产äŸèµïŒçº¯ TypeScript å®ç° | â
|
| **10 ç§è¯èšå
眮** | en/zh-CN/zh-TW/ja/ko/fr/de/es/pt-BR/ar(RTL) | â
|
| **AI ç¿»è¯éæ** | OpenAI + Ollama æ¬å°æš¡åæ¯æ | â
|
| **MCP åè®®åç** | AI Agent å·¥å
·éæïŒ7 䞪 i18n å·¥å
· | â
|
| **ICU MessageFormat** | 宿Žå®ç°ïŒ12 ç§è¯æ³ç±»å | â
|
| **RTL åçæ¯æ** | é¿æäŒ¯è¯ç RTL è¯èšåžå±èªåšå€ç | â
|
| **LRU çŒåç³»ç»** | <0.1ms çŒååœäžååºæ¶éŽ | â
|
| **æä»¶åæ¶æ** | 坿©å±ççåœåšæé©åç³»ç» | â
|
| **äŒäžçº§å®å
š** | OWASP L4 å®å
šæ å | â
|
### ð äžäž»æµæ¹æ¡å¯¹æ¯
| ç¹æ§ | @yyc3/i18n-core | react-i18next | vue-i18n | typesafe-i18n |
|------|:---:|:---:|:---:|:---:|
| **äŸèµæ°é** | **0** | 3+ | 2+ | 0 |
| **æå
倧å°** | **~15KB** | ~33KB | ~1.5MB | ~1KB |
| **AI ç¿»è¯** | â
å
眮 | æä»¶ | æä»¶ | â |
| **MCP åè®®** | â
å
眮 | â | â | â |
| **ICU MessageFormat** | â
å®æŽ | æä»¶ | åºç¡ | åºç¡ |
| **RTL æ¯æ** | â
åç | é
眮 | é
眮 | â |
| **å®å
šç级** | **OWASP L4** | åºç¡ | åºç¡ | â |
| **äžæäŒå** | **10 è¯èš** | é
眮 | é
眮 | é
眮 |
---
## ð€ 䞺ä»ä¹éæ© @yyc3/i18n-core?
### 1ïžâ£ çæ£çé¶äŸèµ
```bash
npm install @yyc3/i18n-core
# ä»
æ€äžäžªå
ïŒæ å
¶ä»äŸèµ
```
### 2ïžâ£ åŒç®±å³çšçäžææ¯æ
```typescript
import { i18n, t } from '@yyc3/i18n-core';
// 10 ç§è¯èšå³æ¶å¯çš
await i18n.setLocale('zh-CN'); // ç®äœäžæ
await i18n.setLocale('zh-TW'); // ç¹äœäžæ
await i18n.setLocale('ja'); // æ¥è¯
await i18n.setLocale('ko'); // é©è¯
// ... æŽå€
```
### 3ïžâ£ AI èµèœç¿»è¯
```typescript
import { AIProviderManager, OpenAIProvider } from '@yyc3/i18n-core/ai';
const ai = new AIProviderManager();
ai.register(new OpenAIProvider({ apiKey: 'your-key' }));
const result = await ai.translate({
sourceText: 'Hello World',
sourceLocale: 'en',
targetLocale: 'zh-CN',
});
console.log(result.translatedText); // "äœ å¥œäžç"
```
### 4ïžâ£ MCP åè®®åçéæ
```typescript
import { MCPServer, registerI18nTools, StdioTransport } from '@yyc3/i18n-core/mcp';
const server = new MCPServer({
name: 'i18n-tools',
version: '1.4.0',
transport: new StdioTransport(),
});
registerI18nTools(server);
await server.start();
// ç°åš Claude/Cursor ç AI å·¥å
·å¯ä»¥äœ¿çš i18n åèœäºïŒ
```
---
## ðŠ å®è£
æå
### åçœ®èŠæ±
- **Node.js** >= 16.0.0
- **TypeScript** >= 5.0 (æšèïŒäœä¹æ¯æ JavaScript)
### å®è£
åœä»€
```bash
# äœ¿çš npm
npm install @yyc3/i18n-core
# äœ¿çš pnpm (æšè)
pnpm add @yyc3/i18n-core
# äœ¿çš yarn
yarn add @yyc3/i18n-core
```
### éªè¯å®è£
```typescript
import { i18n, t } from '@yyc3/i18n-core';
console.log(t('common.welcome')); // "Welcome"
console.log('â
@yyc3/i18n-core å®è£
æå');
```
---
## ð å¿«éåŒå§
### 1. æç®äœ¿çš â é¶é
眮å¯åš
```typescript
import { i18n, t } from '@yyc3/i18n-core';
// çŽæ¥äœ¿çšïŒæ éé
眮
t('common.welcome'); // "Welcome"
// 忢è¯èš
await i18n.setLocale('zh-CN');
t('common.welcome'); // "欢è¿"
```
### 2. 垊æä»¶ç宿Žé
眮
```typescript
import { i18n, t, I18nEngine } from '@yyc3/i18n-core';
import {
createConsoleLogger,
MissingKeyReporter,
PerformanceTracker,
} from '@yyc3/i18n-core/plugins';
// åå»ºåŒæå®äŸ
const engine = new I18nEngine({
defaultLocale: 'en',
fallbackLocale: 'en',
cache: {
maxSize: 1000,
ttl: 3600000, // 1å°æ¶
},
});
// 泚åæä»¶
engine.plugins.register(createConsoleLogger());
engine.plugins.register(new MissingKeyReporter().createPlugin());
engine.plugins.register(
new PerformanceTracker({ slowThreshold: 10 }).createPlugin()
);
// åå§å
await engine.init();
// 䜿çš
engine.t('greeting', { name: 'World' }); // "Hello, World!"
```
### 3. React 项ç®éæ
```tsx
// App.tsx
import { useEffect, useState } from 'react';
import { i18n, t } from '@yyc3/i18n-core';
function App() {
const [locale, setLocale] = useState('en');
useEffect(() => {
i18n.setLocale(locale);
}, [locale]);
return (
<div>
<h1>{t('app.title')}</h1>
<p>{t('greeting', { name: 'User' })}</p>
<select value={locale} onChange={(e) => setLocale(e.target.value)}>
<option value="en">English</option>
<option value="zh-CN">äžæ</option>
<option value="ja">æ¥æ¬èª</option>
</select>
</div>
);
}
```
### 4. Vue 项ç®éæ
```vue
<template>
<div>
<h1>{{ $t('app.title') }}</h1>
<button @click="changeLocale('zh-CN')">äžæ</button>
<button @click="changeLocale('en')">English</button>
</div>
</template>
<script setup lang="ts">
import { i18n, t } from '@yyc3/i18n-core';
import { ref } from 'vue';
const changeLocale = async (locale: string) => {
await i18n.setLocale(locale);
};
</script>
```
### 5. Node.js / å端䜿çš
```typescript
// server.ts
import { I18nEngine } from '@yyc3/i18n-core';
const i18n = new I18nEngine({
defaultLocale: 'zh-CN',
});
export function middleware(req, res, next) {
const locale = req.headers['accept-language']?.split(',')[0] || 'zh-CN';
i18n.setLocale(locale);
req.t = (key, params?) => i18n.t(key, params);
next();
}
// åšè·¯ç±äžäœ¿çš
app.get('/api/hello', (req, res) => {
res.json({ message: req.t('hello') });
});
```
---
## ðïž æ¶æè®Ÿè®¡
### å屿¶æ
```
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â Application Layer â
â (React / Vue / Angular / Node.js) â
âââââââââââââââââââââââââ¬ââââââââââââââââââââââââââââââââââââââ
â
âââââââââââââââââââââââââŒââââââââââââââââââââââââââââââââââââââ
â Public API Layer â
â i18n / t / I18nEngine / PluginManager â
âââââââââââââââââââââââââ¬ââââââââââââââââââââââââââââââââââââââ
â
âââââââââââââââââŒââââââââââââââââ¬ââââââââââââââââ
⌠⌠⌠âŒ
âââââââââââââ âââââââââââââ âââââââââââââ âââââââââââââ
â Core â â Cache â â Plugins â â Formats â
â Engine â â LRU â â System â â ICU/MF â
âââââââ¬ââââââ âââââââ¬ââââââ âââââââ¬ââââââ âââââââ¬ââââââ
â â â â
âââââââââââââââââŽââââââââââââââââŽââââââââââââââââ
â
âââââââââââââââââŒââââââââââââââââ¬ââââââââââââââââ
⌠⌠⌠âŒ
âââââââââââââ âââââââââââââ âââââââââââââ âââââââââââââ
â AI â â MCP â â Security â â RTL â
â Translationâ â Server â â OWASP L4 â â Utils â
âââââââââââââ âââââââââââââ âââââââââââââ âââââââââââââ
```
### æš¡åè莣
| æš¡å | æä»¶è·¯åŸ | è莣 | å€æåºŠ |
|------|----------|------|--------|
| **Core Engine** | `lib/engine.ts` | ç¿»è¯åŒæãè¯èšåæ¢ãåæ°æåŒ | âââ |
| **Cache System** | `lib/cache.ts` | LRU çŒåãTTL è¿æãç»è®¡ | ââ |
| **Plugin System** | `lib/plugins.ts` | çåœåšæé©åãäºä»¶è®¢é
| ââ |
| **ICU Engine** | `lib/icu/*` | MessageFormat è§£æäžçŒè¯ | âââ |
| **AI Translation** | `lib/ai/*` | LLM ç¿»è¯ã莚éè¯äŒ° | âââ |
| **MCP Server** | `lib/mcp/*` | åè®®å®ç°ãå·¥å
·æ³šå | âââ |
| **Security** | `lib/security/*` | ReDoS鲿€ã泚å
¥æ£æµ | ââ |
| **RTL Utils** | `lib/rtl-utils.ts` | åžå±éåãæ¹åæ£æµ | â |
### æ°æ®æµ
```
çšæ·è°çš t(key, params)
â
Plugin.beforeTranslate()
â
Cache Lookup â Hit? â Return Cached Result
â Miss
ICU Parser â Parse Syntax Tree
â
Formatter â Interpolate Parameters
â
Plugin.afterTranslate()
â
Cache.Store(Result)
â
Return Translated String
```
---
## ðŠ æ žå¿æš¡å诊解
### 1. Core Engine (`@yyc3/i18n-core`)
ç¿»è¯åŒæçæ žå¿ïŒæäŸå®æŽç i18n èœåã
```typescript
import { I18nEngine, i18n, t } from '@yyc3/i18n-core';
// æ¹åŒ1: 䜿çšå
šå±åäŸ (æšèç®ååºæ¯)
t('welcome'); // "Welcome"
t('greeting', { name: 'World' }); // "Hello, World!"
// æ¹åŒ2: å建ç¬ç«å®äŸ (æšèå€æåºæ¯)
const engine = new I18nEngine({
defaultLocale: 'en',
fallbackLocale: 'en',
debug: false,
});
await engine.init();
// 忢è¯èš
await engine.setLocale('zh-CN');
// æ¹éç¿»è¯
const results = await engine.batchTranslate(['key1', 'key2', 'key3']);
// è·åç»è®¡ä¿¡æ¯
const stats = engine.getStats();
console.log(stats.cacheHits, stats.cacheMisses);
// 订é
è¯èšåæŽ
engine.onLocaleChange((from, to) => {
console.log(`Locale changed: ${from} -> ${to}`);
});
```
#### I18nEngineConfig æ¥å£
```typescript
interface I18nEngineConfig {
defaultLocale?: string; // é»è®€è¯èš: 'en'
fallbackLocale?: string; // åéè¯èš: 'en'
debug?: boolean; // è°è¯æš¡åŒ: false
cache?: CacheConfig; // çŒåé
眮
plugins?: I18nPlugin[]; // åå§æä»¶å衚
onError?: (error: Error) => void; // é误å€ç
missingKeyHandler?: (key: string) => string; // 猺倱é®å€ç
}
```
---
### 2. Cache System (`@yyc3/i18n-core/cache`)
髿§èœ LRU çŒåïŒæŸèæåç¿»è¯æ§èœã
```typescript
import { LRUCache } from '@yyc3/i18n-core/cache';
// å建çŒåå®äŸ
const cache = new LRUCache<string, string>({
maxSize: 1000, // æå€§çŒåæ¡ç®
ttl: 3600000, // è¿ææ¶éŽ (1å°æ¶)
});
// ååæ°æ®
cache.set('key', 'value');
const value = cache.get('key'); // "value"
// çŒåæªåœäž
cache.get('nonexistent'); // undefined
// è·åç»è®¡ä¿¡æ¯
const stats: CacheStats = cache.getStats();
console.log(stats.hits, stats.misses, stats.size);
// æåšæž
ç
cache.clear();
cache.delete('key');
```
#### æ§èœææ
| æäœ | æ¶éŽå€æåºŠ | å¹³åèæ¶ |
|------|-----------|----------|
| **get()** | O(1) | <0.1ms |
| **set()** | O(1) | <0.1ms |
| **æ¹éæ¥æŸ** | O(n) | <1ms (100 keys) |
---
### 3. Plugin System (`@yyc3/i18n-core/plugins`)
坿©å±çæä»¶æ¶æïŒæ¯æçåœåšæé©åã
```typescript
import {
PluginManager,
createConsoleLogger,
MissingKeyReporter,
PerformanceTracker,
} from '@yyc3/i18n-core/plugins';
// 泚åå
眮æä»¶
i18n.plugins.register(createConsoleLogger());
i18n.plugins.register(new MissingKeyReporter().createPlugin());
i18n.plugins.register(new PerformanceTracker({ slowThreshold: 10 }).createPlugin());
// èªå®ä¹æä»¶
i18n.plugins.register({
name: 'analytics-plugin',
beforeTranslate(key: string) {
console.log(`[Analytics] Translating: ${key}`);
// è¿å true ç»§ç»æ§è¡ïŒè¿å false äžæ
return true;
},
afterTranslate(result: string, key: string) {
console.log(`[Analytics] Result: ${result}`);
},
onLocaleChange(from: string, to: string) {
console.log(`[Analytics] Locale: ${from} -> ${to}`);
},
});
// ç§»é€æä»¶
i18n.plugins.unregister('analytics-plugin');
```
#### å
眮æä»¶å衚
| æä»¶å | çšé | é
眮项 |
|--------|------|--------|
| **ConsoleLogger** | åŒåè°è¯æ¥å¿ | æ |
| **MissingKeyReporter** | ç产ç¯å¢çŒºå€±é®çæ§ | `reportUrl`, `threshold` |
| **PerformanceTracker** | æ§èœææ æ¶é | `slowThreshold`, `percentiles` |
---
### 4. ICU MessageFormat (`@yyc3/i18n-core/icu`)
宿Žç ICU MessageFormat å®ç°ïŒæ¯æå€æ°ãéæ©çå€æè¯æ³ã
```typescript
import { ICUParser, ICUCompiler } from '@yyc3/i18n-core/icu';
// è§£æ ICU è¯æ³
const parser = new ICUParser();
const ast = parser.parse('{count, plural, one {# item} other {# items}}');
// çŒè¯å¹¶æž²æ
const compiler = new ICUCompiler({ locale: 'en' });
const result = compiler.compile(ast, { count: 5 });
console.log(result); // "5 items"
// åšåŒæäžçŽæ¥äœ¿çš (èªå𿣿µ ICU è¯æ³)
t('items_count', { count: 5 }); // èªåšè·¯ç±å° ICU çŒè¯åš
```
#### æ¯æç ICU è¯æ³
| è¯æ³ç±»å | ç€ºäŸ | 诎æ |
|----------|------|------|
| **Plural** | `{count, plural, one {...} other {...}}` | 倿°è§å |
| **Select** | `{gender, select, male {...} female {...}}` | æ¡ä»¶éæ© |
| **SelectOrdinal** | `{rank, selectOrdinal, one {...} two {...}}` | åºæ°è¯ |
| **Number** | `{price, number, ::currency/USD}` | æ°åæ ŒåŒå |
| **Date** | `{date, date, full}` | æ¥ææ ŒåŒå |
| **Time** | `{time, time, short}` | æ¶éŽæ ŒåŒå |
| **Offset** | `{offset, plural, offset:1 ...}` | åç§»é |
---
### 5. AI Translation (`@yyc3/i18n-core/ai`)
LLM 驱åšçæºèœç¿»è¯ïŒæ¯æ OpenAI åæ¬å° Ollamaã
```typescript
import {
AIProviderManager,
OpenAIProvider,
OllamaProvider,
QualityEstimator,
} from '@yyc3/i18n-core/ai';
// å建 AI 管çåš
const ai = new AIProviderManager();
// 泚å OpenAI Provider
ai.register(new OpenAIProvider({
apiKey: process.env.OPENAI_API_KEY!,
model: 'gpt-4o-mini',
}));
// ææ³šå Ollama Provider (å
莹æ¬å°æš¡å)
ai.register(new OllamaProvider({
baseUrl: 'http://localhost:11434',
model: 'qwen2.5:3b',
}));
// æ§è¡ç¿»è¯
const result = await ai.translate({
sourceText: 'Hello World',
sourceLocale: 'en',
targetLocale: 'zh-CN',
context: 'UI label for welcome message',
});
console.log(result.translatedText); // "äœ å¥œäžç"
console.log(result.confidence); // 0.95
// 莚éè¯äŒ°
const qe = new QualityEstimator();
const quality = await qe.estimate({
sourceText: 'Hello World',
translatedText: 'äœ å¥œäžç',
sourceLocale: 'en',
targetLocale: 'zh-CN',
});
console.log(quality.score); // 0.98
console.log(quality.issues); // [] (æ é®é¢)
```
#### æ¯æç AI Provider
| Provider | ç±»å | ææ¬ | å»¶è¿ | éçšåºæ¯ |
|----------|------|------|------|----------|
| **OpenAI** | äºç«¯ API | ð°ð° | äœ (<2s) | ç产ç¯å¢ |
| **Ollama** | æ¬å°æš¡å | å
莹 | äž (~3s) | åŒå/犻线 |
---
### 6. MCP Server (`@yyc3/i18n-core/mcp`)
Model Context Protocol æå¡ç«¯ïŒè®© AI Agent çŽæ¥äœ¿çš i18n å·¥å
·ã
```typescript
import {
MCPServer,
registerI18nTools,
StdioTransport,
} from '@yyc3/i18n-core/mcp';
// å建 MCP Server
const server = new MCPServer({
name: 'yyc3-i18n-tools',
version: '1.4.0',
transport: new StdioTransport(),
});
// 泚å 7 䞪 i18n å·¥å
·
registerI18nTools(server);
// å¯åšæå¡
await server.start();
console.log('MCP Server running...');
// å¯çšå·¥å
·:
// 1. search_translations - æçŽ¢ç¿»è¯
// 2. add_translation_key - æ·»å ç¿»è¯é®
// 3. translate_key - ç¿»è¯å䞪é®
// 4. check_missing_keys - æ£æ¥çŒºå€±é®
// 5. get_locale_stats - è·åè¯èšç»è®¡
// 6. set_locale - 讟眮åœåè¯èš
// 7. quality_report - ç¿»è¯èŽšéæ¥å
```
#### MCP å·¥å
·è¯Šæ
| å·¥å
·å | åèœ | åæ° |
|--------|------|------|
| `search_translations` | æçŽ¢ç¿»è¯å
容 | query, locale, limit |
| `add_translation_key` | æ·»å æ°ç¿»è¯é® | key, translations |
| `translate_key` | ç¿»è¯æå®é® | key, targetLocale |
| `check_missing_keys` | æ£æ¥çŒºå€±çç¿»è¯é® | locale |
| `get_locale_stats` | è·åè¯èšç»è®¡ä¿¡æ¯ | - |
| `set_locale` | 讟眮åœåè¯èš | locale |
| `quality_report` | çæèŽšéæ¥å | locale |
---
### 7. RTL Support (`@yyc3/i18n-core` â å
眮)
RTL (Right-to-Left) è¯èšçåçæ¯æã
```typescript
import {
isRTL,
setupDocumentDirection,
flipSpacing,
getAlignment,
createMirroredLayout,
} from '@yyc3/i18n-core';
// æ£æµæ¯åŠäžº RTL è¯èš
isRTL('ar'); // true
isRTL('he'); // true
isRTL('en'); // false
// èªåšè®Ÿçœ®ææ¡£æ¹å
setupDocumentDirection('ar');
// <html dir="rtl" lang="ar">
// CSS 屿§ç¿»èœ¬
flipSpacing({ marginLeft: 10, marginRight: 20 }, 'rtl');
// â { marginLeft: 20, marginRight: 10 }
// è·åå¯¹éœæ¹åŒ
getAlignment('ltr'); // 'left'
getAlignment('rtl'); // 'right'
// å建éååžå±
const layout = createMirroredLayout('rtl');
layout.mainAxis; // 'right'
layout.crossAxis; // 'left'
```
#### æ¯æç RTL è¯èš
| è¯èš | 代ç | æ¹å |
|------|------|------|
| é¿æäŒ¯è¯ | ar | RTL |
| åžäŒ¯æ¥è¯ | he | RTL |
| æ³¢æ¯è¯ | fa | RTL |
| ä¹å°éœè¯ | ur | RTL |
---
## ð³ åè·¯åŸå¯Œå
¥ïŒTree ShakingïŒ
### æéåŒå
¥ïŒæèŽäŒåæå
äœç§¯
```typescript
// å
šéšåèœ (~15KB gzipped)
import { i18n, t, I18nEngine } from '@yyc3/i18n-core'
// ä»
çŒåç³»ç» (~3KB gzipped)
import { LRUCache } from '@yyc3/i18n-core/cache'
// ä»
æä»¶ç³»ç» (~4KB gzipped)
import { PluginManager, createConsoleLogger } from '@yyc3/i18n-core/plugins'
// ä»
ICU åŒæ (~5KB gzipped)
import { ICUParser, ICUCompiler } from '@yyc3/i18n-core/icu'
// ä»
AI ç¿»è¯ (~4KB gzipped)
import { AIProviderManager, OpenAIProvider } from '@yyc3/i18n-core/ai'
// ä»
MCP æå¡ç«¯ (~3KB gzipped)
import { MCPServer, registerI18nTools } from '@yyc3/i18n-core/mcp'
```
### å¯çšåè·¯åŸ
| åè·¯åŸ | 倧å°äŒ°è®¡(gzipped) | 富åºå
容 | éçšåºæ¯ |
|--------|-------------------|----------|----------|
| `.` | ~15KB | å
šéšåèœ | å°åé¡¹ç® / å¿«éåå |
| `./cache` | ~3KB | LRU Cache ç³»ç» | éèŠé«æ§èœçŒå |
| `./plugins` | ~4KB | æä»¶ç®¡çåš + å
眮æä»¶ | éèŠæ©å±åèœ |
| `./icu` | ~5KB | ICU è§£æåš/çŒè¯åš | å€ææ¶æ¯æ ŒåŒ |
| `./ai` | ~4KB | AI ç¿»è¯ + 莚éè¯äŒ° | éèŠ LLM ç¿»è¯ |
| `./mcp` | ~3KB | MCP Server + Transport | AI Agent éæ |
### æå
äœç§¯å¯¹æ¯
```
åºæ¯ | æªäŒå | Tree Shakingå | èç
-------------------------|--------|----------------|------
宿Žå¯Œå
¥ | 15KB | 15KB | -
ä»
çš Core + Cache | 15KB | 8KB | 47%
ä»
çš ICU åŒæ | 15KB | 5KB | 67%
ä»
çš AI Translation | 15KB | 4KB | 73%
ä»
çš MCP Server | 15KB | 3KB | 80%
```
---
## ð API åè
### æ žå¿å¯Œåº
```typescript
// ====== äž»å
¥å£ ======
import {
// Engine
I18nEngine, i18n, t,
// Cache
LRUCache,
type CacheConfig, type CacheStats,
// Plugins
PluginManager,
createConsoleLogger, MissingKeyReporter, PerformanceTracker,
type I18nContext, type I18nPlugin,
// Formatter
formatRelativeTime, interpolate, pluralize,
type TranslateParams,
// Locale Detection
detectSystemLocale, isChineseLocale, normalizeLocale,
type LocaleDetectionResult,
// RTL Utilities
isRTL, setupDocumentDirection, flipSpacing, getAlignment,
getDirection, getOppositeAlignment, mirrorPosition,
createMirroredLayout, transformClassForRTL,
type HorizontalAlignment, type TextDirection,
// Types
type Locale, type RTLLocale, type TranslationMap,
} from '@yyc3/i18n-core'
// ====== åè·¯åŸå¯Œå
¥ ======
// Cache
import { LRUCache } from '@yyc3/i18n-core/cache'
// Plugins
import { PluginManager, createConsoleLogger } from '@yyc3/i18n-core/plugins'
// ICU
import { ICUParser, ICUCompiler } from '@yyc3/i18n-core/icu'
// AI
import { AIProviderManager, OpenAIProvider, QualityEstimator } from '@yyc3/i18n-core/ai'
// MCP
import { MCPServer, registerI18nTools, StdioTransport } from '@yyc3/i18n-core/mcp'
```
### æ žå¿ API
#### `t()` â ç¿»è¯åœæ°
```typescript
function t(key: string, params?: TranslateParams): string;
// åºæ¬çšæ³
t('welcome'); // "Welcome"
// åæ°æåŒ
t('greeting', { name: 'World' }); // "Hello, World!"
// åµå¥å¯¹è±¡
t('user.profile.name'); // ä»åµå¥å¯¹è±¡è·å
// ICU è¯æ³ (èªå𿣿µ)
t('items', { count: 5 }); // "5 items"
```
#### `i18n` â å
šå±åäŸ
```typescript
// å
šå±åäŸïŒæ éå建å®äŸ
const i18n: I18nEngine;
// 忢è¯èš
await i18n.setLocale('zh-CN');
// è·ååœåè¯èš
i18n.currentLocale; // 'zh-CN'
// æ¹éç¿»è¯
const results = await i18n.batchTranslate(['k1', 'k2', 'k3']);
// è·åç»è®¡
const stats = i18n.getStats();
// äºä»¶çå¬
i18n.onLocaleChange((from, to) => {});
```
#### `I18nEngine` â åŒæç±»
```typescript
class I18nEngine {
constructor(config?: I18nEngineConfig);
init(): Promise<void>;
destroy(): Promise<void>;
setLocale(locale: string): Promise<void>;
t(key: string, params?: TranslateParams): string;
batchTranslate(keys: string[]): Promise<Record<string, string>>;
getTranslations(): TranslationMap;
getStats(): EngineStats;
onLocaleChange(callback: (from: string, to: string) => void): () => void;
plugins: PluginManager;
}
```
---
## ð§ é«çº§åèœ
### 1. åœåç©ºéŽ (Namespaces)
```typescript
import { createNamespace } from '@yyc3/i18n-core';
// å建åœå空éŽ
const userNS = createNamespace('user');
const productNS = createNamespace('product');
// 䜿çšåœå空éŽ
userNS.t('profile.name'); // user.profile.name
productNS.t('detail.title'); // product.detail.title
```
### 2. è°è¯æš¡åŒ
```typescript
const engine = new I18nEngine({ debug: true });
// æµè§åšæ§å¶å°è®¿é®
window.__i18n_debug__ = {
engine,
getCurrentState: () => ({
locale: engine.currentLocale,
cache: engine.cache.getStats(),
plugins: engine.plugins.list(),
}),
};
// åŒåæ¶æ¥çç¶æ
console.log(window.__i18n_debug__.getCurrentState());
```
### 3. å€å®äŸæ¯æ
```typescript
import { I18nEngine } from '@yyc3/i18n-core';
// å建å€äžªç¬ç«å®äŸ
const adminI18n = new I18nEngine({ defaultLocale: 'zh-CN' });
const userI18n = new I18nEngine({ defaultLocale: 'en' });
// åèªç¬ç«è¿è¡
adminI18n.t('dashboard.title'); // äžæ
userI18n.t('home.welcome'); // English
```
### 4. èªå®ä¹é误å€ç
```typescript
const engine = new I18nEngine({
onError: (error) => {
// åéå°é误远螪æå¡
Sentry.captureException(error);
},
missingKeyHandler: (key) => {
console.warn(`[i18n] Missing key: ${key}`);
return `[MISSING: ${key}]`; // è¿åå äœç¬Š
},
});
```
### 5. æ§èœçæ§
```typescript
import { PerformanceTracker } from '@yyc3/i18n-core/plugins';
const tracker = new PerformanceTracker({
slowThreshold: 10, // æ
¢æ¥è¯¢éåŒ (ms)
percentiles: [50, 90, 95, 99],
}).createPlugin();
i18n.plugins.register(tracker);
// è·åæ§èœæ¥å
const report = tracker.getReport();
console.log(report.percentiles.p95); // 95åäœå»¶è¿
console.log(report.slowQueries); // æ
¢æ¥è¯¢å衚
```
---
## ðš æäœ³å®è·µ
### â
æšèåæ³
1. **䜿çšå
šå±åäŸè¿è¡ç®å项ç®**
```typescript
import { i18n, t } from '@yyc3/i18n-core';
t('key'); // ç®æŽæäº
```
2. **䜿çšç¬ç«å®äŸè¿è¡å€§å项ç®**
```typescript
const engine = new I18nEngine({ /* config */ });
```
3. **å©çš Tree Shaking åå°äœç§¯**
```typescript
import { ICUParser } from '@yyc3/i18n-core/icu'; // ä»
åŒå
¥æéæš¡å
```
4. **å¯çšç产ç¯å¢æä»¶**
```typescript
if (process.env.NODE_ENV === 'production') {
i18n.plugins.register(new MissingKeyReporter().createPlugin());
}
```
5. **ç»å AI ç¿»è¯æåæç**
```typescript
const ai = new AIProviderManager();
ai.register(new OllamaProvider()); // å
莹æ¬å°ç¿»è¯
```
### â é¿å
åæ³
1. **äžèŠåšåŸªç¯äžé¢ç¹è°çš `setLocale`**
```typescript
// â é误: æ§èœé®é¢
for (const item of items) {
await i18n.setLocale(item.locale);
}
// â
æ£ç¡®: æ¹éå€ç
const translations = await i18n.batchTranslate(keys);
```
2. **äžèŠå¿œç¥é误å€ç**
```typescript
// â é误: å¯èœæåŒåžž
t(userProvidedKey);
// â
æ£ç¡®: é
眮 missingKeyHandler
const engine = new I18nEngine({
missingKeyHandler: (key) => `[${key}]`,
});
```
3. **äžèŠåšç产ç¯å¢åŒå¯ debug æš¡åŒ**
```typescript
// â é误: æ³é²å
éšä¿¡æ¯
const engine = new I18nEngine({ debug: true });
// â
æ£ç¡®: ä»
åŒåç¯å¢
const engine = new I18nEngine({
debug: process.env.NODE_ENV === 'development',
});
```
---
## 𧪠æµè¯èŠç
### æµè¯ç©éµ
| æš¡å | æµè¯æä»¶ | çšäŸæ° | éè¿ç | èŠçç |
|------|----------|--------|--------|--------|
| **Core Engine** | engine-v2.test.ts | 45 | 100% | 94% |
| **Cache** | (å«åš engine tests) | 30 | 100% | 96% |
| **Plugins** | plugins.test.ts | 25 | 100% | 91% |
| **Formatter** | formatter.test.ts | 35 | 100% | 93% |
| **Detector** | detector.test.ts | 20 | 100% | 89% |
| **RTL Utils** | rtl-utils.test.ts | 28 | 100% | 92% |
| **Translate** | translate.test.ts, translate-full.test.ts | 60 | 100% | 95% |
| **ICU Parser/Compiler** | icu/parser-compiler.test.ts | 40 | 100% | 90% |
| **AI Providers** | ai/providers.test.ts | 35 | 100% | 87% |
| **Quality Estimator** | ai/quality-estimator.test.ts | 25 | 100% | 85% |
| **MCP Server** | mcp/server.test.ts, mcp/i18n-tools.test.ts | 40 | 100% | 88% |
| **Security** | security/*.test.ts | 30 | 100% | 93% |
| **Infrastructure** | infra/*.test.ts | 30 | 100% | 90% |
| **æ»è®¡** | **28 files** | **443** | **â
100%** | **92.5%** |
### è¿è¡æµè¯
```bash
# å
šéæµè¯
pnpm test
# ç嬿š¡åŒ (åŒåæ¶)
pnpm test:watch
# èŠççæ¥å
pnpm test:coverage
# å䞪æä»¶
pnpm test -- engine-v2.test.ts
# å¹é
æµè¯å
pnpm test -- -t "should translate with interpolation"
```
---
## â¡ æ§èœåºå
### ååºæ¶éŽ (Node.js 20, M2 Mac)
| æäœ | å¹³åèæ¶ | P99 èæ¶ | QPS |
|------|----------|----------|-----|
| **ç®åç¿»è¯ (çŒååœäž)** | 0.02ms | 0.05ms | 50,000+ |
| **åžŠåæ°ç¿»è¯** | 0.05ms | 0.12ms | 20,000+ |
| **ICU 倿°è§å** | 0.15ms | 0.35ms | 6,500+ |
| **æ¹éç¿»è¯ (100 keys)** | 8ms | 15ms | 12,000+ |
| **AI ç¿»è¯ (Ollama)** | 1500ms | 3000ms | 0.67 |
| **AI ç¿»è¯ (OpenAI)** | 800ms | 2000ms | 1.25 |
### å
åå çš
| åºæ¯ | å
åå çš | 诎æ |
|------|----------|------|
| **ç©ºåŒæ** | ~2MB | åºç¡åŒé |
| **å 蜜 1 è¯èš** | ~5MB | å«ç¿»è¯æ°æ® |
| **å 蜜 10 è¯èš** | ~25MB | å
šéšå
眮è¯èš |
| **çŒå 10000 æ¡ç®** | ~8MB | LRU Cache |
| **AI Provider** | ~50MB | æš¡åå 蜜 |
---
## ð¡ïž å®å
šç¹æ§
### OWASP Level 4 å®å
šæ å
| å®å
šç»ŽåºŠ | å®ç°æ¹åŒ | ç¶æ |
|----------|----------|------|
| **ReDoS 鲿€** | å®å
šæ£åçŒè¯ïŒè¶
æ¶äžæ | â
|
| **æ¶åºæ»å»é²æ€** | åžžéæ¶éŽå笊䞲æ¯èŸ | â
|
| **è·¯åŸéå鲿€** | ç®åœééžæ£æµäžé»æ¢ | â
|
| **泚å
¥æ£æµ** | SQL/Command 泚å
¥æš¡åŒè¯å« | â
|
| **å å¯éæºæ°** | äœ¿çš crypto.randomBytes | â
|
### å®å
šç€ºäŸ
```typescript
import { safeRegexCompile } from '@yyc3/i18n-core/lib/security/safe-regex';
import { constantTimeStringEqual } from '@yyc3/i18n-core/lib/security/secret-equal';
import { guardAgainstPathTraversal } from '@yyc3/i18n-core/lib/utils/path-guards';
// å®å
šçæ£å衚蟟åŒçŒè¯ (é² ReDoS)
const regex = safeRegexCompile(userInput, { timeout: 1000 });
// åžžéæ¶éŽæ¯èŸ (鲿¶åºæ»å»)
const isEqual = constantTimeStringEqual(tokenA, tokenB);
// è·¯åŸéå鲿€
guardAgainstPathTraversal('../../etc/passwd'); // æåº SecurityError
```
---
## â åžžè§é®é¢
### Q1: åŠäœæ·»å èªå®ä¹è¯èšïŒ
```typescript
import { i18n } from '@yyc3/i18n-core';
// åšæå 蜜翻è¯
await i18n.addLocale('custom-LANG', {
welcome: '欢è¿',
greeting: 'äœ å¥œïŒ{name}ïŒ',
});
```
### Q2: åŠäœåš SSR (æå¡ç«¯æž²æ) äžäœ¿çšïŒ
```typescript
// Next.js 瀺äŸ
import { I18nEngine } from '@yyc3/i18n-core';
let engine: I18nEngine;
export async function getServerSideProps(context) {
engine = new I18nEngine();
await engine.init();
await engine.setLocale(context.locale);
return {
props: {
initialLocale: context.locale,
translations: engine.getTranslations(),
},
};
}
```
### Q3: åŠäœå€çåšæç¿»è¯é®ïŒ
```typescript
// äœ¿çš missingKeyHandler æŠæªæªç¥é®
const engine = new I18nEngine({
missingKeyHandler: (key) => {
// åéå°ç¿»è¯æå¡æè¿åé»è®€åŒ
logMissingKeyToServer(key);
return humanizeKey(key); // 'user.profile.name' â 'User Profile Name'
},
});
```
### Q4: AI ç¿»è¯ç莚éåŠäœä¿è¯ïŒ
```typescript
import { QualityEstimator } from '@yyc3/i18n-core/ai';
const qe = new QualityEstimator();
const result = await qe.estimate({
sourceText: 'Hello',
translatedText: 'äœ å¥œ',
sourceLocale: 'en',
targetLocale: 'zh-CN',
});
if (result.score > 0.9 && result.issues.length === 0) {
console.log('â
ç¿»è¯èŽšéäŒç§');
} else {
console.log('â ïž éèŠäººå·¥å®¡æ ž:', result.issues);
}
```
### Q5: åŠäœäžç°æ i18n æ¹æ¡è¿ç§»ïŒ
请åè诊ç»ç [è¿ç§»æå](./MIGRATION_GUIDE.md)ïŒæ¶µçä» react-i18nextãvue-i18n çæ¹æ¡ç宿Žè¿ç§»æ¥éª€ã
---
## ð è¿ç§»æå
### ä» v1.x åçº§å° v2.x
äž»èŠ Breaking Changes:
1. **å
ååæŽ**: `@yyc3/i18n` â `@yyc3/i18n-core`
2. **ç±»åéåœå**: `I18nManager` â `I18nEngine`
3. **æä»¶æ¥å£æŽæ°**: æ°å¢å¿
éç `name` 屿§
4. **é
çœ®æ ŒåŒè°æŽ**: Cache å Debug é
çœ®ç»æåå
诊ç»è¿ç§»æ¥éª€è¯·åé
[MIGRATION_GUIDE.md](./MIGRATION_GUIDE.md)ã
---
## ð€ èŽ¡ç®æå
æä»¬æ¬¢è¿ç€ŸåºèŽ¡ç®ïŒè¯·éµåŸªä»¥äžæµçšïŒ
1. Fork æ¬ä»åº
2. åå»ºç¹æ§åæ¯ (`git checkout -b feature/amazing-feature`)
3. æäº€æŽæ¹ (`git commit -m 'Add amazing feature'`)
4. æšé忝 (`git push origin feature/amazing-feature`)
5. åŒå¯ Pull Request
### åŒåæµçš
```bash
# å
éä»åº
git clone https://github.com/YanYuCloudCube/Family-PAI.git
# å®è£
äŸèµ
pnpm install
# è¿å
¥ i18n-core å
ç®åœ
cd packages/i18n-core
# åŒåæš¡åŒ
pnpm build:watch
# è¿è¡æµè¯
pnpm test
# ç±»åæ£æ¥
pnpm lint
# æ ŒåŒå代ç
pnpm format
```
### 代ç è§è
- TypeScript strict mode
- 䞺å
Œ
± API æ·»å JSDoc 泚é
- æ°åèœå¿
é¡»å
å«å¯¹åºæµè¯
- éµåŸª OWASP å®å
šçŒç è§è
---
## ð License
MIT © [YYC³ AI Team](https://github.com/YanYuCloudCube/Family-PAI)
---
*YYC³ AI Family â å
«äœæäººåAIå®¶äººçæºèœäžæ¢*
**äºé« · äºæ · äºå · äºç»Ž**
---
*ææ¡£çæ¬: 2.3.0 | æåæŽæ°: 2026-04-24*
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues