mirror of
https://github.com/storytold/cadcraft.git
synced 2026-11-15 02:15:21 -06:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
deff6cb092 | ||
|
|
67514021ae |
@@ -62,6 +62,7 @@ Generated-in-code assets are original and have no file to list:
|
||||
| Asset | Author | Source | Licence | Notes |
|
||||
|---|---|---|---|---|
|
||||
| `crates/ui-egui/src/i18n/uk.tsv` | @dmatviichuk | Original Ukrainian translations of CADCraft English strings | MIT OR Apache-2.0 (`LICENSE-MIT`, `LICENSE-APACHE`) | No proprietary localization resources copied |
|
||||
| `crates/ui-egui/src/i18n/pl.tsv` | @neronek22 (Echo Rozumu & Gadajło; AI-assisted) | Original Polish translations of CADCraft English strings | MIT OR Apache-2.0 (`LICENSE-MIT`, `LICENSE-APACHE`) | No proprietary localization resources copied |
|
||||
| `crates/ui-egui/src/i18n/de.tsv` | the CADCraft contributors | Original German translations of CADCraft English strings | MIT OR Apache-2.0 (`LICENSE-MIT`, `LICENSE-APACHE`) | No proprietary localization resources copied |
|
||||
| `crates/ui-egui/src/i18n/es.tsv` | @PedroGuille | Original Spanish translations of CADCraft English strings | MIT OR Apache-2.0 (`LICENSE-MIT`, `LICENSE-APACHE`) | No proprietary localization resources copied |
|
||||
| `crates/ui-egui/src/i18n/pt_br.tsv` | @WladmirJunior | Original Brazilian Portuguese translations of CADCraft English strings | MIT OR Apache-2.0 (`LICENSE-MIT`, `LICENSE-APACHE`) | No proprietary localization resources copied |
|
||||
|
||||
@@ -19,6 +19,8 @@ pub enum Preference {
|
||||
Greek,
|
||||
#[serde(rename = "uk")]
|
||||
Ukrainian,
|
||||
#[serde(rename = "pl")]
|
||||
Polish,
|
||||
#[serde(rename = "pt-BR")]
|
||||
BrazilianPortuguese,
|
||||
#[serde(rename = "de")]
|
||||
@@ -52,13 +54,13 @@ pub enum Preference {
|
||||
#[serde(rename = "vi")]
|
||||
Vietnamese,
|
||||
}
|
||||
|
||||
impl Preference {
|
||||
pub const ALL: [Self; 20] = [
|
||||
pub const ALL: [Self; 21] = [
|
||||
Self::Auto,
|
||||
Self::English,
|
||||
Self::Greek,
|
||||
Self::Ukrainian,
|
||||
Self::Polish,
|
||||
Self::BrazilianPortuguese,
|
||||
Self::German,
|
||||
Self::Spanish,
|
||||
@@ -109,6 +111,7 @@ impl Preference {
|
||||
Self::English => "en",
|
||||
Self::Greek => "el",
|
||||
Self::Ukrainian => "uk",
|
||||
Self::Polish => "pl",
|
||||
Self::BrazilianPortuguese => "pt-BR",
|
||||
Self::German => "de",
|
||||
Self::Spanish => "es",
|
||||
@@ -134,6 +137,7 @@ impl Preference {
|
||||
Self::English => "English",
|
||||
Self::Greek => "Ελληνικά",
|
||||
Self::Ukrainian => "Українська",
|
||||
Self::Polish => "Polski",
|
||||
Self::BrazilianPortuguese => "Português (Brasil)",
|
||||
Self::German => "Deutsch",
|
||||
Self::Spanish => "Español",
|
||||
@@ -188,6 +192,7 @@ impl Preference {
|
||||
Self::English => "en",
|
||||
Self::Greek => "el",
|
||||
Self::Ukrainian => "uk",
|
||||
Self::Polish => "pl",
|
||||
Self::BrazilianPortuguese => "pt-BR",
|
||||
Self::German => "de",
|
||||
Self::Spanish => "es",
|
||||
@@ -220,8 +225,9 @@ pub struct Language {
|
||||
catalog: OnceLock<Catalog<'static>>,
|
||||
}
|
||||
|
||||
pub static LANGUAGES: [Language; 19] = [
|
||||
pub static LANGUAGES: [Language; 20] = [
|
||||
Language { code: "en", name: "English", source: "", plural: plural_en, plural_forms: 2, catalog: OnceLock::new() },
|
||||
Language { code: "pl", name: "Polski", source: include_str!("i18n/pl.tsv"), plural: plural_pl, plural_forms: 3, catalog: OnceLock::new() },
|
||||
// Greek: one for exactly 1; other for zero and all other integer counts.
|
||||
Language {
|
||||
code: "el", name: "Ελληνικά", source: include_str!("i18n/el.tsv"), plural: plural_en, plural_forms: 2, catalog: OnceLock::new()
|
||||
@@ -375,6 +381,17 @@ pub fn format(source: &str, values: &[(&str, String)]) -> String {
|
||||
result
|
||||
}
|
||||
|
||||
/// Polish plurals: one (1), few (2–4, 22–24), many (0, 5–21, 25–31).
|
||||
pub fn plural_pl(n: u64) -> usize {
|
||||
if n == 1 {
|
||||
0
|
||||
} else if (2..=4).contains(&(n % 10)) && !(12..=14).contains(&(n % 100)) {
|
||||
1
|
||||
} else {
|
||||
2
|
||||
}
|
||||
}
|
||||
|
||||
/// Ukrainian integer plurals: one (1, 21), few (2–4, 22–24), many (0, 5–20, 25…).
|
||||
pub fn plural_uk(n: u64) -> usize {
|
||||
match (n % 10, n % 100) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -195,12 +195,20 @@ fn assert_primary_locale_aliases() {
|
||||
for (tag, code) in [("ru", "ru"), ("ru-RU", "ru"), ("ru_RU.UTF-8", "ru"), ("fr", "fr"), ("fr-FR", "fr"), ("fr_CA.UTF-8", "fr")] {
|
||||
assert_eq!(locale_language(tag), Some(code), "{tag}");
|
||||
}
|
||||
|
||||
for tag in ["ua", "ukulele", "xx-XX", "", "garbage", "💙"] {
|
||||
assert_eq!(locale_language(tag), None, "{tag}");
|
||||
}
|
||||
assert_eq!(locale_language("pl-PL"), Some("pl"));
|
||||
assert_eq!(Preference::Auto.resolve(&["pl-PL".into(), "pt-BR".into()]), "pl");
|
||||
assert_eq!(Preference::Auto.resolve(&["fr-FR".into(), "pt-BR".into()]), "fr");
|
||||
}
|
||||
|
||||
fn assert_portuguese_and_spanish_aliases() {
|
||||
for tag in ["pt", "pt-BR", "pt_BR.UTF-8", "PT-br", "pt-PT"] {
|
||||
assert_eq!(locale_language(tag), Some("pt-BR"), "{tag}");
|
||||
}
|
||||
|
||||
for tag in ["es", "es-ES", "es_MX.UTF-8", "ES-ar"] {
|
||||
assert_eq!(locale_language(tag), Some("es"), "{tag}");
|
||||
}
|
||||
@@ -228,7 +236,7 @@ fn assert_additional_locale_aliases() {
|
||||
|
||||
fn assert_unrecognized_locale_tags() {
|
||||
// Look-alike codes, three-letter codes and endonyms pick nothing: `se` is Northern Sami.
|
||||
let look_alikes = ["ua", "ukulele", "pl-PL", "", "garbage", "💙", "ptolemy", "cz", "csharp", "csomething", "italic"];
|
||||
let look_alikes = ["ua", "ukulele", "nl-NL", "", "garbage", "💙", "ptolemy", "cz", "csharp", "csomething", "italic"];
|
||||
let others = ["kr", "korean", "kotlin", "se", "swe", "svenska", "hun", "magyar", "tur", "türkçe", "elvish", "kat", "geo", "kab", "kartuli"];
|
||||
for tag in look_alikes.into_iter().chain(others) {
|
||||
assert_eq!(locale_language(tag), None, "{tag}");
|
||||
@@ -236,10 +244,11 @@ fn assert_unrecognized_locale_tags() {
|
||||
}
|
||||
|
||||
fn assert_auto_locale_precedence() {
|
||||
assert_eq!(Preference::Auto.resolve(&["pl-PL".into(), "pt-BR".into()]), "pt-BR");
|
||||
assert_eq!(Preference::Auto.resolve(&["nl-NL".into(), "pt-BR".into()]), "pt-BR");
|
||||
assert_eq!(Preference::Auto.resolve(&["pl-PL".into(), "pt-BR".into()]), "pl");
|
||||
assert_eq!(Preference::Auto.resolve(&["fr-FR".into(), "pt-BR".into()]), "fr");
|
||||
assert_eq!(Preference::Auto.resolve(&["es-ES".into(), "pt-BR".into()]), "es");
|
||||
let locales = vec!["pl-PL".into(), "uk-UA".into(), "en-US".into()];
|
||||
let locales = vec!["nl-NL".into(), "uk-UA".into(), "en-US".into()];
|
||||
assert_eq!(Preference::Auto.resolve(&locales), "uk");
|
||||
assert_eq!(Preference::English.resolve(&locales), "en");
|
||||
assert_eq!(Preference::Auto.resolve(&["en-US".into(), "uk-UA".into()]), "en");
|
||||
@@ -262,7 +271,7 @@ fn assert_preference_resolution(preference: Preference) {
|
||||
// A chosen language wins over the system's; Auto takes the first system language there is.
|
||||
assert_eq!(preference.resolve(&["uk-UA".into()]), preference.code());
|
||||
if preference != Preference::English {
|
||||
assert_eq!(Preference::Auto.resolve(&["pl-PL".into(), preference.code().into(), "en-US".into()]), preference.code());
|
||||
assert_eq!(Preference::Auto.resolve(&["nl-NL".into(), preference.code().into(), "en-US".into()]), preference.code());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,6 +288,8 @@ fn assert_saved_preference_persistence(preference: Preference) {
|
||||
#[test]
|
||||
fn locale_and_saved_preference_resolution() {
|
||||
assert_primary_locale_aliases();
|
||||
assert_eq!(locale_language("pl-PL"), Some("pl"));
|
||||
assert_eq!(Preference::parse("pl"), Some(Preference::Polish));
|
||||
assert_portuguese_and_spanish_aliases();
|
||||
assert_additional_locale_aliases();
|
||||
assert_unrecognized_locale_tags();
|
||||
@@ -668,3 +679,11 @@ fn vietnamese_takes_one_form_and_needs_a_font_with_its_letters() {
|
||||
assert_eq!(Preference::Vietnamese.name(), "Vietnamese");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn polish_plural_forms() {
|
||||
for (n, expected) in [(0, 2), (1, 0), (2, 1), (4, 1), (5, 2), (12, 2), (14, 2), (21, 2), (22, 1), (24, 1), (25, 2), (101, 2), (102, 1), (112, 2)]
|
||||
{
|
||||
assert_eq!(plural_pl(n), expected, "n={n}");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user