Nuxt
Internationalization

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.

index.vue
<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.

index.vue
<template>
  <NuxtLinkLocale to="/">{{ $t('home') }}</NuxtLinkLocale>
</template>

is equivalent to

index.vue
<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.

apps/web/locales/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.

apps/web/locales/fr.json
{
  "hello": "Bonjour le monde!"
}

Then register this locale in the apps/web/i18n.config.ts file:

apps/web/i18n.config.ts
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,
      },
    },
  },
}));