intlify / vue-i18n

Vue I18n for Vue 3
https://vue-i18n.intlify.dev/
MIT License
2.21k stars 338 forks source link

Foolproofing and trigger error, when locale is not set. #1788

Open hekep opened 7 months ago

hekep commented 7 months ago

Clear and concise description of the problem

Quasar 2.x In src/boot/i18n.js we have


import { boot } from "quasar/wrappers";

import { createI18n } from "vue-i18n";

// to check https://vue-i18n.intlify.dev/guide/advanced/lazy.html
// Create I18n instance
const i18n = createI18n({
    locale: "fi", // Default Language
    legacy: false, // comment this out if not using Composition API
    allowComposition: true, // https://vue-i18n.intlify.dev/guide/migration/vue3
    // messages,

    messages: {
        en-US: {
            isoName: "en-US",
            isoNative: "English (US)",
            "Select Client": "Select  English/ US Organisaatio",
            "Napoleon Demo": "en-us / index DEMO",
            "Select Language": "Select Language",
        },
        fi: {
            isoName: "fi",
            isoNative: "Suomi",
            "Select Client": "Valitse Organisaatio",
            "Napoleon Demo": " fi index DEMO",
            "Select Language": "Valitse kieli",
        }
    }

});

export default boot(({ app }) => {
    app.use(i18n); // this enables useI18n() later on
    app.config.globalProperties.$i18n = i18n;
    console.log('src boot i18n.js ,app.use(i18n)', app);
});

export { i18n };

in layouts/MainLayout.vue we have

<template>
<q-layout view="lHh Lpr lFf">
    <q-header elevated>

        <q-select
          v-model="locale"
          :options="localeOptions"
          :label="t('Select Language')"
          dense
          dark
          borderless
          emit-value
          map-options
          options-dense
          style="min-width: 150px"
        />

         </q-header>

         <q-page-container>
        <router-view />
        </q-page-container>

      </q-layout>
</template>  

<script setup>
import { useQuasar } from "quasar";
import { useI18n } from "vue-i18n";
import { i18n } from "boot/i18n";

const $q = useQuasar();

const { t, locale } = useI18n();

const localeOptions = [
  { value: "fi", label: "Finnish" },
  { value: "en-US", label: "English" },
];

watch(locale, (val) => {
    i18n.global.locale.value = val;

  // dynamic import, so loading on demand only
  import(
    /* webpackInclude: /(fi|en-US)\.js$/ */
    "quasar/lang/" + val + ".js"
  ).then((locale) => {
    $q.lang.set(locale.default);

  });
});

Notice that the select box has en_US but there is no such locale. There is en-US.

Suggested solution

Error should be triggered when user tries to set invalid, unavailable locale.

Alternative

No response

Additional context

No response

Validations

BobbieGoede commented 7 months ago

Notice that the select box has en_US but there is no such locale. There is en-US.

I'm not sure where en_US is used in your example, if you want to make sure only existing locales are used you could use the availableLocales property to either limit the options or check if the selected option is included.

See the component example on this page of the docs: https://vue-i18n.intlify.dev/guide/essentials/scope.html#global-scope-1 for reference.

As for why it's possible to set the locale without it throwing an error, I'm not sure, perhaps there are use cases in which this would be fine? 😅

hekep commented 7 months ago

Notice that the select box has en_US but there is no such locale. There is en-US.

As for why it's possible to set the locale without it throwing an error, I'm not sure, perhaps there are use cases in which this would be fine? 😅

May be it is falling back to the first default language, right now I do not have 3 languages to test. It should at least write some console.log(...) or something.

aiktb commented 1 week ago

Notice that the select box has en_US but there is no such locale. There is en-US.

I'm not sure where en_US is used in your example, if you want to make sure only existing locales are used you could use the availableLocales property to either limit the options or check if the selected option is included.

See the component example on this page of the docs: https://vue-i18n.intlify.dev/guide/essentials/scope.html#global-scope-1 for reference.

As for why it's possible to set the locale without it throwing an error, I'm not sure, perhaps there are use cases in which this would be fine? 😅

I have a question, when options.locale in createI18n is obtained by browser language detection, how can I dynamically import the correct locale file?

For example:

export const SUPPORT_LOCALES = ["en", "ja", "cn"] as const;
export type SupportLocale = typeof SUPPORT_LOCALES[number];

async function loadLocaleMessages(i18n: I18n, locale: SupportLocale) {
  const messages = await import(
    `~/assets/_locales/${locale}.json`
  );

  i18n.global.setLocaleMessage(locale, messages.default);

  return nextTick();
}

I get the browser language setting through chrome.i18n.getUILanguage(), it returns en-US, which does not match any language translation file, but I want to load en.json.