OpenDTU/webapp/src/i18n.ts
2024-10-21 20:15:56 +02:00

146 lines
3.7 KiB
TypeScript

import { createI18n } from 'vue-i18n';
import messages from '@intlify/unplugin-vue-i18n/messages';
import type { I18nOptions, IntlDateTimeFormat, IntlNumberFormat } from 'vue-i18n';
export const allLocales = [
{ code: 'en', name: 'English' },
{ code: 'de', name: 'Deutsch' },
{ code: 'fr', name: 'Français' },
];
const dateTimeFormatsTemplate: IntlDateTimeFormat = {
datetime: {
hour: 'numeric',
minute: 'numeric',
second: 'numeric',
year: 'numeric',
month: 'numeric',
day: 'numeric',
hour12: false,
},
};
const numberFormatTemplate: IntlNumberFormat = {
decimal: {
style: 'decimal',
},
decimalNoDigits: {
style: 'decimal',
minimumFractionDigits: 0,
maximumFractionDigits: 0,
},
decimalOneDigit: {
style: 'decimal',
minimumFractionDigits: 1,
maximumFractionDigits: 1,
},
decimalTwoDigits: {
style: 'decimal',
minimumFractionDigits: 2,
maximumFractionDigits: 2,
},
percent: {
style: 'percent',
},
percentOneDigit: {
style: 'percent',
minimumFractionDigits: 1,
maximumFractionDigits: 1,
},
byte: {
style: 'unit',
unit: 'byte',
},
kilobyte: {
style: 'unit',
unit: 'kilobyte',
},
megabyte: {
style: 'unit',
unit: 'megabyte',
},
celsius: {
style: 'unit',
unit: 'celsius',
maximumFractionDigits: 1,
},
};
export const dateTimeFormats: I18nOptions['datetimeFormats'] = {};
export const numberFormats: I18nOptions['numberFormats'] = {};
allLocales.forEach((locale) => {
dateTimeFormats[locale.code] = dateTimeFormatsTemplate;
numberFormats[locale.code] = numberFormatTemplate;
});
export const i18n = createI18n({
legacy: false,
globalInjection: true,
locale: navigator.language.split('-')[0],
fallbackLocale: allLocales[0].code,
messages,
datetimeFormats: dateTimeFormats,
numberFormats: numberFormats,
});
const dynamicLocales = await loadAvailLocales();
allLocales.push(...dynamicLocales);
if (localStorage.getItem('locale')) {
setLocale(localStorage.getItem('locale') || 'en');
} else {
localStorage.setItem('locale', i18n.global.locale.value);
}
// Set new locale.
export async function setLocale(locale: string) {
// Load locale if not available yet.
if (!i18n.global.availableLocales.includes(locale)) {
const messages = await loadLocale(locale);
// fetch() error occurred.
if (messages === undefined) {
i18n.global.locale.value = allLocales[0].code;
return;
}
// Add locale.
i18n.global.setLocaleMessage(locale, messages.webapp);
i18n.global.setNumberFormat(locale, numberFormatTemplate);
i18n.global.setDateTimeFormat(locale, dateTimeFormatsTemplate);
}
// Set locale.
i18n.global.locale.value = locale;
localStorage.setItem('locale', i18n.global.locale.value);
}
// Fetch locale.
async function loadLocale(locale: string) {
return fetch(`/api/i18n/language?code=${locale}`)
.then((response) => {
if (response.ok) {
return response.json();
}
throw new Error('Something went wrong!');
})
.catch((error) => {
console.error(error);
});
}
// Fetch available locales
async function loadAvailLocales() {
return fetch('/api/i18n/languages')
.then((response) => {
if (response.ok) {
return response.json();
}
throw new Error('Something went wrong!');
})
.catch((error) => {
console.error(error);
});
}