Guillaume Prévost
Guillaume Prévost

Reputation: 413

Vue i18n : Pluralization and Linked Messages not interpreted in production

I've managed to integrate nicely the vue-i18n library on my development environment and it works perfectly.

However, when I deploy the project on Heroku, every message using vue-i18n Pluralization or Linked Locale Messages is not being interpreted and shows the entire locale message string :

I've opened a discussion on the repo but no reply so far...

I am using vue-i18n (9.2.2) in a Nuxt3 plugin, therefore using VueJS 3, building with Vite with the plugin for vue-i18n vite-plugin-vue-i18n.

Nuxt3 configuration (nuxt.config.ts), showing the Vite plugin config to resolve the locales JSON files :

import { defineNuxtConfig } from 'nuxt'
import { resolve, dirname } from 'node:path'
import { fileURLToPath } from 'url'
import VueI18nVitePlugin from '@intlify/unplugin-vue-i18n/vite'

export default defineNuxtConfig({
  ...
  vite: {
    plugins: [
      VueI18nVitePlugin({
        include: [
          resolve(dirname(fileURLToPath(import.meta.url)), './locales/*.json')
        ]
      })
    ]
  },
 ...
});

Nuxt plugin for vue-i18n (plugins/vue-i18n.ts) :

import { createI18n } from 'vue-i18n'
import fr from '~/locales/fr.json'
import en from '~/locales/en.json'

// DOC I18N : https://www.i18next.com/translation-function/essentials
export default defineNuxtPlugin(({ vueApp }) => {
  const i18n = createI18n({
    legacy: false,
    allowComposition: true,
    globalInjection: true,
    locale: 'fr',
    fallbackLocale: 'en',
    messages: { 
      'en': en, 
      'fr': fr, 
    }
  });
  vueApp.use(i18n);
})

And here are the 2 locales files :

locales/fr.json :

{
  "test": "Zero test | Un test | {n} tests",
  "testnested": {
    "nestedvalue": "Zero sous-test | Un sous-test | {n} sous-tests"
  },
  ...

locales/en.json :

  "test": "Zero test | One test | {n} tests",
  "testnested": {
    "nestedvalue": "Zero sub-test | Un sub-test | {n} sub-tests"
  },
  ...
}

Example of how the locale messages are used within the Vue templates :

    <p>
      -- TEST ROOT --<br />
      {{ $t('test', 0) }}<br />
      {{ $t('test', 1) }}<br />
      {{ $t('test', 2) }}<br />
      <br />
      -- TEST NESTED --<br />
      {{ $t('testnested.nestedvalue', 0) }}<br />
      {{ $t('testnested.nestedvalue', 1) }}<br />
      {{ $t('testnested.nestedvalue', 2) }}<br />
    </p>

The Plurals and Linked messages syntax in the locales messages should be interpreted by vue-i18n and not display the full locale message string.

[EXPECTED] Local environment output :

Expected result (working running on local dev)

[BUG RESULT] Same code packaged for production, deployed on Heroku :

Bug result as displayed once packaged & deployed

Another example with failing Linked Messages (in production) :

Other example

Here are some infos about my system :

  System:
    OS: Windows 10 10.0.22000
    CPU: (8) x64 Intel(R) Core(TM) i7-1065G7 CPU @ 1.30GHz
    Memory: 16.35 GB / 31.59 GB
  Binaries:
    Node: 16.13.2 - C:\Program Files\nodejs\node.EXE
    Yarn: 1.22.17 - C:\Program Files\nodejs\yarn.CMD
    npm: 8.1.2 - C:\Program Files\nodejs\npm.CMD
  Browsers:
    Edge: Spartan (44.22000.120.0), 
    Chromium (105.0.1343.27)
    Internet Explorer: 11.0.22000.120
  npmPackages:
    @intlify/unplugin-vue-i18n: ^0.5.0 => 0.5.0
    vitest: ^0.20.3 => 0.20.3
    vue-i18n: ^9.2.2 => 9.2.2
    vue-toastification: next => 2.0.0-rc.5

I have read on other threads and on StackOverflow here but the accepted answer doesn't seem to be up-to-date, and believe there could be issues with the way webpack or vite are packaging the project.

What am I doing wrong here ?

If nothing seems wrong, would you recommend I open a bug report on vue-i18n repo ? Or on the @intlify/vite-plugin-vue-i18n repository ?

Upvotes: 2

Views: 2883

Answers (2)

Stan Khatko
Stan Khatko

Reputation: 1

A part of quasar starter app config (quasar.config.js)

    // if you want to use named tokens in your Vue I18n messages, such as 'Hello {name}',
      // you need to set `runtimeOnly: false`

Upvotes: 0

Mick Quickfall
Mick Quickfall

Reputation: 61

I had the same problem.

Think this is an issue with the vite-plugin-vue-i18n pre-compile which converts messages to JS functions. I set runtimeOnly:false in vite.config.js and it then worked the same in Production as in HMR.

Upvotes: 6

Related Questions