1
0
mirror of https://github.com/godotengine/godot.git synced 2025-12-31 18:41:20 +00:00

Improve language selection when shaping text.

This commit is contained in:
Pāvels Nadtočajevs
2025-11-12 10:52:46 +02:00
parent 79603b2f28
commit 997f326b58
9 changed files with 791 additions and 50 deletions

View File

@@ -469,7 +469,6 @@ static const char *language_list[][2] = {
{ "chy", "Cheyenne" },
{ "cic", "Chickasaw" },
{ "ckb", "Central Kurdish" },
{ "csb", "Kashubian" },
{ "cmn", "Mandarin Chinese" },
{ "co", "Corsican" },
{ "cop", "Coptic" },
@@ -662,7 +661,6 @@ static const char *language_list[][2] = {
{ "kv", "Komi" },
{ "kw", "Cornish" },
{ "ky", "Kirghiz" },
{ "lag", "Langi" },
{ "la", "Latin" },
{ "lad", "Ladino" },
{ "lag", "Langi" },
@@ -982,7 +980,630 @@ static const char *language_list[][2] = {
{ "zu", "Zulu" },
{ "zun", "Zuni" },
{ "zza", "Zaza" },
{ nullptr, nullptr }
{ nullptr, nullptr },
};
// Scripts used by languages.
// Reference:
// - https://www.unicode.org/cldr/charts/48/supplemental/languages_and_scripts.html
static const char *language_script_list[][2] = {
{ "aa", "Latn" },
{ "ab", "Cyrl" },
{ "ace", "Latn" },
{ "ach", "Latn" },
{ "ada", "Latn" },
{ "ady", "Cyrl" },
{ "ae", "Avst" },
{ "aeb", "Arab" },
{ "af", "Latn" },
{ "afh", "Latn" },
{ "agq", "Latn" },
{ "ain", "Kana Latn" },
{ "agr", "Latn" },
{ "ak", "Latn" },
{ "akk", "Xsux" },
{ "akz", "Latn" },
{ "ale", "Latn" },
{ "aln", "Latn" },
{ "alt", "Cyrl" },
{ "am", "Ethi" },
{ "an", "Latn" },
{ "ang", "Latn" },
{ "anp", "Deva" },
{ "ar", "Arab Syrc" },
{ "arc", "Armi Nbat Palm" },
{ "arn", "Latn" },
{ "aro", "Latn" },
{ "arp", "Latn" },
{ "arq", "Arab" },
{ "ars", "Arab" },
{ "arw", "Latn" },
{ "ary", "Arab" },
{ "arz", "Arab" },
{ "as", "Beng" },
{ "asa", "Latn" },
{ "ast", "Latn" },
{ "av", "Cyrl" },
{ "avk", "Latn" },
{ "awa", "Deva" },
{ "ayc", "Latn" },
{ "ay", "Latn" },
{ "az", "Latn Arab Cyrl" },
{ "ba", "Cyrl" },
{ "bal", "Arab Latn" },
{ "ban", "Latn Bali" },
{ "bar", "Latn" },
{ "bas", "Latn" },
{ "bax", "Bamu" },
{ "bbc", "Latn Batk" },
{ "bbj", "Latn" },
{ "be", "Cyrl" },
{ "bej", "Arab" },
{ "bem", "Latn" },
{ "ber", "Latn Arab Tfng" },
{ "bew", "Latn" },
{ "bez", "Latn" },
{ "bfd", "Latn" },
{ "bfq", "Taml" },
{ "bg", "Cyrl" },
{ "bhb", "Deva" },
{ "bgn", "Arab" },
{ "bho", "Deva" },
{ "bi", "Latn" },
{ "bik", "Latn" },
{ "bin", "Latn" },
{ "bjn", "Latn" },
{ "bkm", "Latn" },
{ "bla", "Latn" },
{ "bm", "Latn Nkoo" },
{ "bn", "Beng" },
{ "bo", "Tibt" },
{ "bpy", "Beng" },
{ "bqi", "Arab" },
{ "br", "Latn" },
{ "brh", "Arab Latn" },
{ "brx", "Deva" },
{ "bs", "Latn Cyrl" },
{ "bss", "Latn" },
{ "bua", "Cyrl" },
{ "bug", "Latn Bug" },
{ "bum", "Latn" },
{ "byn", "Ethi" },
{ "byv", "Latn" },
{ "ca", "Latn" },
{ "cad", "Latn" },
{ "car", "Latn" },
{ "cay", "Latn" },
{ "cch", "Latn" },
{ "ccp", "Cakm Beng" },
{ "ce", "Cyrl" },
{ "ceb", "Latn" },
{ "cgg", "Latn" },
{ "ch", "Latn" },
{ "chb", "Latn" },
{ "chg", "Arab" },
{ "chk", "Latn" },
{ "chm", "Cyrl" },
{ "chn", "Latn" },
{ "cho", "Latn" },
{ "chp", "Latn Cans" },
{ "chr", "Cher" },
{ "chy", "Latn" },
{ "cic", "Latn" },
{ "ckb", "Arab" },
{ "cmn", "Hant Hans Hani" },
{ "co", "Latn" },
{ "cop", "Copt Arab Grek" },
{ "cps", "Latn" },
{ "cr", "Cans Latn" },
{ "crh", "Cyrl" },
{ "crs", "Latn" },
{ "cs", "Latn" },
{ "csb", "Latn" },
{ "cu", "Cyrl" },
{ "cv", "Cyrl" },
{ "cy", "Latn" },
{ "da", "Latn" },
{ "dak", "Latn" },
{ "dar", "Cyrl" },
{ "dav", "Latn" },
{ "de", "Latn Runr" },
{ "del", "Latn" },
{ "den", "Latn Cans" },
{ "dgr", "Latn" },
{ "din", "Latn" },
{ "dje", "Latn" },
{ "doi", "Deva Arab Takr" },
{ "dsb", "Latn" },
{ "dtp", "Latn" },
{ "dua", "Latn" },
{ "dum", "Latn" },
{ "dv", "Thaa" },
{ "dyo", "Latn Arab" },
{ "dyu", "Latn" },
{ "dz", "Tibt" },
{ "dzg", "Latn" },
{ "ebu", "Latn" },
{ "ee", "Latn" },
{ "efi", "Latn" },
{ "egl", "Latn" },
{ "egy", "Egyp" },
{ "eka", "Latn" },
{ "el", "Grek" },
{ "elx", "Xsux" },
{ "en", "Latn Dsrt Shaw" },
{ "enm", "Latn" },
{ "eo", "Latn" },
{ "es", "Latn" },
{ "esu", "Latn" },
{ "et", "Latn" },
{ "eu", "Latn" },
{ "ewo", "Latn" },
{ "ext", "Latn" },
{ "fa", "Arab" },
{ "fan", "Latn" },
{ "fat", "Latn" },
{ "ff", "Latn Adlm" },
{ "fi", "Latn" },
{ "fil", "Latn Tglg" },
{ "fit", "Latn" },
{ "fj", "Latn" },
{ "fo", "Latn" },
{ "fon", "Latn" },
{ "fr", "Latn Dupl" },
{ "frc", "Latn" },
{ "frm", "Latn" },
{ "fro", "Latn" },
{ "frp", "Latn" },
{ "frr", "Latn" },
{ "frs", "Latn" },
{ "fur", "Latn" },
{ "fy", "Latn" },
{ "ga", "Latn" },
{ "gaa", "Latn" },
{ "gag", "Latn Cyrl" },
{ "gan", "Hans Hani" },
{ "gay", "Latn" },
{ "gba", "Latn" },
{ "gbz", "Arab" },
{ "gd", "Latn" },
{ "gez", "Ethi" },
{ "gil", "Latn" },
{ "gl", "Latn" },
{ "glk", "Arab" },
{ "gmh", "Latn" },
{ "gn", "Latn" },
{ "goh", "Latn" },
{ "gom", "Deav Latn Knda Mlym Arab" },
{ "gon", "Deva Telu" },
{ "gor", "Latn" },
{ "got", "Goth" },
{ "grb", "Latn" },
{ "grc", "Grek" },
{ "gsw", "Latn" },
{ "gu", "Gujr" },
{ "guc", "Latn" },
{ "gur", "Latn" },
{ "guz", "Latn" },
{ "gv", "Latn" },
{ "gwi", "Latn" },
{ "ha", "Latn Arab" },
{ "hai", "Latn" },
{ "hak", "Hans Hant Hani" },
{ "haw", "Latn" },
{ "he", "Hebr" },
{ "hi", "Deva Latn Mahj" },
{ "hif", "Deva Latn" },
{ "hil", "Latn" },
{ "hit", "Xsux" },
{ "hmn", "Latn Hmng" },
{ "ho", "Latn" },
{ "hne", "Deva" },
{ "hr", "Latn" },
{ "hsb", "Latn" },
{ "hsn", "Hans Hani" },
{ "ht", "Latn" },
{ "hu", "Latn" },
{ "hup", "Latn" },
{ "hus", "Latn" },
{ "hy", "Armn" },
{ "hz", "Latn" },
{ "ia", "Latn" },
{ "iba", "Latn" },
{ "ibb", "Latn" },
{ "id", "Latn Arab" },
{ "ie", "Latn" },
{ "ig", "Latn" },
{ "ii", "Yiii Latn" },
{ "ik", "Latn" },
{ "ilo", "Latn" },
{ "inh", "Cyrl" },
{ "io", "Latn" },
{ "is", "Latn" },
{ "it", "Latn" },
{ "iu", "Cans Latn" },
{ "izh", "Latn" },
{ "ja", "Jpan Hani Hira Kana" },
{ "jam", "Latn" },
{ "jbo", "Latn" },
{ "jgo", "Latn" },
{ "jmc", "Latn" },
{ "jpr", "Hebr" },
{ "jrb", "Hebr" },
{ "jut", "Latn" },
{ "jv", "Latn Java" },
{ "ka", "Geor" },
{ "kaa", "Cyrl Latn" },
{ "kab", "Latn" },
{ "kac", "Latn" },
{ "kaj", "Latn" },
{ "kam", "Latn" },
{ "kaw", "Bali Java Kawi" },
{ "kbd", "Cyrl" },
{ "kbl", "Arab" },
{ "kcg", "Latn" },
{ "kde", "Latn" },
{ "kea", "Latn" },
{ "ken", "Latn" },
{ "kfo", "Latn" },
{ "kg", "Latn" },
{ "kgp", "Latn" },
{ "kha", "Latn Beng" },
{ "kho", "Brah Khar" },
{ "khq", "Latn" },
{ "khw", "Arab" },
{ "ki", "Latn" },
{ "kiu", "Latn" },
{ "kj", "Latn" },
{ "kk", "Cyrl Arab" },
{ "kkj", "Latn" },
{ "kl", "Latn" },
{ "kln", "Latn" },
{ "km", "Khmr" },
{ "kmb", "Latn" },
{ "kn", "Knda" },
{ "ko", "Kore Hang Hani" },
{ "koi", "Cyrl" },
{ "kok", "Deva Latn" },
{ "kos", "Latn" },
{ "kpe", "Latn" },
{ "kr", "Latn" },
{ "krc", "Cyrl" },
{ "kri", "Latn" },
{ "krj", "Latn" },
{ "krl", "Latn" },
{ "kru", "Deva" },
{ "ks", "Arab Deva" },
{ "ksb", "Latn" },
{ "ksf", "Latn" },
{ "ksh", "Latn" },
{ "ku", "Latn Arab Cyrl" },
{ "kum", "Cyrl" },
{ "kut", "Latn" },
{ "kv", "Cyrl Perm" },
{ "kw", "Latn" },
{ "ky", "Cyrl Arab Latn" },
{ "la", "Latn" },
{ "lad", "Hebr" },
{ "lag", "Latn" },
{ "lah", "Arab" },
{ "lam", "Latn" },
{ "lb", "Latn" },
{ "lez", "Cyrl Aghb" },
{ "lfn", "Latn Cyrl" },
{ "lg", "Latn" },
{ "li", "Latn" },
{ "lij", "Latn" },
{ "liv", "Latn" },
{ "lkt", "Latn" },
{ "lmo", "Latn" },
{ "ln", "Latn" },
{ "lo", "Laoo" },
{ "lol", "Latn" },
{ "lou", "Latn" },
{ "loz", "Latn" },
{ "lrc", "Arab" },
{ "lt", "Latn" },
{ "ltg", "Latn" },
{ "lu", "Latn" },
{ "lua", "Latn" },
{ "lui", "Latn" },
{ "lun", "Latn" },
{ "luo", "Latn" },
{ "lus", "Beng" },
{ "luy", "Latn" },
{ "lv", "Latn" },
{ "lzh", "Hant" },
{ "lzz", "Latn Geor" },
{ "mad", "Latn" },
{ "maf", "Latn" },
{ "mag", "Deva" },
{ "mai", "Deva Tirh" },
{ "mak", "Latn Bugi" },
{ "man", "Latn Nkoo" },
{ "mas", "Latn" },
{ "mde", "Arab Latn" },
{ "mdf", "Cyrl" },
{ "mdr", "Latn Bugi" },
{ "men", "Latn Mend" },
{ "mer", "Latn" },
{ "mfe", "Latn" },
{ "mg", "Latn" },
{ "mga", "Latn" },
{ "mgh", "Latn" },
{ "mgo", "Latn" },
{ "mh", "Latn" },
{ "mhr", "Cyrl" },
{ "mi", "Latn" },
{ "mic", "Latn" },
{ "min", "Latn" },
{ "miq", "Latn" },
{ "mjw", "Latn" },
{ "mk", "Cyrl" },
{ "ml", "Mlym" },
{ "mn", "Cyrl Mong Phag" },
{ "mnc", "Mong" },
{ "mni", "Beng Mtei" },
{ "mnw", "Mymr" },
{ "mos", "Latn" },
{ "moh", "Latn" },
{ "mr", "Deva Modi" },
{ "mrj", "Cyrl" },
{ "ms", "Latn Arab" },
{ "mt", "Latn" },
{ "mua", "Latn" },
{ "mus", "Latn" },
{ "mwl", "Latn" },
{ "mwr", "Deva" },
{ "mwv", "Latn" },
{ "my", "Mymr" },
{ "mye", "Latn" },
{ "myv", "Cyrl" },
{ "mzn", "Arab" },
{ "na", "Latn" },
{ "nah", "Latn" },
{ "nan", "Hans Hant Hani" },
{ "nap", "Latn" },
{ "naq", "Latn" },
{ "nan", "Latn Hans Hant Hani" },
{ "nb", "Latn" },
{ "nd", "Latn" },
{ "nds", "Latn" },
{ "ne", "Deva" },
{ "new", "Deva" },
{ "nhn", "Latn" },
{ "ng", "Latn" },
{ "nia", "Latn" },
{ "niu", "Latn" },
{ "njo", "Latn" },
{ "nl", "Latn" },
{ "nmg", "Latn" },
{ "nn", "Latn" },
{ "nnh", "Latn" },
{ "nog", "Cyrl" },
{ "non", "Runr" },
{ "nov", "Latn" },
{ "nqo", "Nkoo" },
{ "nr", "Latn" },
{ "nso", "Latn" },
{ "nus", "Latn" },
{ "nv", "Latn" },
{ "nwc", "Ranj Newa Deva Sidd Brah" },
{ "ny", "Latn" },
{ "nym", "Latn" },
{ "nyn", "Latn" },
{ "nyo", "Latn" },
{ "nzi", "Latn" },
{ "oc", "Latn" },
{ "oj", "Cans Latn" },
{ "om", "Latn Ethi" },
{ "or", "Orya" },
{ "os", "Cyrl" },
{ "osa", "Osge Latn" },
{ "ota", "Arab" },
{ "pa", "Guru Arab" },
{ "pag", "Latn" },
{ "pal", "Phli Phlp" },
{ "pam", "Latn" },
{ "pap", "Latn" },
{ "pau", "Latn" },
{ "pcd", "Latn" },
{ "pcm", "Latn" },
{ "pdc", "Latn" },
{ "pdt", "Latn" },
{ "peo", "Xpeo" },
{ "pfl", "Latn" },
{ "phn", "Phnx" },
{ "pi", "Latn Deva Mymr Sinh Thai" },
{ "pl", "Latn" },
{ "pms", "Latn" },
{ "pnt", "Grek Cyrl Latn" },
{ "pon", "Latn" },
{ "pr", "Latn" },
{ "prg", "Latn" },
{ "pro", "Latn" },
{ "prs", "Arab" },
{ "ps", "Arab" },
{ "pt", "Latn" },
{ "qu", "Latn" },
{ "quc", "Latn" },
{ "qug", "Latn" },
{ "quy", "Latn" },
{ "quz", "Latn" },
{ "raj", "Deva" },
{ "rap", "Latn" },
{ "rar", "Latn" },
{ "rgn", "Latn" },
{ "rif", "Latn Tfng" },
{ "rm", "Latn" },
{ "rn", "Latn" },
{ "ro", "Latn Cyrl" },
{ "rof", "Latn" },
{ "rom", "Latn Cyrl" },
{ "rtm", "Latn" },
{ "ru", "Cyrl" },
{ "rue", "Cyrl" },
{ "rug", "Latn" },
{ "rup", "Latn" },
{ "rw", "Latn" },
{ "rwk", "Latn" },
{ "sa", "Deva Gran Shrd Sidd Sinh" },
{ "sad", "Latn" },
{ "sah", "Cyrl" },
{ "sam", "Samr Hebr" },
{ "saq", "Latn" },
{ "sas", "Latn" },
{ "sat", "Olck Beng Deva Latn Orya" },
{ "saz", "Saur" },
{ "sba", "Latn" },
{ "sbp", "Latn" },
{ "sc", "Latn" },
{ "scn", "Latn" },
{ "sco", "Latn" },
{ "sd", "Arab Deva Khoj Sind" },
{ "sdc", "Latn" },
{ "sdh", "Arab" },
{ "se", "Latn Cyrl Arab" },
{ "see", "Latn" },
{ "seh", "Latn" },
{ "sei", "Latn" },
{ "sel", "Cyrl" },
{ "ses", "Latn" },
{ "sg", "Latn" },
{ "sga", "Latn Ogam" },
{ "sgs", "Latn" },
{ "sh", "Latn Cyrl" },
{ "shi", "Tfng Latn Arab" },
{ "shn", "Mymr" },
{ "shs", "Latn Dupl" },
{ "shu", "Arab" },
{ "si", "Sinh" },
{ "sid", "Latn" },
{ "sk", "Latn" },
{ "sl", "Latn" },
{ "sli", "Latn" },
{ "sly", "Latn" },
{ "sm", "Latn" },
{ "sma", "Latn" },
{ "smj", "Latn" },
{ "smn", "Latn" },
{ "sms", "Latn" },
{ "sn", "Latn" },
{ "snk", "Latn" },
{ "so", "Latn Arab Osma" },
{ "sog", "Sogd Syrc Mani" },
{ "son", "Latn Arab" },
{ "sq", "Latn Elba" },
{ "sr", "Cyrl Latn" },
{ "srn", "Latn" },
{ "srr", "Latn" },
{ "ss", "Latn" },
{ "ssy", "Latn" },
{ "st", "Latn" },
{ "stq", "Latn" },
{ "su", "Latn Sund" },
{ "suk", "Latn" },
{ "sus", "Latn Arab" },
{ "sux", "Xsux" },
{ "sv", "Latn" },
{ "sw", "Latn" },
{ "swb", "Arab Latn" },
{ "swc", "Arab Latn" },
{ "syc", "Syrc" },
{ "syr", "Syrc" },
{ "szl", "Latn" },
{ "ta", "Taml" },
{ "tcy", "Knda" },
{ "te", "Telu" },
{ "tem", "Latn" },
{ "teo", "Latn" },
{ "ter", "Latn" },
{ "tet", "Latn" },
{ "tg", "Cyrl Arab Latn" },
{ "th", "Thai" },
{ "the", "Deva" },
{ "ti", "Ethi" },
{ "tig", "Ethi" },
{ "tiv", "Latn" },
{ "tk", "Latn Arab Cyrl" },
{ "tkl", "Latn" },
{ "tkr", "Latn Cyrl" },
{ "tl", "Latn Arab Blis" },
{ "tlh", "Piqd Latn" },
{ "tli", "Latn" },
{ "tly", "Latn Arab Cyrl" },
{ "tmh", "Latn" },
{ "tn", "Latn" },
{ "to", "Latn" },
{ "tog", "Latn" },
{ "tpi", "Latn" },
{ "tr", "Latn Arab" },
{ "tru", "Latn Syrc" },
{ "trv", "Latn" },
{ "ts", "Latn" },
{ "tsd", "Grek" },
{ "tsi", "Latn" },
{ "tt", "Cyrl" },
{ "ttt", "Latn Arab Cyrl" },
{ "tum", "Latn" },
{ "tvl", "Latn" },
{ "tw", "Latn" },
{ "twq", "Latn" },
{ "ty", "Latn" },
{ "tyv", "Cyrl" },
{ "tzm", "Latn Tfng" },
{ "udm", "Cyrl Latn" },
{ "ug", "Arab Cyrl Latn" },
{ "uga", "Ugar" },
{ "uk", "Cyrl" },
{ "umb", "Latn" },
{ "unm", "Latn" },
{ "ur", "Arab" },
{ "uz", "Latn Cyrl Arab" },
{ "vai", "Vaii Latn" },
{ "ve", "Latn" },
{ "vec", "Latn" },
{ "vep", "Latn" },
{ "vi", "Latn Hani" },
{ "vls", "Latn" },
{ "vmf", "Latn" },
{ "vo", "Latn" },
{ "vot", "Latn" },
{ "vro", "Latn" },
{ "vun", "Latn" },
{ "wa", "Latn" },
{ "wae", "Latn" },
{ "wal", "Ethi" },
{ "war", "Latn" },
{ "was", "Latn" },
{ "wbp", "Latn" },
{ "wo", "Latn Arab" },
{ "wuu", "Hans Hani" },
{ "xal", "Cyrl" },
{ "xh", "Latn" },
{ "xmf", "Geor" },
{ "xog", "Latn" },
{ "yao", "Latn" },
{ "yap", "Latn" },
{ "yav", "Latn" },
{ "ybb", "Latn" },
{ "yi", "Hebr" },
{ "yo", "Latn" },
{ "yrl", "Latn" },
{ "yue", "Hant Hans Hani" },
{ "yuw", "Latn" },
{ "za", "Latn Hans Hani" },
{ "zap", "Latn" },
{ "zbl", "Blis" },
{ "zea", "Latn" },
{ "zen", "Tfng" },
{ "zgh", "Tfng" },
{ "zh", "Hans Hant Hani Bopo Latn Phag" },
{ "zu", "Latn" },
{ "zun", "Latn" },
{ "zza", "Latn" },
{ nullptr, nullptr },
};
// Additional regional variants.

View File

@@ -89,6 +89,18 @@ void TranslationServer::init_locale_info() {
idx++;
}
// Init locale scripts.
language_script_map.clear();
idx = 0;
while (language_script_list[idx][0] != nullptr) {
HashSet<String> &set = language_script_map[language_script_list[idx][0]];
Vector<String> scripts = String(language_script_list[idx][1]).split(" ");
for (const String &s : scripts) {
set.insert(s);
}
idx++;
}
// Init country names.
country_name_map.clear();
idx = 0;
@@ -492,6 +504,17 @@ String TranslationServer::get_fallback_locale() const {
return fallback;
}
bool TranslationServer::is_script_suppored_by_locale(const String &p_locale, const String &p_script) const {
Locale l = Locale(*this, p_locale, true);
if (l.script == p_script) {
return true;
}
if (!language_script_map.has(l.language)) {
return false;
}
return language_script_map[l.language].has(p_script);
}
PackedStringArray TranslationServer::get_loaded_locales() const {
return main_domain->get_loaded_locales();
}

View File

@@ -92,6 +92,7 @@ class TranslationServer : public Object {
static inline HashMap<String, String> variant_map;
static inline HashMap<String, String> plural_rules_map;
static inline HashMap<String, int> num_system_map;
static inline HashMap<String, HashSet<String>> language_script_map;
void init_locale_info();
@@ -132,6 +133,8 @@ public:
String get_locale_name(const String &p_locale) const;
String get_plural_rules(const String &p_locale) const;
bool is_script_suppored_by_locale(const String &p_locale, const String &p_script) const;
PackedStringArray get_loaded_locales() const;
void add_translation(const Ref<Translation> &p_translation);