UPDATE: Adds bindings to update timezone and locale

UPDATE: Update "generate locale" utility

FIX: Minor fixes to UI and proper support for locales/timezones

UPDATE: Adds "display language" setting to core
This commit is contained in:
Nicolás Hatcher
2025-11-28 21:21:19 +01:00
parent 402a13bd00
commit ffe5d1a158
109 changed files with 4783 additions and 3216 deletions

View File

@@ -1,6 +1,12 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
version = 4
[[package]]
name = "arrayvec"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
[[package]]
name = "atty"
@@ -15,9 +21,33 @@ dependencies = [
[[package]]
name = "autocfg"
version = "1.1.0"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
[[package]]
name = "bitcode"
version = "0.6.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "648bd963d2e5d465377acecfb4b827f9f553b6bc97a8f61715779e9ed9e52b74"
dependencies = [
"arrayvec",
"bitcode_derive",
"bytemuck",
"glam",
"serde",
]
[[package]]
name = "bitcode_derive"
version = "0.6.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffebfc2d28a12b262c303cb3860ee77b91bd83b1f20f0bd2a9693008e2f55a9e"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.111",
]
[[package]]
name = "bitflags"
@@ -26,10 +56,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "clap"
version = "3.2.22"
name = "bytemuck"
version = "1.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86447ad904c7fb335a790c9d7fe3d0d971dc523b8ccd1561a520de9a85302750"
checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4"
[[package]]
name = "clap"
version = "3.2.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123"
dependencies = [
"atty",
"bitflags",
@@ -44,15 +80,15 @@ dependencies = [
[[package]]
name = "clap_derive"
version = "3.2.18"
version = "3.2.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65"
checksum = "ae6371b8bdc8b7d3959e9cf7b22d4435ef3e79e138688421ec654acf8c81b008"
dependencies = [
"heck",
"proc-macro-error",
"proc-macro2",
"quote",
"syn",
"syn 1.0.109",
]
[[package]]
@@ -68,11 +104,18 @@ dependencies = [
name = "generate_locale"
version = "0.1.0"
dependencies = [
"bitcode",
"clap",
"serde",
"serde_json",
]
[[package]]
name = "glam"
version = "0.30.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd47b05dddf0005d850e5644cae7f2b14ac3df487979dbfff3b56f20b1a6ae46"
[[package]]
name = "hashbrown"
version = "0.12.3"
@@ -81,9 +124,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]]
name = "heck"
version = "0.4.0"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
[[package]]
name = "hermit-abi"
@@ -96,9 +139,9 @@ dependencies = [
[[package]]
name = "indexmap"
version = "1.9.1"
version = "1.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e"
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
dependencies = [
"autocfg",
"hashbrown",
@@ -106,27 +149,33 @@ dependencies = [
[[package]]
name = "itoa"
version = "1.0.3"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754"
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
[[package]]
name = "libc"
version = "0.2.132"
version = "0.2.177"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5"
checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976"
[[package]]
name = "memchr"
version = "2.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
[[package]]
name = "once_cell"
version = "1.14.0"
version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
[[package]]
name = "os_str_bytes"
version = "6.3.0"
version = "6.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ff7415e9ae3fff1225851df9e0d9e4e5479f947619774677a63572e55e80eff"
checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1"
[[package]]
name = "proc-macro-error"
@@ -137,7 +186,7 @@ dependencies = [
"proc-macro-error-attr",
"proc-macro2",
"quote",
"syn",
"syn 1.0.109",
"version_check",
]
@@ -154,57 +203,69 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.43"
version = "1.0.103"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab"
checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.21"
version = "1.0.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f"
dependencies = [
"proc-macro2",
]
[[package]]
name = "ryu"
version = "1.0.11"
version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
[[package]]
name = "serde"
version = "1.0.144"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860"
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
dependencies = [
"serde_core",
"serde_derive",
]
[[package]]
name = "serde_core"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.144"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94ed3a816fb1d101812f83e789f888322c34e291f894f19590dc310963e87a00"
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.111",
]
[[package]]
name = "serde_json"
version = "1.0.85"
version = "1.0.145"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44"
checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c"
dependencies = [
"itoa",
"memchr",
"ryu",
"serde",
"serde_core",
]
[[package]]
@@ -215,9 +276,20 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "syn"
version = "1.0.100"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52205623b1b0f064a4e71182c3b18ae902267282930c6d5462c91b859668426e"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn"
version = "2.0.111"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87"
dependencies = [
"proc-macro2",
"quote",
@@ -226,30 +298,30 @@ dependencies = [
[[package]]
name = "termcolor"
version = "1.1.3"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755"
dependencies = [
"winapi-util",
]
[[package]]
name = "textwrap"
version = "0.15.1"
version = "0.16.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "949517c0cf1bf4ee812e2e07e08ab448e3ae0d23472aee8a06c985f0c8815b16"
checksum = "c13547615a44dc9c452a8a534638acdf07120d4b6847c8178705da06306a3057"
[[package]]
name = "unicode-ident"
version = "1.0.4"
version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd"
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
[[package]]
name = "version_check"
version = "0.9.4"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "winapi"
@@ -269,11 +341,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
dependencies = [
"winapi",
"windows-sys",
]
[[package]]
@@ -281,3 +353,18 @@ name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-link"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
[[package]]
name = "windows-sys"
version = "0.61.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
dependencies = [
"windows-link",
]

View File

@@ -10,3 +10,5 @@ edition = "2021"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
clap = { version = "3.2.22", features = ["derive"] }
bitcode = "0.6.3"

View File

@@ -1,3 +1,3 @@
[
"en", "en-GB", "de", "es"
"en", "en-GB", "de", "es", "fr"
]

View File

@@ -1,21 +1,22 @@
use bitcode::Encode;
use serde::{Deserialize, Serialize};
pub const LOCAL_TYPE: &str = "modern"; // or "full"
pub const LOCAL_TYPE: &str = "full"; // or "modern"
#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Encode)]
pub struct Locale {
pub dates: Dates,
pub numbers: NumbersProperties,
pub currency: Currency
pub currency: Currency,
}
#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Encode)]
pub struct Currency {
pub iso: String,
pub symbol: String,
}
#[derive(Serialize, Deserialize, Clone)]
#[derive(Serialize, Deserialize, Encode, Clone)]
pub struct NumbersProperties {
#[serde(rename = "symbols-numberSystem-latn")]
pub symbols: NumbersSymbols,
@@ -25,16 +26,19 @@ pub struct NumbersProperties {
pub currency_formats: CurrencyFormats,
}
#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Encode)]
pub struct Dates {
pub day_names: Vec<String>,
pub day_names_short: Vec<String>,
pub months: Vec<String>,
pub months_short: Vec<String>,
pub months_letter: Vec<String>,
pub date_formats: DateFormats,
pub time_formats: DateFormats,
pub date_time_formats: DateFormats,
}
#[derive(Serialize, Deserialize, Clone)]
#[derive(Serialize, Deserialize, Encode, Clone)]
#[serde(rename_all = "camelCase")]
pub struct NumbersSymbols {
pub decimal: String,
@@ -52,10 +56,8 @@ pub struct NumbersSymbols {
pub time_separator: String,
}
// See: https://cldr.unicode.org/translation/number-currency-formats/number-and-currency-patterns
#[derive(Serialize, Deserialize, Clone)]
#[derive(Serialize, Deserialize, Encode, Clone)]
pub struct CurrencyFormats {
pub standard: String,
#[serde(rename = "standard-alphaNextToNumber")]
@@ -71,8 +73,16 @@ pub struct CurrencyFormats {
pub accounting_no_currency: String,
}
#[derive(Serialize, Deserialize, Clone)]
#[derive(Serialize, Deserialize, Encode, Clone)]
#[serde(rename_all = "camelCase")]
pub struct DecimalFormats {
pub standard: String,
}
#[derive(Serialize, Deserialize, Encode, Clone)]
pub struct DateFormats {
full: String,
long: String,
medium: String,
short: String,
}

View File

@@ -1,37 +1,43 @@
use std::collections::HashMap;
use std::fs;
use bitcode::Encode;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use crate::constants::{Dates, LOCAL_TYPE};
use crate::constants::{DateFormats, Dates, LOCAL_TYPE};
#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Encode)]
struct CaGCalendarsFormat {
format: HashMap<String, HashMap<String, String>>,
}
#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Encode)]
struct CaGCalendarsII {
months: CaGCalendarsFormat,
days: CaGCalendarsFormat,
#[serde(rename = "dateFormats")]
date_formats: DateFormats,
#[serde(rename = "timeFormats")]
time_formats: DateFormats,
#[serde(rename = "dateTimeFormats")]
date_time_formats: DateFormats,
}
#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Encode)]
struct CaGCalendarsI {
gregorian: CaGCalendarsII,
}
#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Encode)]
struct CaGCalendars {
calendars: CaGCalendarsI,
}
#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Encode)]
struct CaGId {
identity: Value,
// identity: Value,
dates: CaGCalendars,
}
#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Encode)]
struct CaGregorian {
main: HashMap<String, CaGId>,
}
@@ -42,6 +48,7 @@ pub fn get_dates_formatting(cldr_dir: &str, locale_id: &str) -> Result<Dates, &'
cldr_dir, LOCAL_TYPE, locale_id
);
println!("Reading dates from file: {}", calendar_file);
let contents =
fs::read_to_string(calendar_file).or(Err("Failed reading 'ca-gregorian' file"))?;
let ca_gregorian: CaGregorian =
@@ -51,6 +58,7 @@ pub fn get_dates_formatting(cldr_dir: &str, locale_id: &str) -> Result<Dates, &'
// for the difference between stand-alone and format. We will use only the format mode
let months_format = &gregorian.months.format;
let days_format = &gregorian.days.format;
let mut day_names = vec![];
let mut day_names_short = vec![];
@@ -79,5 +87,8 @@ pub fn get_dates_formatting(cldr_dir: &str, locale_id: &str) -> Result<Dates, &'
months,
months_short,
months_letter,
date_formats: gregorian.date_formats.clone(),
time_formats: gregorian.time_formats.clone(),
date_time_formats: gregorian.date_time_formats.clone(),
})
}

View File

@@ -1,7 +1,7 @@
use std::fs;
use std::{collections::HashMap, io::Write, path::PathBuf};
use constants::{Locale, Currency};
use constants::{Currency, Locale};
use clap::Parser;
use numbers::get_numbers_formatting;
@@ -34,8 +34,13 @@ fn main() -> Result<(), String> {
let opt = Opt::from_args();
let cldr_dir = opt.cldr_dir;
let locales_list: Vec<String> = if let Some(locales_path) = opt.locales {
let contents = fs::read_to_string(locales_path).or(Err("Failed reading file"))?;
serde_json::from_str(&contents).or(Err("Failed parsing file"))?
let locales_path_str = locales_path.display().to_string();
let contents = fs::read_to_string(locales_path)
.or(Err(format!("Failed reading file: {}", locales_path_str)))?;
serde_json::from_str(&contents).or(Err(format!(
"Failed parsing locales file: {}",
locales_path_str
)))?
} else {
get_all_locales_id(&cldr_dir)
};
@@ -49,13 +54,27 @@ fn main() -> Result<(), String> {
// We just stick here one and make this adaptable in the calc module for now
let currency = Currency {
iso: "USD".to_string(),
symbol: "$".to_string()
symbol: "$".to_string(),
};
locales.insert(locale_id, Locale { dates, numbers, currency });
locales.insert(
locale_id,
Locale {
dates,
numbers,
currency,
},
);
}
let s = serde_json::to_string(&locales).or(Err("Failed to stringify data"))?;
let mut f = fs::File::create(opt.output).or(Err("Failed to create file"))?;
f.write_all(s.as_bytes()).or(Err("Failed writing"))?;
// save to locales.bin using bitcode
let bytes = bitcode::encode(&locales);
let mut f_bin = fs::File::create("locales.bin").or(Err("Failed to create locales.bin"))?;
f_bin
.write_all(&bytes)
.or(Err("Failed writing locales.bin"))?;
Ok(())
}

View File

@@ -1,28 +1,29 @@
use std::collections::HashMap;
use std::fs;
use bitcode::Encode;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use crate::constants::{NumbersProperties, LOCAL_TYPE};
#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Encode)]
struct CaGCalendarsFormat {
format: HashMap<String, HashMap<String, String>>,
}
#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Encode)]
struct CaGCalendarsII {
months: CaGCalendarsFormat,
days: CaGCalendarsFormat,
}
#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Encode)]
struct NumbersJSONId {
identity: Value,
// identity: Value,
numbers: NumbersProperties,
}
#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Encode)]
struct NumbersJSON {
main: HashMap<String, NumbersJSONId>,
}