vue-cli-plugin-i18n icon indicating copy to clipboard operation
vue-cli-plugin-i18n copied to clipboard

Default Locale Messages

Open codetheorist opened this issue 3 years ago • 2 comments

Module versions:

  • Vue CLI: 4.x
  • vue-cli-plugin-i18n: 2.x

To Reproduce Steps to reproduce the behavior:

  1. Create e new Vue app using the CLI
  2. Install the Vue I18n plugin
  3. Enable SFC I18n
  4. View i18n report to see warnings about missing & unused i18n messages
  5. View browser console to see warning about missing i18n message

Expected behavior The installation creates a default file in the locale directory for the default locale. A component is also created, with an i18n block, with a translated string and a call to $t within the template to show this translated string.

All translated string keys should match however, the key created in the default locale file is different to that in the i18n block and the template section.

Screenshots en json - app - Visual Studio Code 19_04_2021 15_03_55

Additional context As the key/value is in the SFC i18n block, then the component shows the string correctly however, there are still warnings produced due to the mismatch in data.

codetheorist avatar Apr 19 '21 14:04 codetheorist

Thank you for your reporting!

@pixari Could you help this issue?

kazupon avatar Apr 19 '21 14:04 kazupon

I have a project that ran vue add i18n before (on 12 May). It works just fine. Then I run into the same issue when I create a new project and ran vue add i18n yesterday.

Turns out that the bug was introduced by the code generated by this plugin. (I'm just a user and not good at webpack and vue-cli. Can't tell the reason why, but provide a solution that I and my collage founded out.)

Let's compare the key piece from generated code (complete code is at the end):

// before
messages[locale] = locales(key).default
// after
messages[locale] = locales(key)

The problem is that messages option for createI18n was in a wrong structure. And the real message is got one level deep. So a working example will be t("default.message"). The comparison:

Before:

{
  "en": {
    "default": {}
  }
}

After:

{
  "en": {}
}

Complete code comparison generated by vue add i18n

Before:

import { createI18n } from 'vue-i18n'

/**
 * Load locale messages
 * 
 * The loaded `JSON` locale messages is pre-compiled by `@intlify/vue-i18n-loader`, which is integrated into `vue-cli-plugin-i18n`.
 * See: https://github.com/intlify/vue-i18n-loader#rocket-i18n-resource-pre-compilation
 */
function loadLocaleMessages() {
  const locales = require.context('./locales', true, /[A-Za-z0-9-_,\s]+\.json$/i)
  const messages = {}
  locales.keys().forEach(key => {
    const matched = key.match(/([A-Za-z0-9-_]+)\./i)
    if (matched && matched.length > 1) {
      const locale = matched[1]
      messages[locale] = locales(key).default
    }
  })
  return messages
}

export default createI18n({
  locale: process.env.VUE_APP_I18N_LOCALE || 'en',
  fallbackLocale: process.env.VUE_APP_I18N_FALLBACK_LOCALE || 'en',
  messages: loadLocaleMessages()
})

After:

import { createI18n } from 'vue-i18n'

/**
 * Load locale messages
 * 
 * The loaded `JSON` locale messages is pre-compiled by `@intlify/vue-i18n-loader`, which is integrated into `vue-cli-plugin-i18n`.
 * See: https://github.com/intlify/vue-i18n-loader#rocket-i18n-resource-pre-compilation
 */
function loadLocaleMessages() {
  const locales = require.context('./locales', true, /[A-Za-z0-9-_,\s]+\.json$/i)
  const messages = {}
  locales.keys().forEach(key => {
    const matched = key.match(/([A-Za-z0-9-_]+)\./i)
    if (matched && matched.length > 1) {
      const locale = matched[1]
      messages[locale] = locales(key)
    }
  })
  return messages
}

export default createI18n({
  legacy: false,
  locale: process.env.VUE_APP_I18N_LOCALE || 'en',
  fallbackLocale: process.env.VUE_APP_I18N_FALLBACK_LOCALE || 'en',
  messages: loadLocaleMessages()
})

QzCurious avatar Jun 04 '21 02:06 QzCurious