import Polyglot from 'node-polyglot' import { App, computed, reactive } from 'vue' import { has } from '@/utilities' import { range } from 'lodash' import { parseISO } from 'date-fns' const STORAGE_KEY = 'aura:locale' const DEFAULT_LOCALE = localStorage.getItem(STORAGE_KEY) ?? import.meta.env.VUE_APP_DEFAULT_LOCALE ?? 'de' const locales = Object.fromEntries( Object.entries(import.meta.glob('./??.js', { import: 'default', eager: true })).map( ([key, locale]) => [(/([a-z]+)?.[jt]s$/.exec(key) as string[])[1], locale], ), ) function createPolyglot(locale: string) { return new Polyglot({ phrases: locales[locale] }) } const state = reactive({ locale: DEFAULT_LOCALE, polyglot: createPolyglot(DEFAULT_LOCALE), }) const locale = computed({ get() { return state.locale }, set(newLocale) { updateLocale(newLocale) }, }) const availableLocales = computed(() => Object.keys(locales)) function t(phrase: string, context = {}): string { return state.polyglot.t(phrase, context) } // IMHO this is not the best naming for this function, but it is consistent // with the vue-i18n library that most people working on vue applications // will be familiar with. function te(phrase: string): boolean { return state.polyglot.has(phrase) } function updateLocale(newLocale: string): void { if (has(locales, newLocale)) { state.locale = newLocale state.polyglot = createPolyglot(newLocale) localStorage.setItem(STORAGE_KEY, newLocale) } else { throw new Error(`Unknown locale code for language: ${newLocale}`) } } export function getLanguageName(languageCode: string) { return new Intl.DisplayNames([languageCode], { type: 'language' }).of(languageCode) } /** * Returns a list of weekday names starting on monday. * @param locale string */ export function getDayNames(locale: string) { return range(7).map((i) => // January, 1st 2018 is a monday parseISO(`2018-01-0${i + 1}`).toLocaleString(locale, { weekday: 'long' }), ) } export function getMonthNames(locale: string) { return range(12).map((i) => parseISO(`2018-${(i + 1).toString().padStart(2, '0')}-01`).toLocaleString(locale, { month: 'long', }), ) } const dayNames = computed(() => getDayNames(locale.value)) const monthNames = computed(() => getMonthNames(locale.value)) export function useI18n() { // This interface is intentionally similar to the one provided by // Vue I18n to make it easier for newcomers already familiar with it // and to ease a potential future migration. // See https://vue-i18n.intlify.dev/guide/advanced/composition.html#basic-usage return { t, te, locale, dayNames, monthNames, availableLocales, } } export const TranslationPlugin = { install(app: App) { app.config.globalProperties.$activeLocale = () => locale.value app.config.globalProperties.$locale = updateLocale app.config.globalProperties.$t = t app.config.globalProperties.$te = te }, }