Added typescript to workspace devdeps, removed no unused var rules from

tsconfig, made i18n not use top-level await, upgraded packages/made sure
they were on compatible versions
This commit is contained in:
Benjamin Singleton 2026-04-17 20:18:41 -05:00
parent 20a1b867f5
commit 2c63701152
7 changed files with 591 additions and 389 deletions

View file

@ -13,6 +13,7 @@ import vpVlFtlSrc from "@/assets/locale/vp_VL.ftl";
import wpVlFtlSrc from "@/assets/locale/wp_VL.ftl";
import type { FluentBundle } from "@fluent/bundle";
import { compileLocale } from "@/vi18n-lib/compile";
import type { ComputedRef } from "vue";
export const LOCALE_IDS = ["en-US", "vp-VL", "wp-VL"] as const;
@ -143,42 +144,71 @@ function deepReadonly<T>(value: T): DeepReadonly<T> {
return value as DeepReadonly<T>;
}
const DEFAULT_LOCALE_BUNDLE = unwrap(await loadLocale("en-US", enUsFtlSrc));
const DEFAULT_LOCALE = unwrap(
setupLocale(DEFAULT_LOCALE_ID, DEFAULT_LOCALE_BUNDLE, undefined),
);
interface I18n {
useLocale: (opt?: UseLocaleOptions) => ComputedRef<DeepReadonly<Locale>>;
}
const doItAllForLocale = async (
localeId: LocaleId,
localeFtlSrc: string,
): Promise<DeepReadonly<Locale>> =>
deepReadonly(
unwrap(
setupLocale(
localeId,
unwrap(await loadLocale(localeId, localeFtlSrc)),
{ bundle: DEFAULT_LOCALE_BUNDLE, locale: DEFAULT_LOCALE },
),
),
async function initI18n(): Promise<I18n> {
const defaultLocaleBundle = unwrap(await loadLocale("en-US", enUsFtlSrc));
const defaultLocale = unwrap(
setupLocale(DEFAULT_LOCALE_ID, defaultLocaleBundle, undefined),
);
const [vpVl, wpVl] = await Promise.all([
doItAllForLocale("vp-VL", vpVlFtlSrc),
doItAllForLocale("wp-VL", wpVlFtlSrc),
]);
const doItAllForLocale = async (
localeId: LocaleId,
localeFtlSrc: string,
): Promise<DeepReadonly<Locale>> =>
deepReadonly(
unwrap(
setupLocale(
localeId,
unwrap(await loadLocale(localeId, localeFtlSrc)),
{ bundle: defaultLocaleBundle, locale: defaultLocale },
),
),
);
const localeIdToLocale = {
"en-US": deepReadonly(DEFAULT_LOCALE),
"vp-VL": vpVl,
"wp-VL": wpVl,
} as const satisfies Record<LocaleId, DeepReadonly<Locale>>;
const [vpVl, wpVl] = await Promise.all([
doItAllForLocale("vp-VL", vpVlFtlSrc),
doItAllForLocale("wp-VL", wpVlFtlSrc),
]);
const localeIdToLocale = {
"en-US": deepReadonly(defaultLocale),
"vp-VL": vpVl,
"wp-VL": wpVl,
} as const satisfies Record<LocaleId, DeepReadonly<Locale>>;
const useLocale = (opt: UseLocaleOptions = {}) =>
computed<DeepReadonly<Locale>>(() => {
const localLocaleId = opt.locale ?? localeId.value;
return localeIdToLocale[localLocaleId];
});
return { useLocale };
}
export interface UseLocaleOptions {
locale?: LocaleId;
}
export const useLocale = (opt: UseLocaleOptions = {}) =>
computed<DeepReadonly<Locale>>(() => {
const localLocaleId = opt.locale ?? localeId.value;
return localeIdToLocale[localLocaleId];
});
const initI18nPromise = initI18n();
let i18n: I18n | null = null;
initI18nPromise.then((x) => {
i18n = x;
});
export const onI18nInit = (f: () => void) => {
initI18nPromise.then(f);
};
export const useLocale = (
opt: UseLocaleOptions = {},
): ComputedRef<DeepReadonly<Locale>> => {
if (i18n === null) {
throw new Error("Cannot use i18n before initialized!");
}
return i18n.useLocale(opt);
};

View file

@ -1,5 +1,8 @@
import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";
import { onI18nInit } from "./i18n";
createApp(App).use(router).mount("#app");
onI18nInit(() => {
createApp(App).use(router).mount("#app");
});

View file

@ -1,10 +1,15 @@
/* eslint-disable */
/* prettier-ignore */
// @ts-nocheck
// Generated by unplugin-vue-router. ‼️ DO NOT MODIFY THIS FILE ‼️
// noinspection ES6UnusedImports
// Generated by unplugin-vue-router. !! DO NOT MODIFY THIS FILE !!
// It's recommended to commit this file.
// Make sure to add this file to your tsconfig.json file as an "includes" or "files" entry.
declare module 'vue-router/auto-resolver' {
export type ParamParserCustom = never
}
declare module 'vue-router/auto-routes' {
import type {
RouteRecordInfo,
@ -18,9 +23,81 @@ declare module 'vue-router/auto-routes' {
* Route name map generated by unplugin-vue-router
*/
export interface RouteNamedMap {
'/': RouteRecordInfo<'/', '/', Record<never, never>, Record<never, never>>,
'/discord/rules': RouteRecordInfo<'/discord/rules', '/discord/rules', Record<never, never>, Record<never, never>>,
'/kotoba': RouteRecordInfo<'/kotoba', '/kotoba', Record<never, never>, Record<never, never>>,
'/resources': RouteRecordInfo<'/resources', '/resources', Record<never, never>, Record<never, never>>,
'/': RouteRecordInfo<
'/',
'/',
Record<never, never>,
Record<never, never>,
| never
>,
'/discord/rules': RouteRecordInfo<
'/discord/rules',
'/discord/rules',
Record<never, never>,
Record<never, never>,
| never
>,
'/kotoba': RouteRecordInfo<
'/kotoba',
'/kotoba',
Record<never, never>,
Record<never, never>,
| never
>,
'/resources': RouteRecordInfo<
'/resources',
'/resources',
Record<never, never>,
Record<never, never>,
| never
>,
}
/**
* Route file to route info map by unplugin-vue-router.
* Used by the \`sfc-typed-router\` Volar plugin to automatically type \`useRoute()\`.
*
* Each key is a file path relative to the project root with 2 properties:
* - routes: union of route names of the possible routes when in this page (passed to useRoute<...>())
* - views: names of nested views (can be passed to <RouterView name="...">)
*
* @internal
*/
export interface _RouteFileInfoMap {
'pages/index.vue': {
routes:
| '/'
views:
| never
}
'pages/discord/rules.vue': {
routes:
| '/discord/rules'
views:
| never
}
'pages/kotoba.vue': {
routes:
| '/kotoba'
views:
| never
}
'pages/resources.vue': {
routes:
| '/resources'
views:
| never
}
}
/**
* Get a union of possible route names in a certain route component file.
* Used by the \`sfc-typed-router\` Volar plugin to automatically type \`useRoute()\`.
*
* @internal
*/
export type _RouteNamesForFilePath<FilePath extends string> =
_RouteFileInfoMap extends Record<FilePath, infer Info>
? Info['routes']
: keyof RouteNamedMap
}