Improve MineGeo interface and functionality

This commit is contained in:
2026-10-06 19:24:41 +05:00
parent 7404f1dc1c
commit 233e4d57f0
67 changed files with 3053 additions and 643 deletions

75
shared/i18n.ts Normal file
View File

@@ -0,0 +1,75 @@
import russian from "./locales/ru.json";
export type Locale = "en" | "ru";
export type LanguagePreference = Locale | "auto";
export const languageCookie = "minegeo-language";
export const localeTag = (locale: Locale) =>
locale === "ru" ? "ru-RU" : "en-GB";
export function detectLocale(acceptLanguage: string | null): Locale {
const languages = (acceptLanguage ?? "")
.split(",")
.map((entry, index) => {
const [tag, ...parameters] = entry.trim().toLowerCase().split(";");
const quality = parameters.find((parameter) =>
parameter.trim().startsWith("q="),
);
return {
tag: tag.split("-")[0],
weight: quality ? Number(quality.trim().slice(2)) : 1,
index,
};
})
.filter(
({ weight }) => Number.isFinite(weight) && weight > 0 && weight <= 1,
)
.sort((a, b) => b.weight - a.weight || a.index - b.index);
return (
(languages.find(({ tag }) => tag === "ru" || tag === "en")
?.tag as Locale) || "en"
);
}
export function resolveLocale(
preference: string | undefined,
acceptLanguage: string | null,
): Locale {
return preference === "en" || preference === "ru"
? preference
: detectLocale(acceptLanguage);
}
export function translator(locale: Locale) {
return (message: string, values?: Record<string, string | number>) => {
const translated =
locale === "ru"
? ((russian as Record<string, string>)[message] ?? message)
: message;
return values
? translated.replace(/\{(\w+)\}/g, (match, key) =>
String(values[key] ?? match),
)
: translated;
};
}
export function statusMessage(status: string) {
const labels: Record<string, string> = {
draft: "Draft",
uploading: "Uploading",
processing: "Processing",
review: "Awaiting review",
published: "Published",
failed: "Failed",
rejected: "Rejected",
submitted: "Submitted",
accepted: "Accepted",
queued: "Queued",
running: "In progress",
open: "Open",
approved: "Approved",
closed: "Closed",
withdrawn: "Withdrawn",
};
return labels[status] ?? status;
}