2

For the sake of reproduction purposes I will try to describe what I've done:

.

import { createVuetify } from 'vuetify'
import { createVueI18nAdapter } from 'vuetify/locale/adapters/vue-i18n'
import { createI18n, useI18n } from 'vue-i18n'

const messages = { en: { title: "title | en" }, de: { title: "Titel | de" }}

const i18n = new createI18n({
  legacy: false,
  locale: 'en',
  fallbackLocale: 'en',
  messages,
})

export default createVuetify({
  locale: {
    adapter: createVueI18nAdapter({ i18n, useI18n })
  }
})
  • For testing purposes I changed the content of App.vue to

.

<script setup lang="ts">
import { useLocale } from 'vuetify'

const { t, current } = useLocale()

setTimeout(() => {
  current.value = 'de';
}, 3000);
</script>

<template>
  <div>
    <div>content:</div>
    <div>{{ t('title') }}</div>
  </div>
</template>

This works as expected!

  • Instead of managing the messages in a large object I would like to move them to their components as described in the vue-i18n docs. I completely removed the messages field from the i18n variable ( because I don't need the messages object anymore ) and added the following to App.vue

.

<i18n>
  {
    "en": {
      "title": "title | en"
    },
    "de": {
      "title": "Titel | de"
    }
  }
</i18n>
  • Since this doesn't work out of the box I installed the package @intlify/unplugin-vue-i18n the from these docs , updated the package @vitejs/plugin-vue to version 3.2.0. and modified the vite.config.ts file to use the plugin

.

VueI18nPlugin({
  include: resolve(dirname(fileURLToPath(import.meta.url)), './src/**'),
}),

Unfortunately I don't know the correct path to use... For now the app does not render the message

enter image description here

Does someone know what's wrong or missing?

baitendbidz
  • 187
  • 3
  • 19

2 Answers2

0

From the vuetify docs:

The Vuetify locale service only provides a basic translation function t, and should really only be used for internal or custom Vuetify components. It is recommended that you use a proper i18n library such as vue-i18n in your own application. Vuetify does provide support for integrating with other libraries.

so instead of using vuetify's t you should use:

import { useI18n } from 'vue-i18n'

const { t } = useI18n;
xyos
  • 269
  • 1
  • 6
  • When calling `const { t } = useI18n();` I get the error `Uncaught SyntaxError: Need to install with 'app.use' function` but I'm already embedding it inside the Vuetify plugin? – baitendbidz Dec 01 '22 at 08:18
0

First off, not entirely sure what the point or benefits are from using the vuetify i18n. Unless someone corrects me on it, you should probably just ignore it. Also, I'm going to assume Vue3, Vite and Typescript, and that you want static locale files (the translations). I use pnpm, but that's very simple to change to yarn or npm.

Installation

pnpm add vue-i18n@9
pnpm add @intlify/unplugin-vue-i18n -D

vite.config.ts (import)

// I18n
import VueI18nPlugin from '@intlify/unplugin-vue-i18n/vite'
// Utilities
import { defineConfig } from 'vite'
import { fileURLToPath, URL } from 'node:url'
import { resolve, dirname } from 'node:path'

vite.config.ts (plugin section)

I have my project setup so that the locales folder is in the src folder. Add this to the plugins array:

VueI18nPlugin({
  // locale messages resource pre-compile option
  include: resolve(dirname(fileURLToPath(import.meta.url)), './src/locales/*.yml'),
}),

i18n.ts (new file)

import { createI18n } from 'vue-i18n'
import messages from '@intlify/unplugin-vue-i18n/messages'

export default createI18n({
    legacy: false,
    locale: 'nl',
    messages
})

index.ts (add to the imports)

import i18n from './i18n'

index.ts (registerPlugins)

To the registerPlugins function you add the .use(i18n) and put a reference to it on the globalProperties (but I'm not 100% sure that this is good practice). It will look something like this, depending on the plugins that you use.

export function registerPlugins (app: App) {
    loadFonts()
    app
        .use(vuetify)
        .use(router)
        .use(pinia)
        .use(i18n)

    app.config.globalProperties.$t = i18n.global.t
}

src/locales The locales folder contains YAML files of the translations. For example, two files called en.yml and nl.yml and contain a YAML structure like this:

button:
  login: Log in
  logout: Log off
auth:
  logged-in-as: Logged in as {name}.
  authenticated: Logged in
about:
  title: About page

The nl.yaml file follows the same structure but has the translation for dutch.


MyComponent.vue

To use the translations in a component, you this in your setup:

<script setup lang="ts">
    import { useI18n } from 'vue-i18n'
    const { t } = useI18n()
</script>

And you can now use the translations in your template (example):

<template>
    <div v-if="isAuthenticated">
        {{ t('auth.logged-in-as', {name: user.given_name}) }}
    </div>
</template>

I had just started integrating i18n, and this seems to be a good setup. I see a somewhat similar (but not exactly) setup in the Vitesse template by Antfu. I can't promise that this is the best setup, as I've not figured that out yet, but it's probably a good start. Let me know if this works.

svenema
  • 1,766
  • 2
  • 23
  • 45