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.env
Set preset language in the file:
# .env.dev / .env.prod / .env.test
VITE_DEFAULT_LANG=zhTW
Currently supported language code:
zhTW
: Traditional ChinesezhCN
: Simplified ChineseenUS
: 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 configurationsrc/utils/i18n.ts
: Tool functions and Naive UI language configurationsrc/store/model/language/index.ts
: Language state managementsrc/utils/tools/defaultLang.ts
: Preset language acquisition logic
Language Pack Structure
Language packages adopt nested JSON structures and are organized by functional modules:
{
"common": {
"confirm": "確認",
"cancel": "取消",
"save": "保存"
},
"userCenter": {
"updateEmail": "更新信箱",
"updateMobile": "更新手機號碼"
},
"language": {
"zhCN": "簡體中文",
"zhTW": "正體中文",
"enUS": "美式英文",
"confirmToSwitchLanguage": "確定要切換語言嗎?"
}
}
Use in Vue files
1. Use in template
<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
<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
<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
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 providedLangsSwitch
Components can be used directly:
<template>
<LangsSwitch />
</template>
2. Programming switch
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
- Users choose new language
- Show the confirmation dialog box
- Update language settings after confirmation
- Update local storage
- Reload the page to apply the new language
Setting a preset language
1. Environment variable settings
exist.env
Settings in the file:
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:
// 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
- Locally stored
languageCurrent
- Browser language (if in the support list)
- Environment variables
VITE_DEFAULT_LANG
Create a new language
1. Add language type definition
existsrc/modules/i18n.ts
Add new language type:
export type Language = 'enUS' | 'zhTW' | 'zhCN' | 'jaJP' // 添加日語
export const language = {
enUS,
zhTW,
zhCN,
jaJP, // 添加日語導入
}
2. Create a language package file
createlocales/jaJP.json
document:
{
"common": {
"confirm": "確認",
"cancel": "キャンセル",
"save": "保存"
},
"language": {
"jaJP": "日本語",
"confirmToSwitchLanguage": "言語を切り替えますか?"
}
}
3. Update i18n configuration
existsrc/modules/i18n.ts
Import new language packs:
import jaJP from '../../locales/jaJP.json'
export const language = {
enUS,
zhTW,
zhCN,
jaJP, // 添加新語言
}
4. Update Naive UI language configuration
existsrc/utils/i18n.ts
Add Naive UI language configuration to:
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.ts
Update the type definition:
interface ImportMetaEnv {
readonly VITE_DEFAULT_LANG: 'zhCN' | 'zhTW' | 'enUS' | 'jaJP'
}
6. Add language display name
Packed in all languageslanguage
Partially add new languages:
// zhCN.json, zhTW.json, enUS.json
{
"language": {
"jaJP": "日語"
// 或 "jaJP": "日語", "jaJP": "Japanese"
}
}
7. Test new languages
- Update environment variables
VITE_DEFAULT_LANG=jaJP
- Restart the development server
- Check language switching function
- 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
- use
missingWarn: true
Configure 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:
- renew
Language
Type definition - Ensure the correct environment variable type
- Be careful when using type assertions
// 正確的類型使用
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
// 正確的方式
$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
// 動態鍵值範例
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 configuration
dateLocale
- Consider using
Intl
Format 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
<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
- Open
missingWarn
andfallbackWarn
- Check language header settings in network requests
// 在開發環境中啟用詳細警告
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.