feat(client): display list of languages

This commit is contained in:
Elian Doran 2025-03-04 17:43:24 +02:00
parent fd652ea7a5
commit 5b4d323936
No known key found for this signature in database
4 changed files with 42 additions and 11 deletions

View File

@ -1,10 +1,21 @@
import options from "./options.js";
import i18next from "i18next";
import i18nextHttpBackend from "i18next-http-backend";
import server from "./server.js";
let locales: Locale[] | null;
// TODO: Deduplicate with server.
export interface Locale {
id: string;
name: string;
}
export async function initLocale() {
const locale = (options.get("locale") as string) || "en";
locales = await server.get<Locale[]>("options/locales");
await i18next.use(i18nextHttpBackend).init({
lng: locale,
fallbackLng: "en",
@ -15,5 +26,13 @@ export async function initLocale() {
});
}
export function getAvailableLocales() {
if (!locales) {
throw new Error("Tried to load list of locales, but localization is not yet initialized.");
}
return locales;
}
export const t = i18next.t;
export const getCurrentLanguage = () => i18next.language;

View File

@ -1,5 +1,6 @@
import { Dropdown } from "bootstrap";
import NoteContextAwareWidget from "./note_context_aware_widget.js";
import { getAvailableLocales, type Locale } from "../services/i18n.js";
const TPL = `\
<div class="dropdown note-language-widget">
@ -21,10 +22,28 @@ export default class NoteLanguageWidget extends NoteContextAwareWidget {
doRender() {
this.$widget = $(TPL);
this.dropdown = Dropdown.getOrCreateInstance(this.$widget.find("[data-bs-toggle='dropdown']")[0]);
this.$widget.on("show.bs.dropdown", () => this.renderDropdown());
this.$noteLanguageDropdown = this.$widget.find(".note-language-dropdown")
this.$noteLanguageButton = this.$widget.find(".note-language-button");
this.$noteLanguageDesc = this.$widget.find(".note-language-desc");
}
renderDropdown() {
this.$noteLanguageDropdown.empty();
if (!this.note) {
return;
}
for (const locale of getAvailableLocales()) {
const $title = $("<span>").text(locale.name);
const $link = $('<a class="dropdown-item">')
.attr("data-language", locale.id)
.append('<span class="check">&check;</span> ')
.append($title);
this.$noteLanguageDropdown.append($link);
}
}
}

View File

@ -1,7 +1,7 @@
import OptionsWidget from "../options_widget.js";
import server from "../../../../services/server.js";
import utils from "../../../../services/utils.js";
import { t } from "../../../../services/i18n.js";
import { getAvailableLocales, t, type Locale } from "../../../../services/i18n.js";
import type { OptionMap } from "../../../../../../services/options_interface.js";
const TPL = `
@ -25,12 +25,6 @@ const TPL = `
</div>
`;
// TODO: Deduplicate with server.
export interface Locale {
id: string;
name: string;
}
export default class LocalizationOptions extends OptionsWidget {
private $localeSelect!: JQuery<HTMLElement>;
@ -53,7 +47,7 @@ export default class LocalizationOptions extends OptionsWidget {
}
async optionsLoaded(options: OptionMap) {
const availableLocales = await server.get<Locale[]>("options/locales");
const availableLocales = getAvailableLocales();
this.$localeSelect.empty();
for (const locale of availableLocales) {

View File

@ -1,7 +1,6 @@
import OptionsWidget from "../options_widget.js";
import type { OptionMap } from "../../../../../../services/options_interface.js";
import server from "../../../../services/server.js";
import type { Locale } from "../appearance/i18n.js";
import { getAvailableLocales } from "../../../../services/i18n.js";
const TPL = `
<div class="options-section">
@ -42,7 +41,7 @@ export default class LanguageOptions extends OptionsWidget {
}
async optionsLoaded(options: OptionMap) {
const availableLocales = await server.get<Locale[]>("options/locales");
const availableLocales = getAvailableLocales();
const enabledLanguages = (JSON.parse(options.languages) as string[]);
this.$languagesContainer.empty();