How can I use vue-i18n in a Vue 3 web component?
Asked Answered
L

2

6

I'm creating a Vue web component using vue-cli 4.5.13 and the --target wc option. I also need the component to use the vue-i18n-next plugin (last version for vue 3 projects), which requires some options to be passed to the main Vue instance, but now there is no main instance since the entrypoint is the vue component itself, so i18n has to be instantiated within the component.

I found this question for vue2: How can I use vue-i18n in a Vue web component? and it works for vue2, but instantiating the i18n object in the component options is not valid for vue3 (this.$i18n stays undefined). So this is not working:

export default {
  name: "custom-compo",
  i18n: i18n,
  components: { ChildComponent }
  data, methods...
};

The solution should work both if exporting the web component (and using it on a standard page) and also if npm run serve ing a standard app with this component inside (but again instantiating i18n in the compo as in answer to that question, not in main.js)

I am not asking how to setup vue-i18n within a normal vue project, but how to inisitalise i18n within a component that's gonna be built or exported as a custom-element or web-component, using the vue-cli, with vue 3.

I am not using composition api and setup(), but old options api. Just upgraded to vue3 package and changed deprecated syntax as per docs.

Listerism answered 18/8, 2021 at 14:10 Comment(4)
Does this help you? #69104050Master
Thanks @anatolhiman, close! but the referred question implements composition api and I am sticking to options api.Listerism
Have you found anything on this?Garvy
Anything written in Options API can be written in Composition API and vice-versa. The only thing changed is how you group code. In options you need to group component members by type (computed, data, methods) whereas in Composition you can group them by any criteria you want, inside setup.Firewater
N
0

So far, vue3 default web components implementation doesn't support all plugins. Therefore you would probably need a vue-web-component wrapper that could build a web-component while still injecting the plugin.

You can build a custom wrapper and try to add your plugin based on this solution

Or you can also look for a vue-web-component wrapper package

Nereidanereids answered 19/5 at 19:51 Comment(0)
W
-1

Step 1: Install vue-i18n and dependency npm package using the commands below,

npm install vue-i18n@next
npm install --save-dev @intlify/vue-i18n-loader

Step 2: Create i18n as seperate i18n.js file inside src folder

import { createI18n } from 'vue-i18n'


function loadLocaleMessages () {
  const locales = require.context('./locales', true, /[A-Za-z0-9-_,\s]+\.json$/i)
  const messages = {}
  locales.keys().forEach(key => {
    const matched = key.match(/([A-Za-z0-9-_]+)\./i)
    if (matched && matched.length > 1) {
      const locale = matched[1]
      messages[locale] = locales(key).default
    }
  })
  return messages
}

export default createI18n({
  locale: process.env.VUE_APP_I18N_LOCALE || 'en',
  fallbackLocale: process.env.VUE_APP_I18N_FALLBACK_LOCALE || 'en',
  messages: loadLocaleMessages()
})

Step 3: Import i18n in main.js

import i18n from './i18n'

Step 4: Inside main.js add the i18n, router, store reference to createApp

import { createApp } from 'vue'
import App from './App.vue'
import './registerServiceWorker'
import router from './router'
import store from './store'
import i18n from './i18n'
const app = createApp(App).use(i18n).use(store).use(router)
app.mount('#app')

Step 5: Design the language dropdown menu

<li class="nav-item dropdown" ref="dropdown">
  <button class="nav-link" data-toggle="dropdown" @click="toggleDropdown">
    <i class="flag-icon " :class="selectedLanguage === 'en' ? 'flag-icon-us': 'flag-icon-es'"></i>
  </button>
  <div class="dropdown-menu dropdown-menu-right p-0" :class="{'show':isDropdownOpened}">
    <a href="#" class="dropdown-item" :class="selectedLanguage === 'en' ? 'active': ''" @click.prevent="changeLanguage('en')">
      <i class="flag-icon flag-icon-us mr-2"></i> English
    </a>
    <a href="#" class="dropdown-item" :class="selectedLanguage === 'es' ? 'active': ''" @click.prevent="changeLanguage('es')">
      <i class="flag-icon flag-icon-es mr-2"></i> Spanish
    </a>
  </div>
</li>

Language Dropdown

Step 6: Add the changeLanguage method inside the component

changeLanguage (locale) {
  this.$i18n.locale = locale
  this.selectedLanguage = locale
  this.isDropdownOpened = false
}

Step 7: Create locales folder inside src folder

Step 8: Create en.json and es.json two seperate files

Step 9: Inside en.json file likes below

{
  "common.login": "Login",
  "common.signout": "Sign Out",
  "common.switchuser": "Switch User",
  "common.profile": "Profile",
  "common.submit": "Submit"
}

Step 10: Inside es.json file likes below

{
   "common.login": "Acceso",
   "common.signout": "Desconectar",
   "common.switchuser": "Cambiar de usuario",
   "common.profile": "Perfil",
   "common.submit": "Enviar"

}

Wargo answered 19/8, 2021 at 3:43 Comment(1)
Please read my question. This is not what I am asking. I am not asking how to setup vue-i18n within a normal vue project, but how to inisitalise i18n within a component that's gonna be built or exported as a custom-element or web-component, using the vue-cli.Listerism

© 2022 - 2024 — McMap. All rights reserved.