v0.2.26
RustBox CI / rustbox (push) Canceled after 0s

This commit is contained in:
Mateusz Gruszczyński committed 2026-11-05 14:03:43 +01:00
1 parent 99ee3385ac
commit 53f4812adc
14 files changed
+730 -192

No files matched your search

+47 -8
View File
@@ -299,7 +299,46 @@ function tr(key, fallback = key) {
}
function trText(text) {
return state.translations?._text?.[text] || text;
const source = String(text ?? "");
const map = state.translations?._text || {};
if (map[source]) return map[source];
if (!source || !Object.keys(map).length) return source;
if (trText._map !== map) {
trText._map = map;
trText._templates = Object.entries(map)
.filter(([template]) => /\{\w+\}/.test(template))
.map(([template, translated]) => {
const names = [];
const pattern = template
.split(/(\{\w+\})/g)
.filter(Boolean)
.map((part) => {
const match = /^\{(\w+)\}$/.exec(part);
if (match) { names.push(match[1]); return "(.+?)"; }
return part.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
})
.join("");
return {
regex: new RegExp(`^${pattern}$`, "s"),
names,
translated,
staticLength: template.replace(/\{\w+\}/g, "").length,
};
})
.sort((a, b) => b.staticLength - a.staticLength);
}
for (const entry of trText._templates || []) {
const match = entry.regex.exec(source);
if (!match) continue;
let translated = entry.translated;
entry.names.forEach((name, index) => { translated = translated.replaceAll(`{${name}}`, match[index + 1]); });
return translated;
}
return source;
}
function fmtText(template, values = {}) {
return trText(template).replace(/\{(\w+)\}/g, (_, key) => String(values[key] ?? ""));
}
function applyPreferences() {
@@ -612,7 +651,7 @@ async function reconcileImapLabels() {
return;
}
if (button) button.disabled = true;
if (status) status.textContent = "Reconciling…";
if (status) status.textContent = trText("Reconciling…");
try {
const result = await request("/tags/reconcile", { method: "POST", body: "{}" });
const added = Number(result.labels_added || 0);
@@ -934,7 +973,7 @@ async function loadAuthPolicy() {
});
["#login-remember-label", "#add-account-remember-label"].forEach((selector) => {
const label = $(selector);
if (label) label.textContent = "Keep me signed in";
if (label) label.textContent = trText("Keep me signed in");
});
}
@@ -1029,7 +1068,7 @@ function renderAccountNotificationSettings() {
saveNotificationAccountSelection();
if (input.checked && typeof loadNotificationPreferencesForAccount === "function") void loadNotificationPreferencesForAccount(account.id);
});
label.append(input, el("span", "", "Notify"));
label.append(input, el("span", "", trText("Notify")));
row.append(details, label);
list.append(row);
}
@@ -1093,7 +1132,7 @@ function renderAccountSettings() {
? state.accounts
: state.accounts.filter((account) => account.id === state.accountId);
if (!accounts.length) {
list.append(el("div", "empty-list", "No active accounts."));
list.append(el("div", "empty-list", trText("No active accounts.")));
renderAccountSwitcher();
renderAccountNotificationSettings();
return;
@@ -1107,7 +1146,7 @@ function renderAccountSettings() {
use.addEventListener("click", () => switchAccount(account.id));
row.append(email, use);
if (multiAccountEnabled()) {
const remove = el("button", "button quiet danger", "Remove");
const remove = el("button", "button quiet danger", trText("Remove"));
remove.type = "button";
remove.addEventListener("click", () => removeBrowserAccount(account.id));
row.append(remove);
@@ -1121,13 +1160,13 @@ function renderAccountSettings() {
async function loadActiveSessions() {
const list = $("#account-session-list");
if (!list) return;
list.replaceChildren(el("div", "empty-list", "Loading sessions…"));
list.replaceChildren(el("div", "empty-list", trText("Loading sessions…")));
try {
const data = await request("/auth/sessions", { method: "GET" });
const sessions = data.sessions || [];
list.replaceChildren();
if (!sessions.length) {
list.append(el("div", "empty-list", "No active sessions."));
list.append(el("div", "empty-list", trText("No active sessions.")));
return;
}
for (const session of sessions) {