ts: add i18n typing

This commit is contained in:
axolotle 2024-07-11 15:10:18 +02:00
parent 8bb2451e9c
commit 00fe9f42bc
3 changed files with 45 additions and 27 deletions

View file

@ -1,40 +1,42 @@
import { nextTick } from 'vue'
import store from '@/store'
import i18n from '@/i18n'
import supportedLocales from './supportedLocales'
import store from '@/store'
import { nextTick } from 'vue'
export let dateFnsLocale
import supportedLocales, {
isSupportedLocale,
type SupportedLocales,
} from '@/i18n/supportedLocales'
export let dateFnsLocale: any
/**
* Returns the first two supported locales that can be found in the `localStorage` or
* in the user browser settings.
*
* @return {string[]}
*/
function getDefaultLocales() {
const locale = store.getters.locale
const fallbackLocale = store.getters.fallbackLocale
const locale: SupportedLocales | null = store.getters.locale
const fallbackLocale: SupportedLocales | null = store.getters.fallbackLocale
if (locale && fallbackLocale) return [locale, fallbackLocale]
const navigatorLocales = navigator.languages || [navigator.language]
const defaultLocales = []
const supported = Object.keys(supportedLocales)
const defaultLocales: SupportedLocales[] = []
for (const locale of navigatorLocales) {
if (supported.includes(locale) && !defaultLocales.includes(locale)) {
if (isSupportedLocale(locale) && !defaultLocales.includes(locale)) {
defaultLocales.push(locale)
} else {
const lang = locale.split('-')[0]
if (supported.includes(lang) && !defaultLocales.includes(lang)) {
if (isSupportedLocale(lang) && !defaultLocales.includes(lang)) {
defaultLocales.push(lang)
}
}
if (defaultLocales.length === 2) break
}
return defaultLocales
return defaultLocales as [SupportedLocales, SupportedLocales]
}
export async function setI18nLocale(locale) {
export async function setI18nLocale(locale: SupportedLocales) {
if (!i18n.global.availableLocales.includes(locale)) {
await loadLocaleMessages(locale)
// also query/set the date-fns locale object for time translation
@ -47,22 +49,24 @@ export async function setI18nLocale(locale) {
}
if (i18n.mode === 'legacy') {
// @ts-ignore
i18n.global.locale = locale
} else {
i18n.global.locale.value = locale
}
document.querySelector('html').setAttribute('lang', locale)
document.querySelector('html')!.setAttribute('lang', locale)
// FIXME can't currently change document direction easily since bootstrap still doesn't handle rtl.
// document.dir = locale === 'ar' ? 'rtl' : 'ltr'
}
export async function setI18nFallbackLocale(locale) {
export async function setI18nFallbackLocale(locale: SupportedLocales) {
if (!i18n.global.availableLocales.includes(locale)) {
await loadLocaleMessages(locale)
}
if (i18n.mode === 'legacy') {
// @ts-ignore
i18n.global.fallbackLocale = [locale, 'en']
} else {
i18n.global.fallbackLocale.value = [locale, 'en']
@ -74,7 +78,7 @@ export async function setI18nFallbackLocale(locale) {
*
* @return {Promise<string>} Promise that resolve the given locale string
*/
export async function loadLocaleMessages(locale) {
export async function loadLocaleMessages(locale: SupportedLocales) {
// load locale messages with dynamic import
const messages = await import(`./locales/${locale}.json`)
@ -87,8 +91,8 @@ export async function loadLocaleMessages(locale) {
/**
* Loads a date-fns locale object
*/
async function loadDateFnsLocale(locale) {
const dateFnsLocaleName = supportedLocales[locale].dateFnsLocale || locale
async function loadDateFnsLocale(locale: SupportedLocales) {
const dateFnsLocaleName = supportedLocales[locale].dateFnsLocale ?? locale
dateFnsLocale = (
await import(`../../node_modules/date-fns/locale/${dateFnsLocaleName}.mjs`)
).default

View file

@ -4,7 +4,7 @@
// If a new locale or a new date-fns locale is added, add it to the supported
// locales list in `app/vue.config.js`
export default {
const supportedLocales = {
ar: {
name: 'عربي',
},
@ -137,4 +137,21 @@ export default {
name: '简化字',
dateFnsLocale: 'zh-CN',
},
} as const
type SL = typeof supportedLocales
export type SupportedLocales = keyof SL
export type SupportedDateFnsLocales = keyof {
[k in SupportedLocales as SL[k] extends { dateFnsLocale: string }
? SL[k]['dateFnsLocale']
: k]: never
}
export function isSupportedLocale(locale: string): locale is SupportedLocales {
return Object.keys(supportedLocales).includes(locale)
}
export default supportedLocales as Record<
SupportedLocales,
{ name: string; dateFnsLocale?: SupportedDateFnsLocales }
>

View file

@ -15,7 +15,6 @@ export default {
dark: localStorage.getItem('dark') === 'true',
experimental: localStorage.getItem('experimental') === 'true',
spinner: 'pacman',
supportedLocales,
},
mutations: {
@ -85,12 +84,10 @@ export default {
experimental: (state) => state.experimental,
spinner: (state) => state.spinner,
availableLocales: (state) => {
return Object.entries(state.supportedLocales).map(
([locale, { name }]) => {
availableLocales: () => {
return Object.entries(supportedLocales).map(([locale, { name }]) => {
return { value: locale, text: name }
},
)
})
},
},
}