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:
parent
55628eea02
commit
9ba8f37486
4 changed files with 1406 additions and 3 deletions
1396
public/i18n/literals/km.json
Normal file
1396
public/i18n/literals/km.json
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -20,6 +20,7 @@ export const LOCALES = [
|
||||||
"uk",
|
"uk",
|
||||||
"tl",
|
"tl",
|
||||||
"id",
|
"id",
|
||||||
|
"km",
|
||||||
"th",
|
"th",
|
||||||
"hi",
|
"hi",
|
||||||
"bn",
|
"bn",
|
||||||
|
|
@ -60,6 +61,7 @@ export const LOCALE_NAMES = {
|
||||||
tl: "Tagalog",
|
tl: "Tagalog",
|
||||||
id: "Indonesia",
|
id: "Indonesia",
|
||||||
th: "ไทย",
|
th: "ไทย",
|
||||||
|
km: "ខ្មែរ",
|
||||||
hi: "हिन्दी",
|
hi: "हिन्दी",
|
||||||
bn: "বাংলা",
|
bn: "বাংলা",
|
||||||
ur: "اردو",
|
ur: "اردو",
|
||||||
|
|
@ -141,6 +143,9 @@ export function normalizeLocale(locale) {
|
||||||
if (locale === "th") {
|
if (locale === "th") {
|
||||||
return "th";
|
return "th";
|
||||||
}
|
}
|
||||||
|
if (locale === "km") {
|
||||||
|
return "km";
|
||||||
|
}
|
||||||
if (locale === "hi") {
|
if (locale === "hi") {
|
||||||
return "hi";
|
return "hi";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ const getLocaleInfo = (locale) => {
|
||||||
"tl": { name: "Tagalog", flag: "🇵🇭" },
|
"tl": { name: "Tagalog", flag: "🇵🇭" },
|
||||||
"id": { name: "Indonesia", flag: "🇮🇩" },
|
"id": { name: "Indonesia", flag: "🇮🇩" },
|
||||||
"th": { name: "ไทย", flag: "🇹🇭" },
|
"th": { name: "ไทย", flag: "🇹🇭" },
|
||||||
|
"km": { name: "ខ្មែរ", flag: "🇰🇭" },
|
||||||
"hi": { name: "हिन्दी", flag: "🇮🇳" },
|
"hi": { name: "हिन्दी", flag: "🇮🇳" },
|
||||||
"bn": { name: "বাংলা", flag: "🇧🇩" },
|
"bn": { name: "বাংলা", flag: "🇧🇩" },
|
||||||
"ur": { name: "اردو", flag: "🇵🇰" },
|
"ur": { name: "اردو", flag: "🇵🇰" },
|
||||||
|
|
@ -63,9 +64,9 @@ export default function LanguageSwitcher({ className = "", isOpen: controlledOpe
|
||||||
|
|
||||||
const isControlled = typeof controlledOpen === "boolean";
|
const isControlled = typeof controlledOpen === "boolean";
|
||||||
const isOpen = isControlled ? controlledOpen : internalOpen;
|
const isOpen = isControlled ? controlledOpen : internalOpen;
|
||||||
const setIsOpen = (value) => {
|
const setIsOpen = (value, nextLocale = locale) => {
|
||||||
if (isControlled) {
|
if (isControlled) {
|
||||||
if (!value && onClose) onClose(locale);
|
if (!value && onClose) onClose(nextLocale);
|
||||||
} else {
|
} else {
|
||||||
setInternalOpen(value);
|
setInternalOpen(value);
|
||||||
}
|
}
|
||||||
|
|
@ -92,7 +93,6 @@ export default function LanguageSwitcher({ className = "", isOpen: controlledOpe
|
||||||
if (nextLocale === locale || isPending) return;
|
if (nextLocale === locale || isPending) return;
|
||||||
|
|
||||||
setIsPending(true);
|
setIsPending(true);
|
||||||
setIsOpen(false);
|
|
||||||
try {
|
try {
|
||||||
await fetch("/api/locale", {
|
await fetch("/api/locale", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
|
|
@ -103,6 +103,7 @@ export default function LanguageSwitcher({ className = "", isOpen: controlledOpe
|
||||||
// Reload translations without full page reload
|
// Reload translations without full page reload
|
||||||
await reloadTranslations();
|
await reloadTranslations();
|
||||||
setLocale(nextLocale);
|
setLocale(nextLocale);
|
||||||
|
setIsOpen(false, nextLocale);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("Failed to set locale:", err);
|
console.error("Failed to set locale:", err);
|
||||||
} finally {
|
} finally {
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ export const LOCALE_FLAGS = {
|
||||||
"tl": "🇵🇭",
|
"tl": "🇵🇭",
|
||||||
"id": "🇮🇩",
|
"id": "🇮🇩",
|
||||||
"th": "🇹🇭",
|
"th": "🇹🇭",
|
||||||
|
"km": "🇰🇭",
|
||||||
"hi": "🇮🇳",
|
"hi": "🇮🇳",
|
||||||
"bn": "🇧🇩",
|
"bn": "🇧🇩",
|
||||||
"ur": "🇵🇰",
|
"ur": "🇵🇰",
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue