Skip to content

Internationalization (i18n)

This document details how to use and configure international features in a project, including language pack management, how to use it in Vue and TypeScript files, language switching, and how to add new languages.

Configuration instructions

1. Environment variable configuration

exist.envSet preset language in the file:

bash
# .env.dev / .env.prod / .env.test
VITE_DEFAULT_LANG=zhTW

Currently supported language code:

  • zhTW: Traditional Chinese
  • zhCN: Simplified Chinese
  • enUS: American English

2. Language Pack Archive Location

Language Pack Archives are located inlocales/In the directory:

locales/
├── zhTW.json    # 正體中文
├── zhCN.json    # 簡體中文
└── enUS.json    # 美式英文

3. Core setting file

  • src/modules/i18n.ts: i18n instance configuration
  • src/utils/i18n.ts: Tool functions and Naive UI language configuration
  • src/store/model/language/index.ts: Language state management
  • src/utils/tools/defaultLang.ts: Preset language acquisition logic

Language Pack Structure

Language packages adopt nested JSON structures and are organized by functional modules:

json
{
  "common": {
    "confirm": "確認",
    "cancel": "取消",
    "save": "保存"
  },
  "userCenter": {
    "updateEmail": "更新信箱",
    "updateMobile": "更新手機號碼"
  },
  "language": {
    "zhCN": "簡體中文",
    "zhTW": "正體中文",
    "enUS": "美式英文",
    "confirmToSwitchLanguage": "確定要切換語言嗎?"
  }
}

Use in Vue files

1. Use in template

vue
<script setup lang="ts">
// 無需額外導入,$t 已全局註冊
</script>

<template>
  <div>
    <!-- 直接使用 $t 函數 -->
    <h1>{{ $t('common.title') }}</h1>

    <!-- 在屬性中使用 -->
    <n-button :placeholder="$t('common.inputPlaceholder')">
      {{ $t('common.submit') }}
    </n-button>
  </div>
</template>

2. Use in script

vue
<script setup lang="ts">
function handleSubmit() {
  // 顯示成功消息
  window.$message.success($t('common.saveSuccess'))

  // 顯示確認對話框
  window.$dialog.warning({
    title: $t('common.warn'),
    content: $t('common.deleteConfirm')
  })
}
</script>

3. Dynamic language switching example

vue
<script setup lang="ts">
import { useLanguageStore } from '@/store/model/language'

const languageStore = useLanguageStore()
</script>

<template>
  <n-popselect
    :value="languageStore.current"
    :options="languageStore.list"
    @update:value="languageStore.setAppLang"
  >
    <CommonWrapper>
      <icon-park-outline-translate />
    </CommonWrapper>
  </n-popselect>
</template>

Use in TypeScript files

typescript
import { $t } from '@/utils'

// 在函數中使用
export function validateEmail(email: string) {
  if (!email) {
    return $t('userCenter.inputEmail')
  }
  return true
}

Language Switching

1. Use language switching components

Project providedLangsSwitchComponents can be used directly:

vue
<template>
  <LangsSwitch />
</template>

2. Programming switch

typescript
import { useLanguageStore } from '@/store/model/language'
// 直接設置語言(不顯示確認對話框)
import { setLocale } from '@/utils'

const languageStore = useLanguageStore()

// 切換語言(會顯示確認對話框)
languageStore.setAppLang('enUS')
setLocale('enUS')
local.set('languageCurrent', 'enUS')

3. Language switching process

  1. Users choose new language
  2. Show the confirmation dialog box
  3. Update language settings after confirmation
  4. Update local storage
  5. Reload the page to apply the new language

Setting a preset language

1. Environment variable settings

exist.envSettings in the file:

bash
VITE_DEFAULT_LANG=zhCN

2. Browser language detection

The system will automatically detect the browser language. If the browser language is in the list of supported languages, use the browser language:

typescript
// src/utils/tools/defaultLang.ts
export function defaultLang(): Language {
  const { VITE_DEFAULT_LANG } = import.meta.env
  const browserLang = navigator.language.replace(/-/g, '')

  if (Object.keys(language).includes(browserLang)) {
    return browserLang as Language
  }

  return VITE_DEFAULT_LANG
}

3. Language priority

  1. Locally storedlanguageCurrent
  2. Browser language (if in the support list)
  3. Environment variablesVITE_DEFAULT_LANG

Create a new language

1. Add language type definition

existsrc/modules/i18n.tsAdd new language type:

typescript
export type Language = 'enUS' | 'zhTW' | 'zhCN' | 'jaJP' // 添加日語

export const language = {
  enUS,
  zhTW,
  zhCN,
  jaJP, // 添加日語導入
}

2. Create a language package file

createlocales/jaJP.jsondocument:

json
{
  "common": {
    "confirm": "確認",
    "cancel": "キャンセル",
    "save": "保存"
  },
  "language": {
    "jaJP": "日本語",
    "confirmToSwitchLanguage": "言語を切り替えますか?"
  }
}

3. Update i18n configuration

existsrc/modules/i18n.tsImport new language packs:

typescript
import jaJP from '../../locales/jaJP.json'

export const language = {
  enUS,
  zhTW,
  zhCN,
  jaJP, // 添加新語言
}

4. Update Naive UI language configuration

existsrc/utils/i18n.tsAdd Naive UI language configuration to:

typescript
import { dateJaJP, jaJP as naiveJaJP } from 'naive-ui'

export const naiveI18nOptions: Record<string, { locale: NLocale | null, dateLocale: NDateLocale | null }> = {
  // ... 現有配置
  jaJP: {
    locale: naiveJaJP,
    dateLocale: dateJaJP,
  },
}

5. Update environment variable types

existsrc/typings/env.d.tsUpdate the type definition:

typescript
interface ImportMetaEnv {
  readonly VITE_DEFAULT_LANG: 'zhCN' | 'zhTW' | 'enUS' | 'jaJP'
}

6. Add language display name

Packed in all languageslanguagePartially add new languages:

json
// zhCN.json, zhTW.json, enUS.json
{
  "language": {
    "jaJP": "日語"
    // 或 "jaJP": "日語", "jaJP": "Japanese"
  }
}

7. Test new languages

  1. Update environment variablesVITE_DEFAULT_LANG=jaJP
  2. Restart the development server
  3. Check language switching function
  4. Verify that all text is displayed correctly

Frequently Asked Questions and Avoiding Trapped

1. Language package key value missing

Problem: "Missing key" warning appears on the console

Solution:

  • Make sure all language packs have the same key structure
  • usemissingWarn: trueConfigure to find missing keys
  • Check language pack consistency regularly

2. The page will not be updated after language switching

Problem: Some text has not been updated after switching languages

Solution:

  • Make sure to use$t()Functions instead of writing dead text
  • Check if the computed attributes respond correctly to language changes
  • The page will be reloaded after the language switch to ensure that the status is reset correctly

3. Type safety issues

Problem: TypeScript type check failed

Solution:

  • renewLanguageType definition
  • Ensure the correct environment variable type
  • Be careful when using type assertions
typescript
// 正確的類型使用
const currentLang = local.get('languageCurrent') as Language || defaultLang()

4. The language package file is too large

Problem: Too large language package files affect loading performance

Solution:

  • Split language packages by function module
  • Loading language packs using dynamic import
  • Consider using CDN to load language packs

5. Nested object access

Problem: Accessing deep nested translation keys

Solution:

  • Key paths separated by dot numbers
  • Avoid overly deep nested structures
  • Consider flat language pack structure
typescript
// 正確的方式
$t('userCenter.personalInfo.nickname')

// 避免過深嵌套
$t('userCenter.personalInfo.details.contact.mobile.placeholder')

6. Dynamic key values

Problem: Translation keys need to be generated dynamically based on variables

Solution:

  • Use template strings
  • Make sure the key value exists
  • Provide preset values
typescript
// 動態鍵值範例
function getFieldLabel(fieldName: string) {
  const key = `userCenter.${fieldName}Label`
  return $t(key) !== key ? $t(key) : fieldName
}

7. Number and date formatting

Question: Number and date formats in different languages

Solution:

  • Local configuration using Naive UI
  • The correct configurationdateLocale
  • Consider usingIntlFormat the API

8. Language pack maintenance

Best Practice:

  • Check language pack consistency regularly
  • Verify key-value integrity with tools
  • Establish a language pack update process
  • Keep the language pack structure simple and clear

9. Optimization of performance

suggestion:

  • Avoid frequent calls in templates$t()
  • Use computed attributes to cache translation results
  • Consider preloading common language packages
vue
<script setup lang="ts">
// 好的做法:使用計算屬性
const pageTitle = computed(() => $t('common.title'))

// 避免:在模板中直接調用
// {{ $t('common.title') }}
</script>

10. Error-destruction skills

debugger:

  • Check language pack load using browser developer tools
  • OpenmissingWarnandfallbackWarn
  • Check language header settings in network requests
typescript
// 在開發環境中啟用詳細警告
export const i18n = createI18n({
  missingWarn: true,
  fallbackWarn: true,
  // ... 其他配置
})

By following these guidelines and best practices, you can effectively use and manage international features in your projects, avoid common problems, and provide a good multilingual user experience.