npm package: @mico_fe/i18n-vue
Description: Vue 3 i18n runtime - auto internationalization
Author: manwang
Latest version: 1.0.0

# @mico_fe/i18n-vue

> Vue 3 国际化运行时 - 自动国际化解决方案

## 📦 安装

```bash
npm install @mico_fe/i18n-vue
# 或
pnpm add @mico_fe/i18n-vue
# 或
yarn add @mico_fe/i18n-vue
```

**配合编译时插件使用（推荐）：**

```bash
# Vite 项目
npm install @mico_fe/vite-plugin-i18n-vue -D

# Webpack 项目
npm install babel-plugin-auto-i18n -D
```

## 🚀 快速开始

### 1. 创建语言包

```
src/locales/
├── zh-CN.json
├── en-US.json
└── index.ts
```

**zh-CN.json**
```json
{
  "button.submit": "提交",
  "button.cancel": "取消",
  "message.welcome": "欢迎使用",
  "message.greeting": "你好，{name}！",
  "message.items": "共 {count} 条数据"
}
```

**en-US.json**
```json
{
  "button.submit": "Submit",
  "button.cancel": "Cancel",
  "message.welcome": "Welcome",
  "message.greeting": "Hello, {name}!",
  "message.items": "Total {count} items"
}
```

**index.ts**
```ts
import { ref } from 'vue'
import zhCN from './zh-CN.json'
import enUS from './en-US.json'

// 语言包数据
export const messages = {
  'zh-CN': zhCN,
  'en-US': enUS,
} as Record<string, Record<string, string>>

// 可用语言列表
export const availableLangs = Object.keys(messages)

// 默认语言
export const defaultLang = 'zh-CN'

// 当前语言（响应式）
export const currentLang = ref(getInitialLang())

// 获取初始语言
function getInitialLang(): string {
  if (typeof window === 'undefined') return defaultLang
  
  // 优先使用存储的语言
  const stored = localStorage.getItem('lang')
  if (stored && availableLangs.includes(stored)) {
    return stored
  }
  
  // 尝试匹配浏览器语言
  const browserLang = navigator.language
  if (availableLangs.includes(browserLang)) {
    return browserLang
  }
  
  return defaultLang
}

// 设置语言
export function setLang(lang: string): void {
  if (!availableLangs.includes(lang)) {
    console.warn(`[i18n] Unsupported language: ${lang}`)
    return
  }
  currentLang.value = lang
  localStorage.setItem('lang', lang)
  document.documentElement.lang = lang
}

// 获取当前语言
export function getLang(): string {
  return currentLang.value
}

// 可选：自定义参数替换
// export function replaceParams(text: string, params: Record<string, any>): string {
//   return text.replace(/\{\{(\w+)\}\}/g, (_, key) => params[key] ?? _)
// }

// 可选：自定义语言映射
// export const langMap = {
//   'ja-JP': { name: '日本語', flag: '🇯🇵' }
// }
```

### 2. 初始化

```ts
// main.ts
import { createApp } from 'vue'
import { setupLangs } from '@mico_fe/i18n-vue'
import * as localeModule from './locales'
import App from './App.vue'

const app = createApp(App)

// 安装 i18n
setupLangs(app, {
  localeModule,
  fallbackLang: 'zh-CN',  // 回退语言
  warnOnMissing: true,    // 缺少翻译时警告
}).then(() => {
  app.mount('#app')
})
```

### 3. 在模板中使用

```vue
<template>
  <!-- 基本用法 -->
  <button>{{ $t('button.submit') }}</button>
  
  <!-- 带参数 -->
  <p>{{ $t('message.greeting', { name: userName }) }}</p>
  
  <!-- 直接写中文（配合编译时插件自动转换） -->
  <p>欢迎使用</p>
  
  <!-- 按文案翻译 -->
  <p>{{ $tt('欢迎使用') }}</p>
</template>

<script setup>
import { ref } from 'vue'

const userName = ref('Vue')
</script>
```

### 4. 在脚本中使用

```vue
<script setup>
import { t, tt, te, tte, useLang } from '@mico_fe/i18n-vue'

// 方式 1：直接使用函数
const submitText = t('button.submit')
const welcomeText = tt('欢迎使用')
const hasKey = te('button.submit')  // true
const hasText = tte('欢迎使用')      // true

// 方式 2：使用 Composition API
const { lang, langs, setLang, langName, langFlag } = useLang()

// 切换语言
function switchToEnglish() {
  setLang('en-US')
}
</script>
```

## 📖 API

### setupLangs(app, config)

初始化 i18n：

| 参数 | 类型 | 说明 |
|------|------|------|
| `app` | `App` | Vue 应用实例 |
| `config.localeModule` | `VueLocaleModule` | 语言模块（必需） |
| `config.fallbackLang` | `string` | 回退语言 |
| `config.warnOnMissing` | `boolean` | 缺少翻译时是否警告 |

### t(key, params?)

按 key 翻译：

```ts
t('button.submit')  // "提交"
t('message.greeting', { name: 'Vue' })  // "你好，Vue！"
t('message.items', { count: 100 })  // "共 100 条数据"
```

### tt(text, params?)

按文案翻译（运行时根据中文查找 key）：

```ts
tt('提交')  // 中文环境: "提交" / 英文环境: "Submit"
tt('你好，{name}！', { name: 'Vue' })  // "Hello, Vue!"
```

### te(key, lang?)

检查 key 是否存在：

```ts
te('button.submit')  // true
te('not.exist')      // false
te('button.submit', 'en-US')  // 检查指定语言
```

### tte(text)

检查文案是否有翻译：

```ts
tte('提交')      // true
tte('不存在的文案')  // false
```

### useLang()

Composition API：

```ts
const {
  lang,       // Ref<string> - 当前语言代码
  langs,      // Ref<string[]> - 可用语言列表
  setLang,    // (lang: string) => void - 设置语言
  langName,   // Ref<string> - 当前语言名称（如 "简体中文"）
  langFlag,   // Ref<string> - 当前语言旗帜（如 "🇨🇳"）
} = useLang()
```

### setLang(lang) / getLang() / getLangs()

全局语言管理：

```ts
import { setLang, getLang, getLangs } from '@mico_fe/i18n-vue'

setLang('en-US')           // 切换到英文
const current = getLang()  // "en-US"
const all = getLangs()     // ["zh-CN", "en-US"]
```

## 🎨 内置组件

### LocaleSwitcher

下拉选择式语言切换器：

```vue
<template>
  <LocaleSwitcher @change="onLangChange" />
</template>

<script setup>
import { LocaleSwitcher } from '@mico_fe/i18n-vue'

function onLangChange(lang: string) {
  console.log('Language changed to:', lang)
}
</script>
```

### FloatingLocaleSwitcher

浮动可拖动语言切换器：

```vue
<template>
  <FloatingLocaleSwitcher 
    :initial-x="20"
    :initial-y="100"
    storage-key="my-locale-pos"
    @change="onLangChange"
  />
</template>

<script setup>
import { FloatingLocaleSwitcher } from '@mico_fe/i18n-vue'
</script>
```

**Props：**

| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `initialX` | `number` | `20` | 初始 X 位置 |
| `initialY` | `number` | `100` | 初始 Y 位置 |
| `storageKey` | `string` | `'floating-locale-position'` | localStorage 存储 key |

**特性：**
- 🖱️ 可拖动定位
- 💾 位置自动保存到 localStorage
- 📱 支持触摸设备
- 🎯 边界检测，不会拖出屏幕

## 📝 TypeScript

### VueLocaleModule 接口

```ts
interface VueLocaleModule {
  // 必需
  messages: Record<string, Record<string, string>>
  availableLangs: string[]
  currentLang: Ref<string>
  setLang: (lang: string) => void
  getLang: () => string
  
  // 可选
  defaultLang?: string
  langMap?: Record<string, LangInfo>
  replaceParams?: (text: string, params: Record<string, any>) => string
}
```

### 全局类型声明

安装后自动扩展 Vue 类型：

```ts
// 模板中可用
this.$t('key')
this.$tt('文案')
this.$lang      // Ref<string>
this.$setLang   // (lang: string) => void
```

## 📄 License

MIT