export const languages = [ ["en", "English"], ["de", "Deutsch"], ["fr", "Français"], ["es", "Español"], ["pt", "Português"], ["it", "Italiano"], ["nl", "Nederlands"], ["zh-CN", "简体中文"], ["zh-TW", "繁體中文"], ["ja", "日本語"], ["hi", "हिन्दी"], ["ar", "العربية"], ["he", "עברית"], ["ru", "Русский"], ["ko", "한국어"], ["tr", "Türkçe"], ["id", "Bahasa Indonesia"], ["bn", "বাংলা"], ["vi", "Tiếng Việt"], ["fil", "Filipino"], ["th", "ไทย"], ["pl", "Polski"], ["uk", "Українська"], ["sv", "Svenska"], ["no", "Norsk"], ["da", "Dansk"], ["fi", "Suomi"], ["cs", "Čeština"], ["el", "Ελληνικά"], ["ro", "Română"], ] as const; export type LangCode = (typeof languages)[number][0]; export const langCodes = languages.map(([code]) => code) as LangCode[]; export const rtlLangs = new Set(["ar", "he"]); export const detectLanguage = (): LangCode => { for (const tag of navigator.languages.length ? navigator.languages : [navigator.language]) { const normalized = tag.toLowerCase(); if (normalized === "zh" || normalized.startsWith("zh-")) { if ( normalized.startsWith("zh-hant") || /-(?:tw|hk|mo)(?:-|$)/.test(normalized) ) { return "zh-TW"; } if ( normalized.startsWith("zh-hans") || /-(?:cn|sg)(?:-|$)/.test(normalized) ) { return "zh-CN"; } return "zh-CN"; } const base = normalized.split("-", 1)[0]; const match = langCodes.find( (code) => code.toLowerCase() === normalized || code === base, ); if (match) return match; } return "en"; };