intlify / vue-cli-plugin-i18n

:globe_with_meridians: Vue CLI plugin to add vue-i18n to your Vue Project

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Default Locale Messages

codetheorist opened this issue · 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.

Thank you for your reporting!

@pixari
Could you help this issue?

commented

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()
})