Internationalization
For internationaliztion supastarter integrates nuxt/i18n (opens in a new tab).
Why nuxt/i18n:
nuxt/i18n is a lightweight internationalization library based on vue-i18n (opens in a new tab) especially designed
to leverage Nuxt 3 features (auto-imports, file-based route generation, etc.). It also supports automatic language detection
and url based language routing.
Usage
In Vue components, you can use the auto-imported composable useTranslations()
. This composable exposes the useI18n()
composable from nuxt/i18n (opens in a new tab) and adds types for the translation keys.
<script setup lang="ts">
const { t } = useTranslations();
</script>
<template>
<div>{{ t('hello') }}</div>
</template>
Localized Links
nuxt/i18n (opens in a new tab) also auto-imports useLocalePath()
(opens in a new tab), a useful composable to generate localized links.
If you want to use a link, the auto-imported component <NuxtLinkLocale>
is built on top of <NuxtLink>
but changes the default behavior by internally using localePath()
to make it easier to link to localized routes.
<template>
<NuxtLinkLocale to="/">{{ $t('home') }}</NuxtLinkLocale>
</template>
is equivalent to
<script setup lang="ts">
const localePath = useLocalePath();
</script>
<template>
<NuxtLink :to="localePath('/')">{{ $t('home') }}</NuxtLink>
</template>
Translations
Translations are stored in the apps/web/locales
folder. The default locale is en
and the translations are stored in en.json
.
{
"hello": "Hello World!"
}
Add a new locale
To add a new locale you need to create a new file in the apps/web/locales
folder with the locale name as the file name. For example fr.json
for French.
{
"hello": "Bonjour le monde!"
}
Then register this locale in the apps/web/i18n.config.ts
file:
export default defineI18nConfig(() => ({
// ...
availableLocales: ['en', 'de', 'es', 'fr' /* 👈🏼 */],
// ...
numberFormats: {
// ...
fr: {
currency: {
style: 'currency',
currency: 'EUR',
notation: 'standard',
},
number: {
style: 'decimal',
maximumFractionDigits: 0,
},
percent: {
style: 'percent',
useGrouping: false,
},
},
},
}));