MCPInstall

internationalization

國際化與本地化開發:i18n/l10n 架構設計、翻譯管理、多語言應用最佳實踐

Installs
59
Last 24h
—
Trending rank
—
Security
Not audited

Install

Works with every agent the skills CLI supports.

npx skills add https://github.com/miles990/claude-software-skills --skill internationalization
  1. 01

    Install

    Run the command in your project. The CLI asks which agents to install for.

  2. 02

    Describe the task

    Ask your agent for something this skill covers. It loads internationalization automatically when relevant.

  3. 03

    Review the result

    The agent follows the SKILL.md steps, scripts and references bundled with the skill.

SKILL.md

The instructions your agent reads when the skill is triggered.

國際化與本地化 Internationalization & Localization

讓你的應用程式走向全世界

核心概念

┌─────────────────────────────────────────────────────────────────┐
│  i18n vs l10n                                                    │
│                                                                 │
│  國際化 (Internationalization - i18n)                           │
│  ├─ 設計支援多語言的架構                                        │
│  ├─ 抽離可翻譯的字串                                            │
│  ├─ 處理日期、數字、貨幣格式                                    │
│  └─ 一次性工程工作                                              │
│                                                                 │
│  本地化 (Localization - l10n)                                   │
│  ├─ 針對特定語言/地區的翻譯                                     │
│  ├─ 文化適應(圖片、顏色、符號)                                │
│  ├─ 法規遵循(隱私、內容)                                      │
│  └─ 持續性工作                                                  │
│                                                                 │
│  i18n = 讓應用「能」支援多語言                                  │
│  l10n = 讓應用「實際」支援某語言                                │
└─────────────────────────────────────────────────────────────────┘

適用場景

  • 新專案的多語言架構設計
  • 現有專案添加多語言支援
  • 翻譯工作流程優化
  • RTL (右到左) 語言支援
  • 日期/數字/貨幣格式化

i18n 架構設計

翻譯檔案結構

推薦結構:按語言分類
locales/
├── en/
│   ├── common.json      # 共用詞彙
│   ├── home.json        # 首頁
│   └── settings.json    # 設定頁
├── zh-TW/
│   ├── common.json
│   ├── home.json
│   └── settings.json
└── ja/
    ├── common.json
    ├── home.json
    └── settings.json

替代結構:按功能分類
locales/
├── common/
│   ├── en.json
│   ├── zh-TW.json
│   └── ja.json
└── settings/
    ├── en.json
    ├── zh-TW.json
    └── ja.json

翻譯 Key 命名規範

## 命名原則

1. **階層式命名**
   ✅ `settings.notifications.email.title`
   ❌ `settingsNotificationsEmailTitle`

2. **語意優先於位置**
   ✅ `action.save`, `action.cancel`
   ❌ `button1`, `button2`

3. **避免縮寫**
   ✅ `error.network.timeout`
   ❌ `err.net.to`

4. **使用英文小寫**
   ✅ `user.profile.avatar`
   ❌ `User.Profile.Avatar`

## 常用前綴

| 前綴 | 用途 | 範例 |
|------|------|------|
| `action.` | 動作按鈕 | `action.submit`, `action.delete` |
| `label.` | 表單標籤 | `label.email`, `label.password` |
| `error.` | 錯誤訊息 | `error.required`, `error.invalid` |
| `message.` | 一般訊息 | `message.success`, `message.loading` |
| `title.` | 頁面標題 | `title.home`, `title.settings` |
| `hint.` | 提示文字 | `hint.password_format` |

主流框架實作

React (react-i18next)

// i18n.ts - 配置
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import LanguageDetector from 'i18next-browser-languagedetector';

i18n
  .use(LanguageDetector)
  .use(initReactI18next)
  .init({
    fallbackLng: 'en',
    supportedLngs: ['en', 'zh-TW', 'ja'],
    ns: ['common', 'home', 'settings'],
    defaultNS: 'common',
    interpolation: {
      escapeValue: false,
    },
    detection: {
      order: ['querystring', 'cookie', 'localStorage', 'navigator'],
      caches: ['localStorage', 'cookie'],
    },
  });

// 使用
import { useTranslation } from 'react-i18next';

function MyComponent() {
  const { t, i18n } = useTranslation();

  return (
    <div>
      <h1>{t('title.welcome')}</h1>
      <p>{t('message.greeting', { name: 'John' })}</p>
      <button onClick={() => i18n.changeLanguage('zh-TW')}>
        中文
      </button>
    </div>
  );
}

Vue (vue-i18n)

// i18n.ts
import { createI18n } from 'vue-i18n';

const i18n = createI18n({
  legacy: false,
  locale: 'en',
  fallbackLocale: 'en',
  messages: {
    en: { /* ... */ },
    'zh-TW': { /* ... */ },
  },
});

// 使用
<template>
  <h1>{{ $t('title.welcome') }}</h1>
  <p>{{ $t('message.greeting', { name: 'John' }) }}</p>
</template>

<script setup>
import { useI18n } from 'vue-i18n';
const { t, locale } = useI18n();
</script>

Next.js (next-intl)

// middleware.ts
import createMiddleware from 'next-intl/middleware';

export default createMiddleware({
  locales: ['en', 'zh-TW', 'ja'],
  defaultLocale: 'en',
  localePrefix: 'as-needed',
});

// app/[locale]/layout.tsx
import { NextIntlClientProvider } from 'next-intl';
import { getMessages } from 'next-intl/server';

export default async function LocaleLayout({
  children,
  params: { locale }
}) {
  const messages = await getMessages();

  return (
    <NextIntlClientProvider messages={messages}>
      {children}
    </NextIntlClientProvider>
  );
}

// 使用
import { useTranslations } from 'next-intl';

function Page() {
  const t = useTranslations('home');
  return <h1>{t('title')}</h1>;
}

複雜翻譯處理

複數形式 (Pluralization)

// en.json
{
  "items": {
    "zero": "No items",
    "one": "{{count}} item",
    "other": "{{count}} items"
  }
}

// zh-TW.json (中文無複數變化)
{
  "items": "{{count}} 個項目"
}

// 使用
t('items', { count: 5 }) // "5 items" / "5 個項目"

插值與格式化

{
  "greeting": "Hello, {{name}}!",
  "date": "Today is {{date, datetime}}",
  "price": "Price: {{amount, currency}}",
  "percent": "{{value, percent}} complete"
}
// 使用 Intl API
t('date', { date: new Date() });
t('price', { amount: 99.99 });
t('percent', { value: 0.85 });

巢狀與引用

{
  "common": {
    "app_name": "MyApp"
  },
  "welcome": "Welcome to $t(common.app_name)!",
  "footer": "© 2024 $t(common.app_name). All rights reserved."
}

日期時間處理

// 使用 Intl.DateTimeFormat
const formatDate = (date: Date, locale: string) => {
  return new Intl.DateTimeFormat(locale, {
    year: 'numeric',
    month: 'long',
    day: 'numeric',
  }).format(date);
};

formatDate(new Date(), 'en-US');    // "January 7, 2024"
formatDate(new Date(), 'zh-TW');    // "2024年1月7日"
formatDate(new Date(), 'ja-JP');    // "2024年1月7日"

// 相對時間
const formatRelative = (date: Date, locale: string) => {
  const rtf = new Intl.RelativeTimeFormat(locale, { numeric: 'auto' });
  const diff = Math.round((date.getTime() - Date.now()) / 86400000);
  return rtf.format(diff, 'day');
};

formatRelative(yesterday, 'en');    // "yesterday"
formatRelative(yesterday, 'zh-TW'); // "昨天"

數字與貨幣

// 數字格式化
const formatNumber = (num: number, locale: string) => {
  return new Intl.NumberFormat(locale).format(num);
};

formatNumber(1234567.89, 'en-US');  // "1,234,567.89"
formatNumber(1234567.89, 'de-DE');  // "1.234.567,89"
formatNumber(1234567.89, 'zh-TW');  // "1,234,567.89"

// 貨幣格式化
const formatCurrency = (amount: number, currency: string, locale: string) => {
  return new Intl.NumberFormat(locale, {
    style: 'currency',
    currency,
  }).format(amount);
};

formatCurrency(99.99, 'USD', 'en-US');  // "$99.99"
formatCurrency(99.99, 'TWD', 'zh-TW');  // "NT$99.99"
formatCurrency(99.99, 'JPY', 'ja-JP');  // "¥100"

RTL 語言支援

┌─────────────────────────────────────────────────────────────────┐
│  RTL (Right-to-Left) 支援                                        │
│                                                                 │
│  RTL 語言:阿拉伯語、希伯來語、波斯語、烏爾都語                │
│                                                                 │
│  HTML 設定                                                      │
│  <html lang="ar" dir="rtl">                                     │
│                                                                 │
│  CSS 邏輯屬性                                                   │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │  LTR 屬性        →  邏輯屬性                            │   │
│  │  margin-left     →  margin-inline-start                 │   │
│  │  margin-right    →  margin-inline-end                   │   │
│  │  padding-left    →  padding-inline-start                │   │
│  │  text-align:left →  text-align: start                   │   │
│  │  float: left     →  float: inline-start                 │   │
│  └─────────────────────────────────────────────────────────┘   │
│                                                                 │
│  自動翻轉                                                       │
│  • 圖標方向(箭頭、導航)                                       │
│  • 表單欄位順序                                                 │
│  • 滾動方向                                                     │
└─────────────────────────────────────────────────────────────────┘

RTL CSS 範例

/* 使用 CSS 邏輯屬性 */
.card {
  margin-inline-start: 1rem;
  padding-inline-end: 2rem;
  border-inline-start: 3px solid blue;
}

/* 針對 RTL 調整 */
[dir="rtl"] .icon-arrow {
  transform: scaleX(-1);
}

/* 使用 :dir() 偽類 */
.nav:dir(rtl) {
  flex-direction: row-reverse;
}

翻譯工作流程

┌─────────────────────────────────────────────────────────────────┐
│  翻譯工作流程                                                    │
│                                                                 │
│  開發者                         翻譯人員                        │
│     │                              │                            │
│     │  1. 新增 key + 預設文字     │                            │
│     ├─────────────────────────────→│                            │
│     │                              │                            │
│     │  2. 同步到翻譯平台          │                            │
│     ├─────────────────────────────→│                            │
│     │                              │                            │
│     │  3. 翻譯 + 審核             │                            │
│     │←─────────────────────────────┤                            │
│     │                              │                            │
│     │  4. 拉取翻譯檔案            │                            │
│     ├─────────────────────────────→│                            │
│     │                              │                            │
│     │  5. 測試 + 發布             │                            │
│     ▼                              │                            │
│                                                                 │
│  工具推薦:                                                     │
│  • Lokalise, Crowdin, Phrase                                   │
│  • Weblate (開源)                                              │
│  • POEditor                                                     │
└─────────────────────────────────────────────────────────────────┘

翻譯品質保證

## 翻譯 Checklist

### 技術檢查
- [ ] 所有 key 都有翻譯
- [ ] 插值變數正確
- [ ] 複數形式完整
- [ ] 特殊字元正確轉義
- [ ] HTML 標籤完整

### 內容檢查
- [ ] 翻譯準確
- [ ] 語氣一致
- [ ] 專有名詞統一
- [ ] 長度適中(UI 不溢出)
- [ ] 文化適宜

### 自動化測試
```typescript
// 檢查遺漏翻譯
function checkMissingTranslations(
  defaultLocale: object,
  targetLocale: object,
  path: string = ''
) {
  const missing: string[] = [];

  for (const key in defaultLocale) {
    const currentPath = path ? `${path}.${key}` : key;

    if (!(key in targetLocale)) {
      missing.push(currentPath);
    } else if (typeof defaultLocale[key] === 'object') {
      missing.push(...checkMissingTranslations(
        defaultLocale[key],
        targetLocale[key],
        currentPath
      ));
    }
  }

  return missing;
}

常見問題與解決

問題解決方案
翻譯後文字太長預留空間、使用縮寫、調整 UI
專有名詞不一致建立術語表 (Glossary)
翻譯遺漏CI 自動檢查
上下文不清為翻譯者提供截圖和說明
硬編碼字串ESLint 規則檢查
動態內容翻譯使用插值,避免字串拼接

效能優化

## 翻譯載入策略

### 1. 按需載入
只載入當前語言,切換時再載入
```typescript
const loadLocale = async (locale: string) => {
  const messages = await import(`./locales/${locale}.json`);
  i18n.addResourceBundle(locale, 'translation', messages);
};

2. 命名空間分割

按頁面/功能分割翻譯檔案

// 只載入首頁需要的翻譯
await i18n.loadNamespaces(['common', 'home']);

3. 預載入常用語言

// 預載入可能使用的語言
const preloadLocales = ['en', 'zh-TW'];
preloadLocales.forEach(locale => {
  i18n.loadLanguages(locale);
});

4. 快取策略

使用 Service Worker 快取翻譯檔案


## 工具推薦

### 翻譯管理平台
- **Lokalise** - 開發者友好,支援多種格式
- **Crowdin** - 社群翻譯,開源專案免費
- **Phrase** - 企業級,強大的工作流程

### 開發工具
- **i18n Ally** - VS Code 擴展,即時預覽
- **eslint-plugin-i18n** - 檢查硬編碼字串
- **FormatJS** - 強大的格式化工具集

### 測試工具
- **pseudolocalization** - 偽本地化測試
- **i18next-parser** - 自動提取 key

## 最佳實踐總結

```markdown
## DO ✅

1. 從專案開始就考慮 i18n
2. 使用語意化的 key 命名
3. 避免字串拼接,使用插值
4. 為翻譯者提供上下文
5. 自動化翻譯檢查
6. 測試所有支援的語言

## DON'T ❌

1. 硬編碼任何用戶可見文字
2. 假設所有語言長度相同
3. 在 key 中使用預設文字
4. 忽略複數和性別變化
5. 手動管理翻譯同步
6. 忽略 RTL 語言需求

FAQ

What does the internationalization skill do?

國際化與本地化開發:i18n/l10n 架構設計、翻譯管理、多語言應用最佳實踐

How do I install internationalization?

Run npx skills add https://github.com/miles990/claude-software-skills --skill internationalization in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/internationalization/ (personal) or .claude/skills/internationalization/ (project).

Which AI agents can use internationalization?

Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.

Is internationalization safe to install?

No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.

Who maintains internationalization?

It is published by miles990 in miles990/claude-software-skills. It has 59 recorded installs.

More from miles990/claude-software-skills

View all →

code-quality

miles990/claude-software-skills

Clean code principles, SOLID, and code review practices

devops-cicd

miles990/claude-software-skills

CI/CD pipelines, infrastructure as code, and deployment strategies

DevOps & Cloud606 installs

game-development

miles990/claude-software-skills

Game development patterns, architectures, and best practices

Media & Creative411 installs

project-management

miles990/claude-software-skills

Open the skill to read its SKILL.md instructions.

389 installs

e-commerce

miles990/claude-software-skills

E-commerce platforms, payment processing, and shopping cart patterns

Backend & APIs376 installs

saas-platforms

miles990/claude-software-skills

Open the skill to read its SKILL.md instructions.

362 installs

Popular other skills

View category →

hyperframes-cli

heygen-com/hyperframes

The HyperFrames CLI by job - scaffold, check, look at frames, edit the timeline, preview, render locally or in the cloud, publish, project history - plus reading its JSON and recovering from build or render failures.

1.3M installs

triage

mattpocock/skills

Move issues and external PRs through a state machine of triage roles, categorise, verify, grill if needed, and write agent-ready briefs.

1M installs

ask-matt

mattpocock/skills

Ask which skill or flow fits your situation. A router over the skills in this repo.

778.4K installs

to-questionnaire

mattpocock/skills

Turn a decision you can't fully answer into a questionnaire for someone else to fill in.

508.9K installs

wait-what

mattpocock/skills

Stop. That last message did not land: re-pitch it.

459.7K installs

loop-me

mattpocock/skills

Grill me about specs for the workflows I want to build, within this workspace.

447.9K installs