nuxt-modules / i18n

I18n module for Nuxt
https://i18n.nuxtjs.org
MIT License
1.71k stars 478 forks source link

Translations fetched via API; Hydration mismatch #1688

Closed markus-gx closed 1 year ago

markus-gx commented 1 year ago

Version

@nuxtjs/i18n: 8.0.0-beta.4 nuxt:3.0.0

Nuxt configuration

Please change to [x] if relevant for this issue:

@nuxtjs/i18n configuration

i18n: {
    strategy: 'no_prefix', // todo switch to prefix (currently buggy)
    defaultLocale: process.env.DEFAULT_LANG,
    vueI18n: {
      fallbackLocale: process.env.DEFAULT_LANG,
      legacy: false,
    },
    detectBrowserLanguage: {
      useCookie: true,
      cookieCrossOrigin: true,
      cookieKey: 'langkey',
      redirectOn: 'root',
    },
  },

What is Expected?

I am fetching translations from a CMS. Therefore no static json file with translations is available. In app.vue => on start of the application I inject the translations.

if (settingsStore.getTranslations) {
  for (const lang of Object.keys(settingsStore.getTranslations)) {
    useI18n().setLocaleMessage(lang, settingsStore.getTranslations[lang])
  }
}

Which seems to work but I do get a hydration mismatch warning in local development mode when using (example)

<h2>{{$t('project-link')}}</h2>

[Vue warn]: Hydration text content mismatch in :

  • Client: to the project
  • Server: project-link

Am I doing something wrong or is this still an issue.

motea927 commented 1 year ago

Hi, It seems not a bug, Because you not wait fetch translations, So client side and server side will render difference result, You can use top level await to wait fetch translations, like this

<script setup lang="ts">
await fetchTranslation()

if (settingsStore.getTranslations) {
  for (const lang of Object.keys(settingsStore.getTranslations)) {
    useI18n().setLocaleMessage(lang, settingsStore.getTranslations[lang])
  }
}
</script>

And you may invoke fetchTranslation twice, So you need use useState in your fetchTranslation and add some logic to prevent fetch twice.

markus-gx commented 1 year ago

You are absolutely right. I tried that, but in the end it was an API caching issue I faced. #resolved.

khaledOghli commented 2 months ago

Hi, It seems not a bug, Because you not wait fetch translations, So client side and server side will render difference result, You can use top level await to wait fetch translations, like this

<script setup lang="ts">
await fetchTranslation()

if (settingsStore.getTranslations) {
  for (const lang of Object.keys(settingsStore.getTranslations)) {
    useI18n().setLocaleMessage(lang, settingsStore.getTranslations[lang])
  }
}
</script>

And you may invoke fetchTranslation twice, So you need use useState in your fetchTranslation and add some logic to prevent fetch twice.

where can I put the code !! where ever I put the await I tried all hooks mounted created, and in setup await but still loading the local keys first in the server then in client changed!

[Vue warn]: Hydration text content mismatch on <p data-v-inspector=​"layers/​base/​components/​app/​Footer.vue:​8:​7">​ © 2024 - قالب Nuxt​

khaledOghli commented 2 months ago
    // BUG: Hydration text content mismatch
    const storedTranslations = localStorage.getItem(translationsKey);

    if (storedTranslations) {
      const translations = JSON.parse(storedTranslations);
      i18nSetLocaleMessage(lang, translations);
      if (import.meta.client)
        console.log(`Loaded translations for ${lang} from local storage`);
      return;
     }

my main issue was that I loaded them from local storage and of course, it was not SSR friendly, any other way other than cookies!