add localizations, exclude ref from recursion

This commit is contained in:
Alex Holliday committed 2026-08-31 10:17:00 -07:00
1 parent b24e42e516
commit 073635d786
19 files changed
+140 -26

No files matched your search

+14 -26
View File
@@ -58,8 +58,6 @@ const SETTINGS_TABS = [
type SettingsTabKey = (typeof SETTINGS_TABS)[number]["key"];
// Maps a validation error back to the tab holding it, so a failed save can
// reveal the offending field instead of naming one on a hidden tab.
const FIELD_TAB: Record<string, SettingsTabKey> = {
checkTTL: "monitoring",
globalThresholds: "monitoring",
@@ -74,10 +72,6 @@ const tabForField = (field: string): SettingsTabKey =>
? "email"
: (FIELD_TAB[field.split(".")[0]] ?? "general");
// Error rows named the raw schema key ("systemEmailRejectUnauthorized"). Each
// field already owns a translated label, so reuse those rather than adding
// strings. Labels that append an explanation after a dash are trimmed to the
// name itself.
const FIELD_LABEL_KEY: Record<string, string> = {
checkTTL: "pages.settings.form.retention.option.days.label",
"globalThresholds.cpu": "pages.settings.form.thresholds.option.cpu.label",
@@ -104,10 +98,6 @@ const FIELD_LABEL_KEY: Record<string, string> = {
"pages.settings.form.email.option.rejectUnauthorized.label",
};
// react-hook-form nests errors by path, so a grouped field arrives as
// { globalThresholds: { cpu: { message } } }. Iterating the top level alone
// yields an entry whose own message is undefined, which renders as a bare
// "globalThresholds" naming none of the four sliders. Walk to the leaves.
type FieldErrorLeaf = { path: string; message?: string };
const flattenFieldErrors = (errors: unknown, prefix = ""): FieldErrorLeaf[] => {
@@ -115,6 +105,9 @@ const flattenFieldErrors = (errors: unknown, prefix = ""): FieldErrorLeaf[] => {
return [];
}
return Object.entries(errors).flatMap(([key, value]) => {
if (key === "ref") {
return [];
}
const path = prefix ? `${prefix}.${key}` : key;
if (typeof value !== "object" || value === null) {
return [];
@@ -141,11 +134,7 @@ export const SettingsPage = () => {
[isAdmin]
);
// An unknown tab, or an admin tab requested by a non-admin, falls back to the
// first tab the current user can actually see.
const requestedTab = searchParams.get("tab");
// visibleTabs always contains "general" today; the constant fallback keeps a
// future gating change from throwing on an empty list.
const firstVisibleTab: SettingsTabKey = visibleTabs[0]?.key ?? SETTINGS_TABS[0].key;
const activeTab: SettingsTabKey =
visibleTabs.find((tab) => tab.key === requestedTab)?.key ?? firstVisibleTab;
@@ -160,16 +149,19 @@ export const SettingsPage = () => {
setSearchParams(updated, { replace: true });
};
// A "tab" that does not resolve -- an unknown key, or an admin tab followed by
// a non-admin -- leaves the URL claiming a tab the page is not showing. Drop it
// so the address bar matches what is rendered.
// Drop a "tab" param that does not resolve to a rendered tab, or that names
// the first tab, which is addressed with no param at all.
useEffect(() => {
if (requestedTab !== null && requestedTab !== activeTab) {
const updated = new URLSearchParams(searchParams);
updated.delete("tab");
setSearchParams(updated, { replace: true });
if (requestedTab === null) {
return;
}
}, [requestedTab, activeTab, searchParams, setSearchParams]);
if (requestedTab === activeTab && activeTab !== firstVisibleTab) {
return;
}
const updated = new URLSearchParams(searchParams);
updated.delete("tab");
setSearchParams(updated, { replace: true });
}, [requestedTab, activeTab, firstVisibleTab, searchParams, setSearchParams]);
// Local state for demo monitors dialog
const [isDemoMonitorsDialogOpen, setIsDemoMonitorsDialogOpen] = useState(false);
@@ -418,10 +410,6 @@ export const SettingsPage = () => {
logger.debug("Form validation errors", errors);
};
// The save bar lists errors by field name, and the offending field may sit on
// a tab that is not open. Submitting cannot reveal it -- the button is
// disabled while the form is invalid -- so each listed field switches to its
// own tab instead.
const revealField = (field: string) => {
const target = tabForField(field);
if (visibleTabs.some((tab) => tab.key === target)) {
+7
View File
@@ -1141,6 +1141,13 @@
}
},
"settings": {
"tabs": {
"general": "عام",
"monitoring": "المراقبة",
"email": "البريد الإلكتروني",
"integrations": "التكاملات",
"data": "البيانات"
},
"form": {
"timezone": {
"title": "المنطقة الزمنية للعرض",
+7
View File
@@ -1141,6 +1141,13 @@
}
},
"settings": {
"tabs": {
"general": "General",
"monitoring": "Monitoratge",
"email": "Correu electrònic",
"integrations": "Integracions",
"data": "Dades"
},
"form": {
"timezone": {
"title": "Zona horària de visualització",
+7
View File
@@ -1141,6 +1141,13 @@
}
},
"settings": {
"tabs": {
"general": "Obecné",
"monitoring": "Monitorování",
"email": "E-mail",
"integrations": "Integrace",
"data": "Data"
},
"form": {
"timezone": {
"title": "Zobrazované časové pásmo",
+7
View File
@@ -1141,6 +1141,13 @@
}
},
"settings": {
"tabs": {
"general": "Allgemein",
"monitoring": "Überwachung",
"email": "E-Mail",
"integrations": "Integrationen",
"data": "Daten"
},
"form": {
"timezone": {
"title": "Anzeigesprache Zeitzone",
+7
View File
@@ -1141,6 +1141,13 @@
}
},
"settings": {
"tabs": {
"general": "General",
"monitoring": "Monitorización",
"email": "Correo electrónico",
"integrations": "Integraciones",
"data": "Datos"
},
"form": {
"timezone": {
"title": "Zona horaria de visualización",
+7
View File
@@ -1141,6 +1141,13 @@
}
},
"settings": {
"tabs": {
"general": "Yleiset",
"monitoring": "Valvonta",
"email": "Sähköposti",
"integrations": "Integraatiot",
"data": "Tiedot"
},
"form": {
"timezone": {
"title": "Näytettävä aikavyöhyke",
+7
View File
@@ -1141,6 +1141,13 @@
}
},
"settings": {
"tabs": {
"general": "Général",
"monitoring": "Surveillance",
"email": "E-mail",
"integrations": "Intégrations",
"data": "Données"
},
"form": {
"timezone": {
"title": "Fuseau horaire d'affichage",
+7
View File
@@ -1237,6 +1237,13 @@
}
},
"settings": {
"tabs": {
"general": "Generale",
"monitoring": "Monitoraggio",
"email": "Email",
"integrations": "Integrazioni",
"data": "Dati"
},
"form": {
"timezone": {
"title": "Fuso orario di visualizzazione",
+7
View File
@@ -1141,6 +1141,13 @@
}
},
"settings": {
"tabs": {
"general": "一般",
"monitoring": "監視",
"email": "メール",
"integrations": "連携",
"data": "データ"
},
"form": {
"timezone": {
"title": "表示タイムゾーン",
+7
View File
@@ -1207,6 +1207,13 @@
}
},
"settings": {
"tabs": {
"general": "Ogólne",
"monitoring": "Monitorowanie",
"email": "E-mail",
"integrations": "Integracje",
"data": "Dane"
},
"form": {
"about": {
"developedBy": "Opracowane przez Bluewave Labs",
+7
View File
@@ -1141,6 +1141,13 @@
}
},
"settings": {
"tabs": {
"general": "Geral",
"monitoring": "Monitoramento",
"email": "E-mail",
"integrations": "Integrações",
"data": "Dados"
},
"form": {
"timezone": {
"title": "Fuso horário de exibição",
+7
View File
@@ -1141,6 +1141,13 @@
}
},
"settings": {
"tabs": {
"general": "Общие",
"monitoring": "Мониторинг",
"email": "Электронная почта",
"integrations": "Интеграции",
"data": "Данные"
},
"form": {
"timezone": {
"title": "Часовой пояс отображения",
+7
View File
@@ -1141,6 +1141,13 @@
}
},
"settings": {
"tabs": {
"general": "ทั่วไป",
"monitoring": "การตรวจสอบ",
"email": "อีเมล",
"integrations": "การเชื่อมต่อ",
"data": "ข้อมูล"
},
"form": {
"timezone": {
"title": "เขตเวลาที่แสดง",
+7
View File
@@ -1141,6 +1141,13 @@
}
},
"settings": {
"tabs": {
"general": "Genel",
"monitoring": "İzleme",
"email": "E-posta",
"integrations": "Entegrasyonlar",
"data": "Veri"
},
"form": {
"timezone": {
"title": "Görüntüleme saat dilimi",
+7
View File
@@ -1141,6 +1141,13 @@
}
},
"settings": {
"tabs": {
"general": "Загальні",
"monitoring": "Моніторинг",
"email": "Електронна пошта",
"integrations": "Інтеграції",
"data": "Дані"
},
"form": {
"timezone": {
"title": "Часовий пояс відображення",
+7
View File
@@ -1141,6 +1141,13 @@
}
},
"settings": {
"tabs": {
"general": "Chung",
"monitoring": "Giám sát",
"email": "Email",
"integrations": "Tích hợp",
"data": "Dữ liệu"
},
"form": {
"timezone": {
"title": "Múi giờ hiển thị",
+7
View File
@@ -1142,6 +1142,13 @@
}
},
"settings": {
"tabs": {
"general": "常规",
"monitoring": "监控",
"email": "邮件",
"integrations": "集成",
"data": "数据"
},
"form": {
"timezone": {
"title": "显示时区",
+7
View File
@@ -1141,6 +1141,13 @@
}
},
"settings": {
"tabs": {
"general": "一般",
"monitoring": "監控",
"email": "郵件",
"integrations": "整合",
"data": "資料"
},
"form": {
"timezone": {
"title": "顯示時區",