Skip to main content

ironcalc_base/locale/
mod.rs

1use std::{collections::HashMap, sync::OnceLock};
2
3use bitcode::{Decode, Encode};
4
5#[derive(Encode, Decode)]
6pub struct Locale {
7    pub dates: Dates,
8    pub numbers: NumbersProperties,
9    pub currency: Currency,
10}
11
12#[derive(Encode, Decode)]
13pub struct Currency {
14    pub iso: String,
15    pub symbol: String,
16}
17
18#[derive(Encode, Decode)]
19pub struct NumbersProperties {
20    pub symbols: NumbersSymbols,
21    pub decimal_formats: DecimalFormats,
22    pub currency_formats: CurrencyFormats,
23}
24
25#[derive(Encode, Decode)]
26pub struct Dates {
27    pub day_names: Vec<String>,
28    pub day_names_short: Vec<String>,
29    pub months: Vec<String>,
30    pub months_short: Vec<String>,
31    pub months_letter: Vec<String>,
32    pub date_formats: DateFormats,
33    pub time_formats: DateFormats,
34    pub date_time_formats: DateFormats,
35}
36
37#[derive(Encode, Decode)]
38pub struct NumbersSymbols {
39    pub decimal: String,
40    pub group: String,
41    pub list: String,
42    pub percent_sign: String,
43    pub plus_sign: String,
44    pub minus_sign: String,
45    pub approximately_sign: String,
46    pub exponential: String,
47    pub superscripting_exponent: String,
48    pub per_mille: String,
49    pub infinity: String,
50    pub nan: String,
51    pub time_separator: String,
52}
53
54// See: https://cldr.unicode.org/translation/number-currency-formats/number-and-currency-patterns
55#[derive(Encode, Decode)]
56pub struct CurrencyFormats {
57    pub standard: String,
58    pub standard_alpha_next_to_number: Option<String>,
59    pub standard_no_currency: String,
60    pub accounting: String,
61    pub accounting_alpha_next_to_number: Option<String>,
62    pub accounting_no_currency: String,
63}
64
65#[derive(Encode, Decode)]
66pub struct DecimalFormats {
67    pub standard: String,
68}
69
70#[derive(Encode, Decode)]
71pub struct DateFormats {
72    pub full: String,
73    pub long: String,
74    pub medium: String,
75    pub short: String,
76}
77
78#[derive(Encode, Decode)]
79pub struct TimeFormats {
80    pub full: String,
81    pub long: String,
82    pub medium: String,
83    pub short: String,
84}
85
86pub fn get_default_locale() -> &'static Locale {
87    #[allow(clippy::unwrap_used)]
88    get_locale("en").unwrap()
89}
90
91static LOCALES: OnceLock<HashMap<String, Locale>> = OnceLock::new();
92
93#[allow(clippy::expect_used)]
94fn get_locales() -> &'static HashMap<String, Locale> {
95    LOCALES.get_or_init(|| {
96        bitcode::decode(include_bytes!("locales.bin")).expect("Failed parsing locale")
97    })
98}
99
100/// Get all available locale IDs.
101pub fn get_supported_locales() -> Vec<String> {
102    get_locales().keys().cloned().collect()
103}
104
105pub fn get_locale(id: &str) -> Result<&'static Locale, String> {
106    get_locales()
107        .get(id)
108        .ok_or_else(|| format!("Invalid locale: '{id}'"))
109}