feat(i18n): add Khmer language support

Register Khmer (km) locale, add complete 1,394-entry dashboard translation,
and show the Cambodia flag in the language selector. Place Khmer immediately
before Thai in the selector and keep the header locale in sync after switching.
This commit is contained in:
seakleang.nhak
2026-07-19 16:30:13 +07:00
committed by decolua
parent 55628eea02
commit 9ba8f37486
4 changed files with 1406 additions and 3 deletions

1396
public/i18n/literals/km.json Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -20,6 +20,7 @@ export const LOCALES = [
"uk",
"tl",
"id",
"km",
"th",
"hi",
"bn",
@@ -60,6 +61,7 @@ export const LOCALE_NAMES = {
tl: "Tagalog",
id: "Indonesia",
th: "ไทย",
km: "ខ្មែរ",
hi: "हिन्दी",
bn: "বাংলা",
ur: "اردو",
@@ -141,6 +143,9 @@ export function normalizeLocale(locale) {
if (locale === "th") {
return "th";
}
if (locale === "km") {
return "km";
}
if (locale === "hi") {
return "hi";
}

View File

@@ -39,6 +39,7 @@ const getLocaleInfo = (locale) => {
"tl": { name: "Tagalog", flag: "🇵🇭" },
"id": { name: "Indonesia", flag: "🇮🇩" },
"th": { name: "ไทย", flag: "🇹🇭" },
"km": { name: "ខ្មែរ", flag: "🇰🇭" },
"hi": { name: "हिन्दी", flag: "🇮🇳" },
"bn": { name: "বাংলা", flag: "🇧🇩" },
"ur": { name: "اردو", flag: "🇵🇰" },
@@ -63,9 +64,9 @@ export default function LanguageSwitcher({ className = "", isOpen: controlledOpe
const isControlled = typeof controlledOpen === "boolean";
const isOpen = isControlled ? controlledOpen : internalOpen;
const setIsOpen = (value) => {
const setIsOpen = (value, nextLocale = locale) => {
if (isControlled) {
if (!value && onClose) onClose(locale);
if (!value && onClose) onClose(nextLocale);
} else {
setInternalOpen(value);
}
@@ -92,7 +93,6 @@ export default function LanguageSwitcher({ className = "", isOpen: controlledOpe
if (nextLocale === locale || isPending) return;
setIsPending(true);
setIsOpen(false);
try {
await fetch("/api/locale", {
method: "POST",
@@ -103,6 +103,7 @@ export default function LanguageSwitcher({ className = "", isOpen: controlledOpe
// Reload translations without full page reload
await reloadTranslations();
setLocale(nextLocale);
setIsOpen(false, nextLocale);
} catch (err) {
console.error("Failed to set locale:", err);
} finally {

View File

@@ -22,6 +22,7 @@ export const LOCALE_FLAGS = {
"tl": "🇵🇭",
"id": "🇮🇩",
"th": "🇹🇭",
"km": "🇰🇭",
"hi": "🇮🇳",
"bn": "🇧🇩",
"ur": "🇵🇰",