Skip to content
Snippets Groups Projects
index.ts 2.91 KiB
Newer Older
  • Learn to ignore specific revisions
  • 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,
    
        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