intlify / bundle-tools

bundling for intlify i18n tools
MIT License
244 stars 37 forks source link

vite build ends up with "[intlify] Not found '...' key in '...' locale messages." #147

Open Vectrex opened 2 years ago

Vectrex commented 2 years ago

Setting up vite with vite-plugin-vue-i18n according to the documentation followed by npm run dev and navigating to localhost:<port> Will always display "message" and the console tells me

[intlify] Not found 'message' key in 'ja' locale messages.
[intlify] Fall back to translate 'message' key with 'en' locale.
[intlify] Not found 'message' key in 'en' locale messages.

Both in a "full-scale" application and the minimal example below.

Expected behavior

Localized message string.

Reproduction

package.json

{
  "name": "my-project",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "serve": "vite preview"
  },
  "dependencies": {
    "@heroicons/vue": "^1.0.6",
    "@tailwindcss/forms": "^0.5.2",
    "tailwindcss": "^3.0.24",
    "vue": "^3.2.37",
    "vue-i18n": "^9.1.10"
  },
  "devDependencies": {
    "@intlify/vite-plugin-vue-i18n": "^5.0.0",
    "@vitejs/plugin-vue": "^3.0.0",
    "@vue/cli-service": "^5.0.8",
    "@vue/compiler-sfc": "^3.2.37",
    "autoprefixer": "^10.4.7",
    "postcss": "^8.4.14",
    "vite": "3.0.0",
    "vue-router": "^4.1.2"
  }
}

vite.config.js

import { fileURLToPath, URL } from 'url'
const { defineConfig } = require('vite')
import vue from '@vitejs/plugin-vue'
import vueI18n from '@intlify/vite-plugin-vue-i18n'

export default defineConfig({
  plugins: [
      vue(),
      vueI18n({
        // if you want to use Vue I18n Legacy API, you need to set `compositionOnly: false`
        // compositionOnly: false,
        // include: path.resolve(__dirname, './path/to/src/locales/**')
      })
  ],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
    }
  },
})

index.js

import './index.css'
import { createApp } from 'vue'
import { createI18n } from 'vue-i18n'
import App from './App.vue'

const messages = {
    en: {
        message: {
            hello: 'hello world'
        }
    },
    ja: {
        message: {
            hello: 'こんにちは、世界'
        }
    }
}

const i18n = createI18n({
    globalInjection: true,
    locale: 'ja',
    fallbackLocale: 'en',
    messages,
})

const app = createApp(App);
app.use(i18n).mount('#app');

App.vue

<script setup>
</script>

<template>
  <div class="flex justify-center text-3xl py-16">{{ $t('message') }}</div>
</template>

<script>
export default {}
</script>

Issue Package

vite-plugin-vue-i18n

System Info

System:
    OS: Linux 5.15 Ubuntu 22.04 LTS 22.04 LTS (Jammy Jellyfish)
    CPU: (16) x64 AMD Ryzen 7 PRO 4750U with Radeon Graphics
    Memory: 11.71 GB / 14.86 GB
    Container: Yes
    Shell: 5.1.16 - /bin/bash
  Binaries:
    Node: 18.6.0 - /usr/bin/node
    npm: 8.14.0 - /usr/bin/npm
  Browsers:
    Chromium: 103.0.5060.53
    Firefox: 102.0.1
  npmPackages:
    @intlify/vite-plugin-vue-i18n: ^5.0.0 => 5.0.0 
    vite: 3.0.0 => 3.0.0 
    vue: ^3.2.37 => 3.2.37 
    vue-i18n: ^9.1.10 => 9.1.10

Screenshot

No response

Additional context

No response

Validations

Vectrex commented 2 years ago

Fixed it (partially): The example here https://vue-i18n.intlify.dev/guide/#html is erroneous. It has to be

const messages = {
    en: {
        hello: 'hello world'
    },
    ja: {
        hello: 'こんにちは、世界'
    },
    de: {
        hello: 'hi!'
    },
}

/*
doesn't work

const messages = {
    en: {
        message: {
            hello: 'hello world'
        }
    },
    ja: {
        message: {
            hello: 'こんにちは、世界'
        }
    },
    de: {
        message: {
            hello: 'hi!'
        }
    }
}
*/

const i18n = createI18n({
    globalInjection: true,
    locale: 'ja',
    fallbackLocale: 'en',
    legacy: false,
    messages
})

However, the i18n section in an SFC is still ignored:

App.vue

<template>
  <div class="flex justify-center text-3xl py-16">{{ $t('hello') }}</div>
</template>

<script>
export default {}
</script>

<i18n>
{
  "de": {
    "hello": "foo"
  },
  "en": {
    "hello": "bar"
  },
  "ja": {
    "hello": "baz"
  }
}
</i18n>

Results in こんにちは、世界 on the screen From my understanding the SFC configuration should always override the global setting. Upon removing the messages obiect in the index.js We are back to

[intlify] Not found 'hello' key in 'ja' locale messages.

UI-Mario commented 2 years ago

I haven't tried mixing global and custom blocks, but using only custom blocks is ok for me. https://github.com/intlify/bundle-tools/issues/120#issuecomment-1257126108

kburda commented 1 year ago

I changed 2 things to get rid of this error: 1.Use locale instead of inheritLocale in the options object. navigator.language seems to be good solution to get users agent language.

app.js

 
let userLocale = 'en'
if (navigator.language === 'pl') {
  userLocale = 'pl'
}
const i18n = createI18n({
  legacy: 'composition',
  inheritLocale: true,// must be removed
  globalInjection: true,
  locale: userLocale,// manually set locale
  messages: {
    en: en,
    pl: pl,
  }
})
  1. Do not use auto-resolving in the vite.config.js.

vite.config.js

    vueI18n({
      // This line must be removed.
      include: resolve(dirname(fileURLToPath(import.meta.url)), 'resources/js/locale/**'),
    }),
folmert commented 8 months ago

What if I don't have messages beforehand and get them from API?