mirror of
https://github.com/bookorbit/bookorbit.git
synced 2026-11-03 00:11:37 -06:00
feat(i18n): add multi-language support with Dutch translation (#500)
* feat(i18n): add vue-i18n foundation with language switcher and Dutch locale Introduce multi-language support for the client using vue-i18n and @intlify/unplugin-vue-i18n. Locale is detected from a stored preference or the browser language and persisted client-first, with optional server sync riding the existing theme-sync mechanism (new locale category on the generic user_preferences store, no migration needed). Adds a language selector in Appearance > Behavior settings and seeds en/nl message catalogs. Extraction of existing hardcoded strings follows in subsequent commits. * feat(i18n): add full en/nl message catalogs and test/build wiring Populate the English and Dutch message catalogs (~4300 keys) covering the whole UI, register a vitest setup that installs vue-i18n globally so component tests resolve real messages, and allow inline HTML in messages (strictMessage/escapeHtml off) for notes rendered via v-html / <i18n-t>. * feat(i18n): localize settings and book UI strings Replace hardcoded strings with t() calls across the settings and book feature areas (including book detail, table, metadata edit, reading log, highlights). Label collections captured at setup are wrapped in computed() so they react to locale changes. * feat(i18n): localize remaining feature UI strings Replace hardcoded strings with t() across reader, email, library, tools, migration, dashboard, auth, hardcover, author, series, book-dock, book-metadata-fetch, annotations, admin, statistics, collection, smart-scope, audit, whats-new, achievements, notifications, custom-icons, scanner and metadata-score. Reactive label maps use computed(). * feat(i18n): localize shared components and view wrappers Replace hardcoded strings with t() across shared components (app header, sidebar, view header, pickers, selection bar) and top-level views. * feat(i18n): localize settings tab bars and browser page titles Make settings tab labels reactive via t() in the consuming components and slim the *-tabs.ts helpers to ids/order/permission only. Route the browser page titles in the router through the app i18n instance so document.title follows the active locale. Adds settings.<area>.tabs.* and titles.* keys. * feat(i18n): localize KOReader hash-linking and reader sidebar pin Localize the strings from the KOReader manual hash-linking feature and the reader sidebar pin/close controls that were merged from main during the rebase, adding the corresponding en/nl keys. * feat(i18n): localize upstream features merged during rebase onto main Add en/nl catalog keys for the new upstream functionality pulled in by the rebase (Kobo activity log, KOReader dismiss/remove-device and hash-link modal, default library access, upload-size settings) and update a few existing keys whose wording changed upstream (dynamic upload-size hints, write-and-rename phrasing). * feat(i18n): switch language picker to a dropdown Replace the segmented language buttons with a native select, which scales better as more locales are added. * feat(i18n): add German and Slovenian translations Register de and sl in the supported locales and ship full de.json and sl.json catalogs (4616 keys each, structural parity with en.json). * fix(client): harden locale switching and translation coverage Keep locale catalogs structurally aligned, localize rebased UI changes, and use locale-aware formatting. Move language selection into the header, persist authenticated preferences, and prevent stale locale loads from winning. --------- Co-authored-by: neon <18559658+neonsolstice@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
f68a3ca98e
commit
31bda18c9a
@@ -2,6 +2,7 @@ export * from "./audit";
|
||||
export * from "./auth";
|
||||
export * from "./theme";
|
||||
export * from "./display-preferences";
|
||||
export * from "./locale";
|
||||
export * from "./permissions";
|
||||
export * from "./content-filter";
|
||||
export * from "./metadata-preferences";
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
export const SUPPORTED_LOCALES = ["en", "de", "nl", "sl"] as const;
|
||||
export type Locale = (typeof SUPPORTED_LOCALES)[number];
|
||||
|
||||
export const DEFAULT_LOCALE: Locale = "en";
|
||||
|
||||
/** Native display names for each supported locale, shown in the language picker. */
|
||||
export const LOCALE_LABELS: Record<Locale, string> = {
|
||||
en: "English",
|
||||
de: "Deutsch",
|
||||
nl: "Nederlands",
|
||||
sl: "Slovenščina",
|
||||
};
|
||||
|
||||
export const LOCALE_DIRECTIONS: Record<Locale, "ltr" | "rtl"> = {
|
||||
en: "ltr",
|
||||
de: "ltr",
|
||||
nl: "ltr",
|
||||
sl: "ltr",
|
||||
};
|
||||
|
||||
export interface LocalePreferences {
|
||||
locale: Locale;
|
||||
}
|
||||
|
||||
export function isSupportedLocale(value: unknown): value is Locale {
|
||||
return typeof value === "string" && (SUPPORTED_LOCALES as readonly string[]).includes(value);
|
||||
}
|
||||
Reference in New Issue
Block a user