---
navigation.title: Vue
title: Internationalization (i18n) in a Vue app
description: 'Learn how to internationalize your Vue app with multi-directional support (LTR/RTL).'
select:
  items:
    - label: Nuxt
      icon: i-logos-nuxt-icon
      to: /getting-started/i18n/nuxt
    - label: Vue
      icon: i-logos-vue
      to: /getting-started/i18n/vue
---

## Usage

::note{to="/components/app"}
Nuxt UI provides an [App](/components/app) component that wraps your app to provide global configurations.
::

### Locale

Use the `locale` prop with the locale you want to use from `@nuxt/ui/locale`:

```vue [App.vue]
<script setup lang="ts">
import { fr } from '@nuxt/ui/locale'
</script>

<template>
  <UApp :locale="fr">
    <RouterView />
  </UApp>
</template>
```

### Custom locale

You also have the option to add your locale using `defineLocale`:

```vue [App.vue]
<script setup lang="ts">
import { defineLocale } from '@nuxt/ui/runtime/composables/defineLocale'

const locale = defineLocale({
  name: 'My custom locale',
  code: 'en',
  dir: 'ltr',
  messages: {
    // implement pairs
  }
})
</script>

<template>
  <UApp :locale="locale">
    <RouterView />
  </UApp>
</template>
```

::tip
Look at the `code` parameter, there you need to pass the iso code of the language. Example:
* `hi` Hindi (language)
* `de-AT`: German (language) as used in Austria (region)
::

### Dynamic locale

To dynamically switch between languages, you can use the [Vue I18n](https://vue-i18n.intlify.dev/) plugin.

::steps{level="4"}

#### Install the Vue I18n package

::code-group{sync="pm"}

```bash [pnpm]
pnpm add vue-i18n@10
```

```bash [yarn]
yarn add vue-i18n@10
```

```bash [npm]
npm install vue-i18n@10
```

```bash [bun]
bun add vue-i18n@10
```

::

#### Use the Vue I18n plugin in your `main.ts`

```ts [main.ts]{2,6-18,22}
import { createApp } from 'vue'
import { createI18n } from 'vue-i18n'
import ui from '@nuxt/ui/vue-plugin'
import App from './App.vue'

const i18n = createI18n({
  legacy: false,
  locale: 'en',
  availableLocales: ['en', 'de'],
  messages: {
    en: {
      // ...
    },
    de: {
      // ...
    }
  }
})

const app = createApp(App)

app.use(i18n)
app.use(ui)

app.mount('#app')
```

#### Set the `locale` prop using `useI18n`

```vue [App.vue]
<script setup lang="ts">
import { useI18n } from 'vue-i18n'
import * as locales from '@nuxt/ui/locale'

const { locale } = useI18n()
</script>

<template>
  <UApp :locale="locales[locale]">
    <RouterView />
  </UApp>
</template>
```

::

### Dynamic direction

Each locale has a `dir` property which will be used by the `App` component to set the directionality of all components.

In a multilingual application, you might want to set the `lang` and `dir` attributes on the `<html>` element dynamically based on the user's locale, which you can do with the [useHead](https://unhead.unjs.io/usage/composables/use-head) composable:

```vue [App.vue]
<script setup lang="ts">
import { computed } from 'vue'
import { useI18n } from 'vue-i18n'
import { useHead } from '@unhead/vue'
import * as locales from '@nuxt/ui/locale'

const { locale } = useI18n()

const lang = computed(() => locales[locale.value].code)
const dir = computed(() => locales[locale.value].dir)

useHead({
  htmlAttrs: {
    lang,
    dir
  }
})
</script>

<template>
  <UApp :locale="locales[locale]">
    <RouterView />
  </UApp>
</template>
```

## Supported languages

:supported-languages
