PronounsPage/plugins/globals.ts
Valentyne Stigloher 61ecf5025d (ts) migrate
2024-06-26 13:57:06 +02:00

159 lines
5.7 KiB
TypeScript

import Vue from 'vue';
import type { Plugin } from '@nuxt/types';
import { Translator } from '../src/translator.ts';
import { buildDict } from '../src/helpers.ts';
import { DateTime, Settings } from 'luxon';
import { decodeTime } from 'ulid';
import type { Pronoun } from '../src/classes.ts';
import type { LocaleDescription } from '../locale/locales.ts';
import translations from '../data/translations.suml';
import baseTranslations from '../locale/_base/translations.suml';
import { LoadScriptError } from '../src/errors.ts';
import type { Config } from '../locale/config.ts';
import buildLocaleList from '../src/buildLocaleList.ts';
declare global {
interface Window {
fusetag: any;
}
}
declare module '@nuxt/types/config/runtime' {
interface NuxtRuntimeConfig extends Config { }
}
declare module 'vue/types/vue' {
interface Vue {
$eventHub: Vue;
$base: string;
$translator: Translator;
$t(key: string, params?: Record<string, string>, warn?: boolean): string;
$te(key: string, fallback?: boolean): boolean;
$translateForPronoun(str: string, pronoun: Pronoun | null): string;
$locales: Record<string, LocaleDescription>;
$loadScript(name: string, src: string, nonce?: string): Promise<unknown>;
$loadStylesheet(name: string, src: string): Promise<unknown>;
}
}
const plugin: Plugin = ({ app, store }, inject) => {
inject('eventHub', new Vue());
inject('base', process.env.BASE_URL);
const translator = new Translator(translations, baseTranslations, app.$config);
inject('translator', translator);
inject('t', (key: string, params = {}, warn = false): string => translator.translate(key, params, warn));
inject('te', (key: string, fallback = false): boolean => {
if (translator.has(key)) {
return true;
}
if (fallback && translator.hasFallback(key)) {
return true;
}
return false;
});
inject('translateForPronoun', (str: string, pronoun: Pronoun | null): string => {
let translation = translator.translate(`flags.${str.replace(/ /g, '_').replace(/'/g, '*')}`, {}, false) || str;
if (pronoun) {
translation = pronoun.format(translation);
}
return translation;
});
inject('locales', buildDict(function* () {
const locales = buildLocaleList(app.$config.locale);
if (app.$config.locale !== '_') {
yield [app.$config.locale, locales[app.$config.locale]];
}
for (const [locale, localeDescription] of Object.entries(locales)) {
if (locale !== app.$config.locale) {
yield [locale, localeDescription];
}
}
}));
store.commit('setSpelling', app.$cookies.get('spelling'));
store.commit('restoreTranslations', app.$cookies.get('translations'));
if (app.$cookies.get('translationModeVisible')) {
store.commit('showTranslationMode');
}
inject('loadScript', (name: string, src: string, nonce: string | undefined = undefined): Promise<void> => {
if (!process.client || document.querySelectorAll(`script.${name}-script`).length > 0) {
return new Promise((resolve) => {
resolve();
});
}
return new Promise((resolve, reject) => {
const script = document.createElement('script');
script.setAttribute('src', src);
if (nonce) {
script.setAttribute('nonce', nonce);
}
script.classList.add(`${name}-script`);
// script.crossOrigin = 'true'; TODO proper fix (adding it breaks publift)
script.addEventListener('load', () => {
script.classList.add('loaded');
resolve();
});
script.addEventListener('error', (event) => {
reject(new LoadScriptError(name, src, typeof event === 'string' ? event : event.type));
});
document.body.appendChild(script);
});
});
inject('loadStylesheet', (name: string, src: string): Promise<void> => {
if (!process.client || document.querySelectorAll(`link.${name}-stylesheet`).length > 0) {
return new Promise((resolve) => {
resolve();
});
}
return new Promise((resolve, reject) => {
const link = document.createElement('link');
link.setAttribute('rel', 'stylesheet');
link.setAttribute('href', src);
link.classList.add(`${name}-stylesheet`);
link.crossOrigin = 'true';
link.addEventListener('load', () => resolve());
link.addEventListener('error', (event) => {
reject(new LoadScriptError(name, src, typeof event === 'string' ? event : event.type));
});
document.body.appendChild(link);
});
});
try {
Settings.defaultLocale = app.$config.intlLocale || app.$config.locale;
DateTime.now().toFormat('y-MM-dd HH:mm'); // test if locale is supported by luxon
} catch {
Settings.defaultLocale = 'en';
}
inject('datetime', (timestamp: number): string => {
const dt = DateTime.fromSeconds(timestamp);
return dt.toFormat('y-MM-dd HH:mm');
});
inject('date', (timestamp: number): string => {
const dt = DateTime.fromSeconds(timestamp);
return dt.toFormat('y-MM-dd');
});
inject('ulidTime', (ulid: string): number => {
return decodeTime(ulid) / 1000;
});
app.router?.afterEach(() => {
if (typeof window !== 'undefined' && window.fusetag && window.fusetag.pageInit) {
window.fusetag.pageInit();
}
});
};
export default plugin;