I18n-module: Load fallback language when needed (lazy-load)

Created on 25 Feb 2018  路  24Comments  路  Source: nuxt-community/i18n-module

nuxt-i18n version: 2.3.4

Imagine you have two languages, en (default) and de.
But only parts of the en language is localized in the de file.
If you now enter a page (e.g. /de/only-half-localized-route), you see the correct translations (for de) where it applies, but no en translation because the fallback language isn't loaded properly because of lazy-loading. Instead, you see the translation keys.

A naive fix for it would be to load the fallback language every time, but I guess there is a way to check if a fallback is needed and load the fallback language in that case (if not already loaded).

This feature request is available on Nuxt.js community (#c39)
feature-request

Most helpful comment

Possibly simpler workaround:

In nuxt_config.js, using require or import, load default locale manually and pass to vue-i18n configuration:

[
      'nuxt-i18n',
      {
            // ...
            vueI18n: {
                fallbackLocale: 'en',
                messages: {
                    en: require('./app/locales/en.json'),
                },
            },
      }
],

nuxt-i18n will merge current locale messages into same object and then vue-i18n will be able to access default locale for fallback.

All 24 comments

Any update on this? Or before feature is implemented, what's the way to load fallback language every time? (and not load all of language files at the same time)

Any news?

As a workaround for now we might be using the following:

// nuxt.config.js
module.exports = {
  srcDir: './src',
  ...
  modules: [
    '@nuxtjs/pwa',
    [
      'nuxt-i18n',
      {
        locales: [
          { code: 'en', iso: 'en-US', file: 'en.js' },
          { code: 'es', iso: 'es-ES', file: 'es.js' }
        ],
        defaultLocale: 'en',
        vueI18n: {
          fallbackLocale: 'en'
        },
        lazy: true,
        langDir: 'locales/'
      }
    ]
  ],
  ...
};

// src/locales/es.js
import { assignWith } from 'lodash';
import { loadTranslation } from '../services/contents';

const useDefault = (value, defaultValue) =>
  typeof value === 'object' ?
    assignWith({}, value, defaultValue, useDefault) :
    value || defaultValue;

export default () => Promise.all([
  loadTranslation('en'),
  loadTranslation('es')
])
.then(([ defaultMessages, localizedMessages ]) => 
  assignWith({}, localizedMessages, defaultMessages, useDefault));

@RecuencoJones how does the loadTranslation function look like? Are you using axios or nuxt-axios in loadTranslation? Thx.

@JkmAS it's a simple function running fetch to load translations from our CMS:

// src/services/contents.js
export function loadTranslation(lang) {
  return fetch(`${ config.api.host }/content/lang/${ lang }`, {
    headers: { ...defaultHeaders }
  })
  .then((res) => res.json());
}

Would it be possible to prioritize it? I think it's a major missing feature.

Possibly simpler workaround:

In nuxt_config.js, using require or import, load default locale manually and pass to vue-i18n configuration:

[
      'nuxt-i18n',
      {
            // ...
            vueI18n: {
                fallbackLocale: 'en',
                messages: {
                    en: require('./app/locales/en.json'),
                },
            },
      }
],

nuxt-i18n will merge current locale messages into same object and then vue-i18n will be able to access default locale for fallback.

@rchl your solution works well and seems to be the simplest one.

I also agree that this missing feature is really important and should be prioritized!

My function for load fallback language when needed

/plugins/i18n.js:

export default ({ app }, inject) => {

inject ('loadLanguageAsync', async (lang) => {
    if (app.i18n.locale !== lang) {
      if (!app.i18n.loadedLanguages.includes(lang)) {
        try {
          const module = await import(/* webpackChunkName: "lang-[request]" */ `@/lang/${lang}`)
          const messages = module.default ? module.default : module
          app.i18n.setLocaleMessage(lang, typeof messages === 'function' ? await Promise.resolve(messages()) : messages)
          app.i18n.loadedLanguages.push(lang)
        } catch (error) {
          console.error(error)
        }
      }
      app.i18n.locale = lang
    }
  })

}

then call "this.$loadLanguageAsync(lang)" from anywhere

I am using that for translating via keyboard shortcuts events :)

Hope this will help someone

I can confirm this as well. Using nuxt 2.5.0.
Meaning this option won't work at all for lazy loaded messages.

        vueI18n: {
          fallbackLocale: 'en'
        }

@MarvinMiles would you mind sending in a PR?

        vueI18n: {
          fallbackLocale: 'en'
        },

This is what i needed! thank you!

No sure why this issue is closed. Today, bug still exists in latest nuxt v2.11.0. It really is needed to add to documentation that the fallback settings in nuxt.config are useless without, the vueI18n: { fallbackLocale: 'en' }, mentioned above

I have this bug.
My nuxt version 2.11.0.

My nuxt config

  i18n: {
    defaultLocale: 'en',
    vueI18n: {
      fallbackLocale: 'en',
      messages: {
        en: require('./lang/json/en'),
      },
    },
    detectBrowserLanguage: {
      useCookie: false,
    },
    strategy: 'no_prefix',
    locales: [
      {
        code: 'ru',
        name: 'Russian',
        file: 'ru-RU.js'
      },
      {
        code: 'en',
        name: 'English',
        file: 'en-US.js'
      }
    ],
    differentDomains: false,
    forwardedHost: false,
    lazy: true,
    langDir: 'lang/',
    parsePages: false,
  },

This solution does not work.

            vueI18n: {
                fallbackLocale: 'en',
                messages: {
                    en: require('./app/locales/en.json'),
                },
            },
````

It does not work.

vueI18n: {
  fallbackLocale: 'en'
},
It does not work.

vueI18n: {
  fallbackLocale: 'en'
},
detectBrowserLanguage: {
  useCookie: false,
  alwaysRedirect: true,
  fallbackLocale: 'en'
},

```

@golubvladimir Since this bug was fixed, you don't need to manually load messages using require. You are probably breaking the fallback functionality by doing so.

And I don't understand why do you have different paths to en messages in different places. In one it's ./app/locales/en.json, in another the file is called en-US.js.

I think the issue is with your configuration. You can create a separate issue if you need some help but you should create reproduction on https://codesandbox.io/

No sure why this issue is closed. Today, bug still exists in latest nuxt v2.11.0. It really is needed to add to documentation that the fallback settings in nuxt.config are useless without, the vueI18n: { fallbackLocale: 'en' }, mentioned above

Feel free to submit improvements.
The vueI18n.fallbackLocale is THE setting that is needed. There are no other settings that are needed.
The detectBrowserLanguage.fallbackLocale, if that's what you are confused about, is unrelated to the fallback above. Former is to have fallback for i18n keys, latter is fallback for detecting the browser language.

@rchl
My config:

  i18n: {
    defaultLocale: 'en',
    vueI18n: {
      fallbackLocale: 'en'
    },
    detectBrowserLanguage: {
      useCookie: false,
    },
    strategy: 'no_prefix',
    locales: [
      {
        code: 'ru',
        name: 'Russian',
        file: 'ru-RU.js'
      },
      {
        code: 'en',
        name: 'English',
        file: 'en-US.js'
      }
    ],
    differentDomains: false,
    forwardedHost: false,
    lazy: true,
    langDir: 'lang/',
    parsePages: false,
  },

// en-US.js

export default require('./json/en');

It does not work.

It does not work.

    locales: [
      {
        code: 'ru',
        name: 'Russian',
        file: 'json/ru.json'
      },
      {
        code: 'en',
        name: 'English',
        file: 'json/en.json'
      }
    ],

@golubvladimir You are repeating yourself, please create small reproducible case on codesandbox if you want some help.

@golubvladimir so no problem then?

@rchl Yes, update to 6.5.0. It helped.

Related to this issue is a problem that if we have a non-language file like for example README.md in the langDir, the compiler breaks. Which I think is weird, as should nuxt-i18n not _only_ load the files specified with locales: [{file: 'en.js',..},..] ?

Was this page helpful?
0 / 5 - 0 ratings