Skip to content

Internationalization

The template comes with built-in internationalization support using Vue I18n. This guide will help you understand and implement multi-language support in your app.

How It Works

The internationalization system is preconfigured with:

  • Dynamic locale loading
  • Route-based language switching
  • Persistent language preferences
  • Runtime locale changes

Project Structure

src/
├── i18n.js           # i18n configuration
└── locales/          # Translation files
    ├── en.json       # English translations
    └── zh.json       # Chinese translations

Basic Usage

1. Using Translations in Templates

vue
<template>
  <!-- Simple text -->
  <p>{{ $t('HomePage.heading') }}</p>

  <!-- With parameters -->
  <i18n-t keypath="HomePage.welcome" tag="p">
    <template #name>{{ username }}</template>
  </i18n-t>

  <!-- Pluralization -->
  <p>{{ $tc('Products.count', productCount) }}</p>
</template>

2. Using Translations in JavaScript

js
import { useI18n } from 'vue-i18n'

export default {
  setup() {
    const { t, locale } = useI18n()

    // Get translation
    console.log(t('HomePage.heading'))

    // Change locale
    locale.value = 'zh'
  }
}

Translation Files

Structure

Each locale file (e.g., en.json, zh.json) follows a nested structure:

json
{
  "NavBar": {
    "home": "Home",
    "about": "About"
  },
  "HomePage": {
    "heading": "Welcome to {app}",
    "feature-text": "Features",
    "loading": "Loading..."
  }
}

Adding a New Language

  1. Create a new locale file in src/locales/:

    json
    // fr.json
    {
      "NavBar": {
        "home": "Accueil",
        "about": "À propos"
      }
    }
  2. Register the locale in src/i18n.js:

    js
    export const SUPPORT_LOCALES = ['en', 'zh', 'fr']

Advanced Features

1. Locale Switching

The template includes a LanguageSwitcher component that handles locale changes:

vue
<template>
  <select v-model="currentLocale">
    <option v-for="locale in availableLocales" :key="locale" :value="locale">
      {{ locale }}
    </option>
  </select>
</template>

2. Route-Based Localization

URLs automatically include the current locale:

  • English: /en/products
  • Chinese: /zh/products

The router handles this through navigation guards:

js
router.beforeEach(async (to, _from, next) => {
  const paramsLocale = to.params.locale
  // Load locale if needed
  await loadLocaleMessages(i18n, paramsLocale)
  // Set i18n language
  setI18nLanguage(i18n, paramsLocale)
  return next()
})

3. Number and Date Formatting

Use Vue I18n's number and date formatting:

vue
<template>
  <p>{{ $n(price, 'currency') }}</p>
  <p>{{ $d(date, 'long') }}</p>
</template>

<script setup>
const price = 99.99
const date = new Date()
</script>

4. Lazy Loading Translations

For large applications, you can lazy load translations:

js
const messages = await import(`@/locales/${locale}.json`)
i18n.global.setLocaleMessage(locale, messages.default)

Best Practices

  1. Use Namespaces

    json
    {
      "ProductList": {
        "title": "Products",
        "empty": "No products found"
      }
    }
  2. Handle Pluralization

    json
    {
      "cart": {
        "items": "no items | one item | {count} items"
      }
    }
  3. Provide Fallbacks

    js
    const i18n = createI18n({
      fallbackLocale: 'en'
      // ...
    })
  4. Use Translation Keys

    vue
    <!-- ❌ Don't -->
    {{ $t('Submit') }}
    
    <!-- ✅ Do -->
    {{ $t('Forms.submit') }}

Testing Translations

  1. Check Missing Keys

    bash
    npm run i18n:check
  2. Visual Testing

    • Test UI in all supported languages
    • Verify text wrapping and layout
    • Check RTL support if needed

RTL Support

For right-to-left languages:

  1. Add RTL detection:

    js
    const isRTL = ['ar', 'he'].includes(locale.value)
  2. Apply RTL styles:

    css
    [dir='rtl'] {
      /* RTL-specific styles */
    }

Common Issues

1. Missing Translations

Use the fallback locale and warn in development:

js
const i18n = createI18n({
  missingWarn: process.env.NODE_ENV === 'development',
  fallbackWarn: process.env.NODE_ENV === 'development'
})

2. Runtime Locale Changes

Handle dynamic imports correctly:

js
async function changeLocale(locale) {
  await loadLocaleMessages(i18n, locale)
  document.querySelector('html').setAttribute('lang', locale)
}

3. Date/Time Formatting

Import necessary date-fns locales:

js
import { format } from 'date-fns'
import { enUS, zhCN } from 'date-fns/locale'

Next Steps

  1. Review your app's internationalization needs
  2. Plan your locale structure
  3. Implement translations progressively
  4. Test with native speakers
  5. Consider automated translation workflows

Released under the MIT License.