Update lang.rs - Splits ambiguous pt into pt-pt and pt-br (#16155)

* Update lang.rs - Splits ambiguous pt into pt-pt and pt-br

Splits the ambiguous "Português" entry into two explicit options: Português (Portugal) [pt-pt] and Português (Brasil) [pt-br]. The pt_PT.rs translation file already existed in the repo (fully translated, key-complete) but was never wired into lang.rs. Kept the old "pt" and "br" locale codes mapped to ptbr::T for backward compatibility with existing user configs.

* Preserve pt-PT/pt-BR region in automatic locale resolution

Preserve pt-PT/pt-BR region in automatic locale resolution

* Fix pt-pt detection: check region suffix instead of redundant "pt" substring

Fix pt-pt detection: check region suffix instead of redundant "pt" substring

* Normalize legacy pt/br saved lang option to pt-br

Normalize legacy pt/br saved lang option to pt-br

* Normalize legacy pt/br lang option on Web client

* Add regression tests for pt-pt/pt-br locale resolution

* Follow CLDR inheritance for Portuguese regional locales (pt-AO, pt-MZ, etc.)
This commit is contained in:
Ricardo Simões authored and GitHub committed 2026-09-22 16:31:23 +08:00
1 parent 458ffe44c6
commit c6a358afbe
3 files changed
+48 -2

No files matched your search

+40 -1
View File
@@ -34,6 +34,7 @@ mod nb;
mod nl;
mod pl;
mod ptbr;
mod pt_PT;
mod ro;
mod ru;
mod sc;
@@ -63,7 +64,8 @@ pub const LANGS: &[(&str, &str)] = &[
("nb", "Norsk bokmål"),
("zh-cn", "简体中文"),
("zh-tw", "繁體中文"),
("pt", "Português"),
("pt-pt", "Português (Portugal)"),
("pt-br", "Português (Brasil)"),
("es", "Español"),
("et", "Eesti keel"),
("eu", "Euskara"),
@@ -143,6 +145,21 @@ fn resolve_lang(saved_lang: &str, locale: &str, cjk_fallback: bool) -> String {
.to_owned();
}
}
if lang.is_empty() {
// pt_PT on Linux, pt-PT on mac, pt_PT on Android.
// Per CLDR locale inheritance, every Portuguese-speaking locale
// besides bare "pt" and Brazil's own variants (pt-BR/pt_BR) has
// pt-PT as its parent (Angola, Mozambique, Cape Verde, etc.),
// so it should resolve to European Portuguese.
if locale.starts_with("pt") {
lang = (if locale == "pt" || locale.starts_with("pt-br") || locale.starts_with("pt_br") {
"pt-br"
} else {
"pt-pt"
})
.to_owned();
}
}
if lang.is_empty() {
lang = locale
.split("-")
@@ -187,6 +204,8 @@ pub fn translate_locale(name: String, locale: &str) -> String {
"id" => id::T.deref(),
"br" => ptbr::T.deref(),
"pt" => ptbr::T.deref(),
"pt-br" => ptbr::T.deref(),
"pt-pt" => pt_PT::T.deref(),
"tr" => tr::T.deref(),
"cs" => cs::T.deref(),
"da" => da::T.deref(),
@@ -344,4 +363,24 @@ mod test {
assert_eq!(f("", "zh_TW", false), "zh-tw");
assert_eq!(f("", "ja-JP", false), "ja");
}
#[test]
fn test_resolve_lang_detects_pt_pt_and_pt_br_from_locale() {
use super::resolve_lang as f;
assert_eq!(f("", "pt-PT", false), "pt-pt");
assert_eq!(f("", "pt_PT", false), "pt-pt");
assert_eq!(f("", "pt-BR", false), "pt-br");
assert_eq!(f("", "pt_BR", false), "pt-br");
assert_eq!(f("", "pt-AO", false), "pt-pt");
assert_eq!(f("", "pt-MZ", false), "pt-pt");
}
#[test]
fn test_resolve_lang_saved_lang_takes_precedence_over_locale() {
use super::resolve_lang as f;
assert_eq!(f("pt-br", "pt-PT", false), "pt-br");
assert_eq!(f("pt-pt", "pt-BR", false), "pt-pt");
}
}