i18n
Alixan UI uses the official Nuxt i18n module. The project keeps message keys typed, while locale switching and persistence are handled by the module.
For more detailed information, visit the Nuxt i18n documentation.
Installation
Install the Nuxt i18n module, then register it in nuxt.config.ts.
npx nuxt module add i18nConfiguration
Use strategy: 'prefix_except_default' to keep the default language without a prefix and prefix all other locales.
export default defineNuxtConfig({
modules: ['@nuxtjs/i18n'],
i18n: {
vueI18n: './configs/i18n.config.ts',
defaultLocale: 'en',
strategy: 'prefix_except_default',
detectBrowserLanguage: false,
locales: [
{ code: 'en', name: 'English', file: 'en.json' },
{ code: 'ru', name: 'Русский', file: 'ru.json' },
{ code: 'kk', name: 'Қазақша', file: 'kk.json' },
],
},
})Point vueI18n to the external config file and disable i18n warnings in i18n/configs/i18n.config.ts.
export default {
// Disable warnings because some UI props intentionally pass plain strings through $t.
missingWarn: false,
fallbackWarn: false,
}Translations
Keep locale JSON files in i18n/locales. The file option maps each locale to its translation file.
{
"app": {
"settings": "Open settings"
},
"settings": {
"language": "Language"
},
"component": {
"button": "Button"
}
}{
"app": {
"settings": "Открыть настройки"
},
"settings": {
"language": "Язык"
},
"component": {
"button": "Кнопка"
}
}{
"app": {
"settings": "Баптауларды ашу"
},
"settings": {
"language": "Тіл"
},
"component": {
"button": "Батырма"
}
}Usage
Language
<script setup lang="ts">
type Locale = 'en' | 'ru' | 'kk'
const { locale, setLocale } = useI18n()
const languageOptions: Array<{ label: string; value: Locale }> = [
{ label: 'English', value: 'en' },
{ label: 'Русский', value: 'ru' },
{ label: 'Қазақша', value: 'kk' },
]
const changeLocale = async (value: Locale): Promise<void> => {
useHead({
htmlAttrs: { lang: value },
})
await setLocale(value)
}
</script>
<template>
<div class="space-y-2">
<p class="px-1 text-sm font-medium text-muted-foreground">
{{ $t('settings.language') }}
</p>
<Select
:model-value="locale"
:options="languageOptions"
@change="changeLocale($event.value as Locale)"
/>
</div>
</template>Localized Links
Wrap internal Nuxt routes with useLocalePath before passing them to Button, IconButton or NuxtLink. This keeps the current locale prefix when users navigate between pages.
<template>
<Button :to="$localePath('/button')">
Button
</Button>
</template>Page Meta
Pass page-level SEO translation keys to usePageMeta . The composable resolves them with useI18n().t internally.
<script setup lang="ts">
usePageMeta({
title: 'seo.metaTitle',
description: 'seo.metaDescription',
})
</script>