Search code examples
javascriptvue.jsvuejs2internationalizationvue-i18n

Changing translations within Vue-i18n for different domains


I have an app used globally and my company is in the process of rebranding itself for some markets.

For example in the U.S. and Canada we are known as "Acme Company", but now we want to be known as "Acme Company" in the U.S. and as "Foo Company in Canada.

Currently our vue-18n translation files are littered with "Acme Company" inside the translations, for example:

TITLE_WELCOME_MSG: 'Acme Company lorem ipsum dolor sit amet, consectetur adipiscing elit.'

What I am trying to do is something like this:

TITLE_WELCOME_MSG: '{companyBrand} lorem ipsum dolor sit amet, consectetur adipiscing elit.'

Which then requires me to update the implementation of TITLE_WELCOME_MSG to now pass companyBrand in like this:

this.$t('TITLE_WELCOME_MSG', { companyBrand: getCompanyBrandBasedOnDomain() })

However now I need to do this in hundreds of places (apparently we really like saying our name). It would be better if I could just provide companyBrand to the i18n instance on build and it would automatically update all of the translations with that variable. Then I wouldn't need to update hundreds of places.

We want all locales to see the same text so if you're in Canada in any locale you would see "Foo Company". Additionally if possible, I am hoping to also exclude "Acme Company" from any source code as well.

Is there a way to setup variables inside the vue-i18n instance that will all get translated the same without having to update all of the implementations?


Solution

  • If you need custom behaviour, it's preferable to use custom functions that suit it instead of shimming third-party library that shouldn't be aware of your case.

    vue-i18n functions have variadic arguments, some signatures can be discarded for the ease of the implementation. It's cleaner to use another function name to not interfere with library names, but they could be replaced for a drop-in replacement:

    Vue.use(VueI18n);
    Vue.use({
      install() {
        Vue.prototype._orig$t = Vue.prototype.$t;
        Vue.prototype.$t = function (path, values = {}) {
          return this._orig$t(path, { companyBrand: '...', ...values };
        }
      }
    );
    

    Same for $tc, etc if needed.

    Another option would probably be to use a formatter. Since base formatter not publicly exposed, it needs to be reimplemented, or extended from i18n.formatter, and this becomes hacky at this point.