Complete Guide to MineAdmin Internationalization Configuration โ
MineAdmin's frontend is built on Vue i18n v11, providing a comprehensive internationalization solution that supports multi-language switching, dynamic language pack loading, and modular translation management. This document details the system's internationalization implementation mechanisms and usage methods.
Overview โ
Supported Languages โ
- Simplified Chinese (zh_CN) - Default language
- Traditional Chinese (zh_TW)
- English (en)
Core Features โ
- ๐ Dynamic multi-language switching
- ๐ฆ Modular language pack management
- โก Dynamic language pack loading
- ๐ง Development tool integration
- ๐ฑ Global and local scope support
- ๐ฏ TypeScript type safety
Technology Stack โ
- Vue i18n: 11.1.2
- Build Plugin: @intlify/unplugin-vue-i18n 6.0.3
- Language Format: YAML (supports JSON)
- Type System: TypeScript
Project Configuration โ
System Initialization โ
The system initializes internationalization configuration in /web/src/bootstrap.ts
:
// Source location: web/src/bootstrap.ts:44-67
// GitHub: https://github.com/mineadmin/mineadmin/blob/master/web/src/bootstrap.ts
async function createI18nService(app: App) {
// Automatically scan language pack files
const locales: any[] = Object.entries(import.meta.glob('./locales/*.y(a)?ml')).map(([key]: any) => {
const [, value, label] = key.match(/^.\/locales\/(\w+)\[([^[\]]+)\]\.yaml$/)
return { label, value }
})
useUserStore().setLocales(locales)
// Process message format
Object.keys(messages as any).map((name: string) => {
const matchValue = name.match(/(\w+)/) as RegExpMatchArray | null
if (messages && matchValue) {
messages[matchValue[1]] = messages[name]
delete messages[name]
}
})
// Create i18n instance
app.use(createI18n({
legacy: false, // Use Composition API
globalInjection: true, // Global injection
fallbackLocale: 'zh_CN', // Fallback language
locale: useUserStore().getLanguage(), // Current language
silentTranslationWarn: true, // Silent translation warnings
silentFallbackWarn: true, // Silent fallback warnings
messages, // Language pack data
}))
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
System Architecture โ
Architecture Diagram โ
graph TB
A[Vue App] --> B[Bootstrap]
B --> C[I18n Service]
C --> D[createI18n]
D --> E[Global Messages]
D --> F[Local Messages]
E --> G[Core Locales]
E --> H[Module Locales]
E --> I[Plugin Locales]
F --> J[Component i18n blocks]
K[useTrans Hook] --> L[Global Translation]
K --> M[Local Translation]
N[useLocalTrans Hook] --> M
G --> O[/src/locales/*.yaml]
H --> P[/src/modules/*/locales/*.yaml]
I --> Q[/src/plugins/*/locales/*.yaml]
style A fill:#e1f5fe
style C fill:#f3e5f5
style K fill:#fff3e0
style N fill:#fff3e0
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
File Structure โ
web/src/
โโโ locales/ # Core language packs
โ โโโ zh_CN[็ฎไฝไธญๆ].yaml
โ โโโ en[English].yaml
โ โโโ zh_TW[็น้ซไธญๆ].yaml
โโโ modules/ # Module language packs
โ โโโ base/
โ โโโ locales/
โ โโโ zh_CN[็ฎไฝไธญๆ].yaml
โ โโโ en[English].yaml
โ โโโ zh_TW[็น้ซไธญๆ].yaml
โโโ plugins/ # Plugin language packs
โ โโโ mine-admin/
โ โโโ code-generator/
โ โโโ web/
โ โโโ locales/
โ โโโ zh_CN[็ฎไฝไธญๆ].yaml
โ โโโ en[English].yaml
โ โโโ zh_TW[็น้ซไธญๆ].yaml
โโโ hooks/ # Internationalization Hooks
โโโ auto-imports/
โ โโโ useTrans.ts # Auto-imported translation Hook
โโโ useLocalTrans.ts # Local translation Hook
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Language Pack Management โ
File Naming Convention โ
Language pack files must follow the specific format: language identifier[language name].yaml
# Correct naming format
zh_CN[็ฎไฝไธญๆ].yaml
en[English].yaml
zh_TW[็น้ซไธญๆ].yaml
# Incorrect naming format
zh_CN.yaml # Missing language name
en[่ฑๆ].yaml # Incorrect language name
zh-CN[็ฎไฝไธญๆ].yaml # Incorrect language identifier format
2
3
4
5
6
7
8
9
Global Language Packs โ
The system automatically scans language packs from three locations:
- Core language packs:
src/locales/
- Module language packs:
src/modules/<module name>/locales/
- Plugin language packs:
src/plugins/<plugin name>/locales/
Important Note
Module and plugin language pack filenames must exactly match those in src/locales
, otherwise console warnings about missing translation keys will appear.
Language Pack Content Example โ
Core language pack example (src/locales/zh_CN[็ฎไฝไธญๆ].yaml
):
# Login form
loginForm:
loginButton: ็ปๅฝ
passwordPlaceholder: ่ฏท่พๅ
ฅๅฏ็
codeLabel: ้ช่ฏ็
usernameLabel: ่ดฆๆท
# CRUD operations
crud:
cancel: ๅๆถ
save: ไฟๅญ
ok: ็กฎๅฎ
add: ๆฐๅข
edit: ็ผ่พ
delete: ๅ ้ค
createSuccess: ๅๅปบๆๅ
updateSuccess: ไฟฎๆนๆๅ
delMessage: ๆฏๅฆๅ ้คๆ้ไธญๆฐๆฎ๏ผ
# Form validation
form:
pleaseInput: ่ฏท่พๅ
ฅ{msg}
pleaseSelect: ่ฏท้ๆฉ{msg}
requiredInput: '{msg}ๅฟ
ๅกซ'
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Local Language Packs โ
Define local language packs in Vue components:
<template>
<div>
<h1>{{ t('welcome') }}</h1>
<p>{{ t('description') }}</p>
</div>
</template>
<script setup lang="ts">
const { t } = useLocalTrans()
</script>
<i18n lang="yaml">
zh_CN:
welcome: ๆฌข่ฟไฝฟ็จ
description: ่ฟๆฏไธไธช็คบไพ้กต้ข
zh_TW:
welcome: ๆญก่ฟไฝฟ็จ
description: ้ๆฏไธๅ็คบไพ้ ้ข
en:
welcome: Welcome
description: This is a sample page
</i18n>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Hook System Details โ
useTrans Hook โ
Source location: web/src/hooks/auto-imports/useTrans.ts
GitHub: https://github.com/mineadmin/mineadmin/blob/master/web/src/hooks/auto-imports/useTrans.ts
import { useI18n } from 'vue-i18n'
import type { ComposerTranslation } from 'vue-i18n'
export interface TransType {
globalTrans: ComposerTranslation
localTrans: ComposerTranslation
}
export function useTrans(key: any | null = null): TransType | string | any {
const global = useI18n()
const local = useI18n({
inheritLocale: true,
useScope: 'local',
})
if (key === null) {
return {
localTrans: local.t,
globalTrans: global.t,
}
}
else {
// First look for global translation, then fall back to local
return global.te(key) ? global.t(key) : local.te(key) ? local.t(key) : key
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
useLocalTrans Hook โ
Source location: web/src/hooks/useLocalTrans.ts
GitHub: https://github.com/mineadmin/mineadmin/blob/master/web/src/hooks/useLocalTrans.ts
import { useI18n } from 'vue-i18n'
import type { ComposerTranslation } from 'vue-i18n'
export function useLocalTrans(key: any | null = null): string | ComposerTranslation | any {
const { t } = useI18n({
inheritLocale: true,
useScope: 'local',
})
return key === null ? t as ComposerTranslation : t(key) as string
}
2
3
4
5
6
7
8
9
10
Usage Methods โ
Basic Usage โ
1. Global and Local Translation Objects โ
<script setup lang="ts">
import type { TransType } from '@/hooks/auto-imports/useTrans.ts'
// Get translation objects
const i18n = useTrans() as TransType
const t = i18n.globalTrans // Global translation function
const localT = i18n.localTrans // Local translation function
// Usage examples
const title = t('crud.createSuccess') // "ๅๅปบๆๅ"
const localTitle = localT('welcome') // Translation defined in component
</script>
2
3
4
5
6
7
8
9
10
11
12
2. Direct Translation Calls โ
// Smart translation: prioritizes global, falls back to local
const message = useTrans('crud.updateSuccess') // "ไฟฎๆนๆๅ"
// Local-only translation
const localMessage = useLocalTrans('description')
2
3
4
5
Real-World Project Example โ
Source location: web/src/modules/base/views/permission/user/index.vue
GitHub: https://github.com/mineadmin/mineadmin/blob/master/web/src/modules/base/views/permission/user/index.vue
<script setup lang="tsx">
import type { TransType } from '@/hooks/auto-imports/useTrans.ts'
// Get internationalization object
const i18n = useTrans() as TransType
const t = i18n.globalTrans
// Using translations in dialog configuration
const maDialog: UseDialogExpose = useDialog({
ok: ({ formType }, okLoadingState: (state: boolean) => void) => {
// Show different messages based on operation type
switch (formType) {
case 'add':
formRef.value.add().then((res: any) => {
res.code === ResultCode.SUCCESS
? msg.success(t('crud.createSuccess')) // "ๅๅปบๆๅ"
: msg.error(res.message)
})
break
case 'edit':
formRef.value.edit().then((res: any) => {
res.code === 200
? msg.success(t('crud.updateSuccess')) // "ไฟฎๆนๆๅ"
: msg.error(res.message)
})
break
}
},
})
// Using translations in table configuration
const options = ref<MaProTableOptions>({
header: {
mainTitle: () => t('baseUserManage.mainTitle'),
subTitle: () => t('baseUserManage.subTitle'),
},
})
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
Parameterized Translations โ
<template>
<div>
<!-- Displays: ่ฏท่พๅ
ฅ็จๆทๅ -->
<el-input :placeholder="t('form.pleaseInput', { msg: '็จๆทๅ' })" />
<!-- Displays: ็จๆทๅๅฟ
ๅกซ -->
<span class="error">{{ t('form.requiredInput', { msg: '็จๆทๅ' }) }}</span>
</div>
</template>
<script setup lang="ts">
const { globalTrans: t } = useTrans()
</script>
2
3
4
5
6
7
8
9
10
11
12
13
Direct Usage in Templates โ
<template>
<div>
<!-- Using global $t function -->
<el-button>{{ $t('crud.save') }}</el-button>
<!-- Using Hook -->
<el-button>{{ t('crud.cancel') }}</el-button>
</div>
</template>
2
3
4
5
6
7
8
9
Advanced Features โ
Dynamic Language Switching โ
// Switch to English
const { locale } = useI18n()
locale.value = 'en'
// Or use user store
const userStore = useUserStore()
userStore.setLanguage('en')
2
3
4
5
6
7
Checking Translation Key Existence โ
const { te, t } = useI18n()
// Check if key exists
if (te('some.key')) {
const translation = t('some.key')
} else {
console.warn('Translation key not found: some.key')
}
2
3
4
5
6
7
8
Pluralization Handling โ
# Language pack definition
en:
cart:
items: 'no items | one item | {count} items'
zh_CN:
cart:
items: '{count} ไธชๅๅ'
2
3
4
5
6
7
// Usage
const itemCount = ref(5)
const message = t('cart.items', itemCount.value) // "5 ไธชๅๅ"
2
3
Performance Optimization โ
Lazy Loading Language Packs โ
// On-demand language pack loading
const loadLanguage = async (locale: string) => {
try {
const messages = await import(`../locales/${locale}[${getLocaleName(locale)}].yaml`)
const { global } = useI18n()
global.setLocaleMessage(locale, messages.default)
global.locale.value = locale
} catch (error) {
console.error(`Failed to load language pack: ${locale}`, error)
}
}
2
3
4
5
6
7
8
9
10
11
Caching Optimization โ
// Cache translation results
const translationCache = new Map<string, string>()
const cachedT = (key: string, ...args: any[]) => {
const cacheKey = `${key}-${JSON.stringify(args)}`
if (translationCache.has(cacheKey)) {
return translationCache.get(cacheKey)
}
const result = t(key, ...args)
translationCache.set(cacheKey, result)
return result
}
2
3
4
5
6
7
8
9
10
11
12
13
Debugging and Troubleshooting โ
Common Issues โ
1. Missing Translation Keys โ
Issue: Console warning Not found 'xxx' key in 'zh_CN' locale messages.
Solution:
// Check if key exists
const { te, t } = useI18n()
const safeT = (key: string, fallback: string = key) => {
return te(key) ? t(key) : fallback
}
2
3
4
5
2. Module Language Packs Not Working โ
Issue: Module or plugin language packs not being loaded
Solution:
- Ensure filename format is correct:
zh_CN[็ฎไฝไธญๆ].yaml
- Check if file path is within scan scope
- Verify YAML syntax is correct
3. Type Errors โ
Issue: TypeScript type checking fails
Solution:
// Use correct type definitions
import type { TransType } from '@/hooks/auto-imports/useTrans.ts'
const i18n = useTrans() as TransType
const t = i18n.globalTrans // Type-safe translation function
2
3
4
5
Development Tools โ
Recommended IDE Plugins โ
Debugging Tips โ
// Enable verbose logging
const i18n = createI18n({
// ... other configurations
silentTranslationWarn: false, // Show translation warnings
silentFallbackWarn: false, // Show fallback warnings
missingWarn: true, // Show missing warnings
fallbackWarn: true, // Show fallback warnings
})
2
3
4
5
6
7
8
Testing Strategy โ
Unit Testing โ
// tests/i18n.spec.ts
import { mount } from '@vue/test-utils'
import { createI18n } from 'vue-i18n'
describe('i18n Component', () => {
const i18n = createI18n({
legacy: false,
locale: 'zh_CN',
messages: {
zh_CN: { hello: 'ไฝ ๅฅฝ' },
en: { hello: 'Hello' }
}
})
it('renders correct translation', () => {
const wrapper = mount(TestComponent, {
global: { plugins: [i18n] }
})
expect(wrapper.text()).toContain('ไฝ ๅฅฝ')
})
it('switches language correctly', async () => {
i18n.global.locale.value = 'en'
await wrapper.vm.$nextTick()
expect(wrapper.text()).toContain('Hello')
})
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
E2E Testing โ
// tests/e2e/i18n.spec.ts
test('language switching works', async ({ page }) => {
await page.goto('/login')
// Check default language
await expect(page.locator('.login-title')).toHaveText('็ปๅฝ')
// Switch language
await page.click('.language-switcher')
await page.click('[data-lang="en"]')
// Check language switch effect
await expect(page.locator('.login-title')).toHaveText('Login')
})
2
3
4
5
6
7
8
9
10
11
12
13
14
Extension Development โ
Adding New Languages โ
- Create language pack file:
# Create new language file in src/locales/
touch src/locales/ja[ๆฅๆฌ่ช].yaml
2
- Add translation content:
# ja[ๆฅๆฌ่ช].yaml
loginForm:
loginButton: ใญใฐใคใณ
passwordPlaceholder: ใในใฏใผใใๅ
ฅๅใใฆใใ ใใ
crud:
save: ไฟๅญ
cancel: ใญใฃใณใปใซ
2
3
4
5
6
7
8
- Update language configuration:
// If needed, add new language support during initialization
const supportedLocales = ['zh_CN', 'en', 'zh_TW', 'ja']
2
Custom Translation Logic โ
// Create custom translation Hook
export function useCustomTrans() {
const { t, te } = useI18n()
return {
t: (key: string, fallback?: string) => {
if (te(key)) {
return t(key)
2
3
4
5
6
7
8