Use getLocale for date, relative time, and money formatting

This commit is contained in:
Marc Brooks 2025-10-14 14:39:00 -05:00
parent 5363baa37a
commit 75716405d5
No known key found for this signature in database
GPG Key ID: 583A6AF2D6AE1DC6
13 changed files with 947 additions and 908 deletions

View File

@ -719,6 +719,13 @@
"something_went_wrong": "Noget gik galt. Prøv igen senere, eller kontakt support.",
"step_counter_step": "Trin {step}",
"subnet_mask": "Undernetmaske",
"time_division_days": "dage",
"time_division_hours": "timer",
"time_division_minutes": "minutter",
"time_division_months": "måneder",
"time_division_seconds": "sekunder",
"time_division_weeks": "uger",
"time_division_years": "år",
"troubleshoot_connection": "Fejlfinding af forbindelse",
"unknown_error": "Ukendt fejl",
"update_in_progress": "Opdatering i gang",

View File

@ -719,6 +719,13 @@
"something_went_wrong": "Ein Fehler ist aufgetreten. Bitte versuchen Sie es später noch einmal oder wenden Sie sich an den Support.",
"step_counter_step": "Schritt {step}",
"subnet_mask": "Subnetzmaske",
"time_division_days": "Tage",
"time_division_hours": "Std.",
"time_division_minutes": "Minuten",
"time_division_months": "Monate",
"time_division_seconds": "Sekunden",
"time_division_weeks": "Wochen",
"time_division_years": "Jahre",
"troubleshoot_connection": "Verbindungsprobleme beheben",
"unknown_error": "Unbekannter Fehler",
"update_in_progress": "Aktualisierung läuft",

File diff suppressed because it is too large Load Diff

View File

@ -719,6 +719,13 @@
"something_went_wrong": "Algo salió mal. Inténtalo de nuevo más tarde o contacta con el servicio de asistencia.",
"step_counter_step": "Paso {step}",
"subnet_mask": "Máscara de subred",
"time_division_days": "días",
"time_division_hours": "horas",
"time_division_minutes": "minutos",
"time_division_months": "meses",
"time_division_seconds": "artículos de segunda clase",
"time_division_weeks": "semanas",
"time_division_years": "años",
"troubleshoot_connection": "Solucionar problemas de conexión",
"unknown_error": "Error desconocido",
"update_in_progress": "Actualización en progreso",

View File

@ -719,6 +719,13 @@
"something_went_wrong": "Une erreur s'est produite. Veuillez réessayer ultérieurement ou contacter le support.",
"step_counter_step": "Étape {step}",
"subnet_mask": "Masque de sous-réseau",
"time_division_days": "jours",
"time_division_hours": "heures",
"time_division_minutes": "minutes",
"time_division_months": "mois",
"time_division_seconds": "secondes",
"time_division_weeks": "semaines",
"time_division_years": "années",
"troubleshoot_connection": "Dépannage de connexion",
"unknown_error": "Erreur inconnue",
"update_in_progress": "Mise à jour en cours",

View File

@ -719,6 +719,13 @@
"something_went_wrong": "Qualcosa è andato storto. Riprova più tardi o contatta l'assistenza.",
"step_counter_step": "Passaggio {step}",
"subnet_mask": "Maschera di sottorete",
"time_division_days": "giorni",
"time_division_hours": "ore",
"time_division_minutes": "minuti",
"time_division_months": "mesi",
"time_division_seconds": "secondi",
"time_division_weeks": "settimane",
"time_division_years": "anni",
"troubleshoot_connection": "Risoluzione dei problemi di connessione",
"unknown_error": "Errore sconosciuto",
"update_in_progress": "Aggiornamento in corso",

View File

@ -719,6 +719,13 @@
"something_went_wrong": "Noe gikk galt. Prøv igjen senere, eller kontakt kundestøtte.",
"step_counter_step": "Trinn {step}",
"subnet_mask": "Nettmaske",
"time_division_days": "dager",
"time_division_hours": "timer",
"time_division_minutes": "minutter",
"time_division_months": "måneder",
"time_division_seconds": "sekunder",
"time_division_weeks": "uker",
"time_division_years": "år",
"troubleshoot_connection": "Feilsøking av tilkobling",
"unknown_error": "Ukjent feil",
"update_in_progress": "Oppdatering pågår",

View File

@ -719,6 +719,13 @@
"something_went_wrong": "Något gick fel. Försök igen senare eller kontakta supporten.",
"step_counter_step": "Steg {step}",
"subnet_mask": "Subnätmask",
"time_division_days": "dagar",
"time_division_hours": "timmar",
"time_division_minutes": "minuter",
"time_division_months": "månader",
"time_division_seconds": "sekunder",
"time_division_weeks": "veckor",
"time_division_years": "år",
"troubleshoot_connection": "Felsök anslutning",
"unknown_error": "Okänt fel",
"update_in_progress": "Uppdatering pågår",

View File

@ -719,6 +719,13 @@
"something_went_wrong": "出了点问题。请稍后重试或联系客服",
"step_counter_step": "步骤{step}",
"subnet_mask": "子网掩码",
"time_division_days": "天",
"time_division_hours": "小时",
"time_division_minutes": "分钟",
"time_division_months": "个月",
"time_division_seconds": "秒",
"time_division_weeks": "周",
"time_division_years": "年",
"troubleshoot_connection": "连接故障排除",
"unknown_error": "未知错误",
"update_in_progress": "正在更新",

62
ui/package-lock.json generated
View File

@ -70,10 +70,10 @@
"globals": "^16.4.0",
"postcss": "^8.5.6",
"prettier": "^3.6.2",
"prettier-plugin-tailwindcss": "^0.6.14",
"prettier-plugin-tailwindcss": "^0.7.0",
"tailwindcss": "^4.1.14",
"typescript": "^5.9.3",
"vite": "^7.1.9",
"vite": "^7.1.10",
"vite-tsconfig-paths": "^5.1.4"
},
"engines": {
@ -3078,9 +3078,9 @@
"license": "MIT"
},
"node_modules/baseline-browser-mapping": {
"version": "2.8.14",
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.14.tgz",
"integrity": "sha512-GM9c0cWWR8Ga7//Ves/9KRgTS8nLausCkP3CGiFLrnwA2CDUluXgaQqvrULoR2Ujrd/mz/lkX87F5BHFsNr5sQ==",
"version": "2.8.16",
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.16.tgz",
"integrity": "sha512-OMu3BGQ4E7P1ErFsIPpbJh0qvDudM/UuJeHgkAvfWe+0HFJCXh+t/l8L6fVLR55RI/UbKrVLnAXZSVwd9ysWYw==",
"dev": true,
"license": "Apache-2.0",
"bin": {
@ -3201,9 +3201,9 @@
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001749",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001749.tgz",
"integrity": "sha512-0rw2fJOmLfnzCRbkm8EyHL8SvI2Apu5UbnQuTsJ0ClgrH8hcwFooJ1s5R0EP8o8aVrFu8++ae29Kt9/gZAZp/Q==",
"version": "1.0.30001750",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001750.tgz",
"integrity": "sha512-cuom0g5sdX6rw00qOoLNSFCJ9/mYIsuSOA+yzpDw8eopiFqcVwQvZHqov0vmEighRxX++cfC0Vg1G+1Iy/mSpQ==",
"dev": true,
"funding": [
{
@ -3684,9 +3684,9 @@
}
},
"node_modules/electron-to-chromium": {
"version": "1.5.233",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.233.tgz",
"integrity": "sha512-iUdTQSf7EFXsDdQsp8MwJz5SVk4APEFqXU/S47OtQ0YLqacSwPXdZ5vRlMX3neb07Cy2vgioNuRnWUXFwuslkg==",
"version": "1.5.235",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.235.tgz",
"integrity": "sha512-i/7ntLFwOdoHY7sgjlTIDo4Sl8EdoTjWIaKinYOVfC6bOp71bmwenyZthWHcasxgHDNWbWxvG9M3Ia116zIaYQ==",
"dev": true,
"license": "ISC"
},
@ -4020,24 +4020,6 @@
}
}
},
"node_modules/eslint-config-prettier": {
"version": "10.1.8",
"resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz",
"integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==",
"dev": true,
"license": "MIT",
"optional": true,
"peer": true,
"bin": {
"eslint-config-prettier": "bin/cli.js"
},
"funding": {
"url": "https://opencollective.com/eslint-config-prettier"
},
"peerDependencies": {
"eslint": ">=7.0.0"
}
},
"node_modules/eslint-import-resolver-alias": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/eslint-import-resolver-alias/-/eslint-import-resolver-alias-1.1.2.tgz",
@ -6316,13 +6298,13 @@
}
},
"node_modules/prettier-plugin-tailwindcss": {
"version": "0.6.14",
"resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.6.14.tgz",
"integrity": "sha512-pi2e/+ZygeIqntN+vC573BcW5Cve8zUB0SSAGxqpB4f96boZF4M3phPVoOFCeypwkpRYdi7+jQ5YJJUwrkGUAg==",
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.7.0.tgz",
"integrity": "sha512-zpRZhkfwq1cNmbKhmKzXKuKFdkgXZXlf6p+KttD75v6pGz1FxmcKMc4RKdw97GYBKBbout4113HSLaBJAomFDw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=14.21.3"
"node": ">=20.19"
},
"peerDependencies": {
"@ianvs/prettier-plugin-sort-imports": "*",
@ -6335,14 +6317,12 @@
"prettier": "^3.0",
"prettier-plugin-astro": "*",
"prettier-plugin-css-order": "*",
"prettier-plugin-import-sort": "*",
"prettier-plugin-jsdoc": "*",
"prettier-plugin-marko": "*",
"prettier-plugin-multiline-arrays": "*",
"prettier-plugin-organize-attributes": "*",
"prettier-plugin-organize-imports": "*",
"prettier-plugin-sort-imports": "*",
"prettier-plugin-style-order": "*",
"prettier-plugin-svelte": "*"
},
"peerDependenciesMeta": {
@ -6373,9 +6353,6 @@
"prettier-plugin-css-order": {
"optional": true
},
"prettier-plugin-import-sort": {
"optional": true
},
"prettier-plugin-jsdoc": {
"optional": true
},
@ -6394,9 +6371,6 @@
"prettier-plugin-sort-imports": {
"optional": true
},
"prettier-plugin-style-order": {
"optional": true
},
"prettier-plugin-svelte": {
"optional": true
}
@ -7651,9 +7625,9 @@
}
},
"node_modules/vite": {
"version": "7.1.9",
"resolved": "https://registry.npmjs.org/vite/-/vite-7.1.9.tgz",
"integrity": "sha512-4nVGliEpxmhCL8DslSAUdxlB6+SMrhB0a1v5ijlh1xB1nEPuy1mxaHxysVucLHuWryAxLWg6a5ei+U4TLn/rFg==",
"version": "7.1.10",
"resolved": "https://registry.npmjs.org/vite/-/vite-7.1.10.tgz",
"integrity": "sha512-CmuvUBzVJ/e3HGxhg6cYk88NGgTnBoOo7ogtfJJ0fefUWAxN/WDSUa50o+oVBxuIhO8FoEZW0j2eW7sfjs5EtA==",
"license": "MIT",
"dependencies": {
"esbuild": "^0.25.0",

View File

@ -83,10 +83,10 @@
"globals": "^16.4.0",
"postcss": "^8.5.6",
"prettier": "^3.6.2",
"prettier-plugin-tailwindcss": "^0.6.14",
"prettier-plugin-tailwindcss": "^0.7.0",
"tailwindcss": "^4.1.14",
"typescript": "^5.9.3",
"vite": "^7.1.9",
"vite": "^7.1.10",
"vite-tsconfig-paths": "^5.1.4"
}
}

View File

@ -10,6 +10,7 @@ import {
YAxis,
} from "recharts";
import { getLocale } from '@localizations/runtime.js';
import CustomTooltip, { CustomTooltipProps } from "@components/CustomTooltip";
export default function MetricsChart({
@ -51,8 +52,7 @@ export default function MetricsChart({
axisLine={{ stroke: "rgba(30, 41, 59, 0.3)" }}
tickLine={{ stroke: "rgba(30, 41, 59, 0.3)" }}
tickFormatter={date => {
// TODO use locale from user settings for date formatting
return new Date(date * 1000).toLocaleString("en-US", {
return new Date(date * 1000).toLocaleString(getLocale() || "en-US", {
hourCycle: "h23",
hour: "numeric",
minute: "2-digit",

View File

@ -1,8 +1,9 @@
import { KeySequence } from "@hooks/stores";
import { getLocale } from '@localizations/runtime.js';
export const formatters = {
date: (date: Date, options?: Intl.DateTimeFormatOptions) =>
new Intl.DateTimeFormat("en-US", {
new Intl.DateTimeFormat(getLocale() || "en-US", {
year: "numeric",
month: "long",
day: "numeric",
@ -34,11 +35,12 @@ export const formatters = {
},
timeAgo: (date: Date, options?: Intl.RelativeTimeFormatOptions) => {
const relativeTimeFormat = new Intl.RelativeTimeFormat("en-US", {
const relativeTimeFormat = new Intl.RelativeTimeFormat(getLocale() || "en-US", {
numeric: "auto",
...(options || {}),
});
// Note, do not translate the unit names in DIVISIONS, as they must match Intl.RelativeTimeFormatUnit
const DIVISIONS: {
amount: number;
name: Intl.RelativeTimeFormatUnit;
@ -79,7 +81,7 @@ export const formatters = {
opts.minimumFractionDigits = 0;
}
return new Intl.NumberFormat("en-US", opts).format(numericPrice);
return new Intl.NumberFormat(getLocale() || "en-US", opts).format(numericPrice);
},
truncateMiddle: (str: string | null | undefined, maxLength: number): string => {