Search code examples
vue.jsvuejs2vue-i18n

vue-i18n: Wrong date format for e.g. Norwegian


I'm using vue-i18n (version 8.24.2) in my app, and everything works as expected except when rendering dates using locale = nb-NO (Norwegian). Expected format: dd.MM.yyyy. Actual format: MM/dd/yyyy. When switching locale to German, which is using the same date format as Norwegian, correct date format is applied.

This open issue would probably solve my issue: https://github.com/kazupon/vue-i18n/issues/625

I've spent a couple of hours investigating this issue, but I'm currently stuck, hence any help will be highly appreciated.

My i18n.ts (I left out config for languages not related to this issue)

import Vue from "vue";
import VueI18n from "vue-i18n";

enum Locales {
    NO = "nb-NO"
}

const LOCALES = [
    { value: Locales.NO, caption: "Norsk" }
];

import nb_NO from "./locales/nb-NO.json";

export const messages = {
    [Locales.NO]: nb_NO
};

const defaultLocale = Locales.NO;

const dateTimeFormats = {
    "nb-NO": {
        short: {
            year: "numeric",
            month: "2-digit",
            day: "2-digit",
        },
        long: {
            year: "numeric",
            month: "2-digit",
            day: "2-digit",
            hour: "2-digit",
            minute: "2-digit",
            hour12: false,
        },
    },
} as VueI18n.DateTimeFormats;

Vue.use(VueI18n);

// Create VueI18n instance with options
const i18n = new VueI18n({
    locale: navigator.language.split('-')[0] || process.env.VUE_APP_I18N_LOCALE || defaultLocale,
    fallbackLocale: defaultLocale,
    messages,
    dateTimeFormats: dateTimeFormats,
    silentTranslationWarn: true,
});

const translate = (key: string): string => {
    if (!key) {
        return "";
    }
    return i18n.t(key) as string;
};

export { i18n, translate }; //export above method

Solution

  • vue-i18n simply forwards the date localization to Intl.DateTimeFormat(locale).format(date).

    It seems the result is only incorrect in Chrome as of v92 (Issue 1233509). This bug is fixed in Chrome Canary v94.

    As a workaround, you can modify the vue-i18n instance's _dateTimeFormatters to use the Danish (da) locale's formatter for nb-NO:

    const i18n = new VueI18n({/*...*/});
    i18n._dateTimeFormatters[Locales.NO + '__short'] =
      new Intl.DateTimeFormat('da', dateTimeFormats[Locales.NO].short);
    i18n._dateTimeFormatters[Locales.NO + '__long'] =
      new Intl.DateTimeFormat('da', dateTimeFormats[Locales.NO].long);
    

    demo