Search code examples
vue.jsnuxt.jsnuxt3.jsvue-i18n

How to make i18n settings async Nuxt 3


Active langauges and translations are coming from API. I need to find a way to set up i18n to be async. So first of all I'll fetch available languages for this website from API, after that I would detect current langauge from prefix/cookie and fetch only It's translations and after that I would listen to nuxtApp.$i18n.onBeforeLanguageSwitch so i can fetch translations if needed and add it to i18n object

Edited

nuxt.config.ts

i18n: {
    locales: ['en', 'ru', 'es', 'de', 'fi', 'sv', 'fr', 'it', 'br'],
    defaultLocale: 'en',
    strategy: 'prefix',
    detectBrowserLanguage: {
      useCookie: true,
      cookieKey: 'i18n_redirected',
      redirectOn: 'root',
    },
  },

plugins/i18n.ts

export default defineNuxtPlugin(nuxtApp => {

  useAsyncData('directory_translations', async () => {
    const data = await DirectoryApi.getAllDirectories()
    const directory = DirectoryService.createDirectoryObject(data)
    const translationsData = await DirectoryApi.getTranslations(directory.languages[nuxtApp.$i18n.locale.value].ID)
    const translations = DirectoryService.createTranslationsObject(translationsData, directory)

    nuxtApp.$i18n.mergeLocaleMessage(nuxtApp.$i18n.locale.value, translations)
    // this is working also, but somehow messages are created from scratch on client side and data is lost
    useState('directory', () => directory)
    useState('translations', () => translations)

  })

  nuxtApp.$i18n.onBeforeLanguageSwitch = async (oldLocale, newLocale, isInitialSetup, nuxtApp) => {
    // This works
    const directory = useState('directory') as Ref<Directory>
    const translationsData = await DirectoryApi.getTranslations(directory.value.languages[newLocale].ID)
    const translations = DirectoryService.createTranslationsObject(translationsData, directory.value)
    nuxtApp.$i18n.mergeLocaleMessage(newLocale, translations)
  }
})
<script lang="ts" setup>

const {messages} = useI18n()

</script>

<template>

<div>
 {{ JSON.stringify(messages) }} 
</div>

</template>

Everything works fine on server side, On recieved html (from server) i can see message list, but seems like i18n reruns itself on client ones more and my messages are gone


Solution

  • OP fixed the issue by using an async plugin + using node-fetch to get the data (rather than useAsyncData).

    I also recommend that you give a try to that one (works everywhere): https://github.com/unjs/ohmyfetch