Skip to main content

factorion_lib/
locale.rs

1#![doc = include_str!("../Locales.md")]
2use std::{borrow::Cow, collections::HashMap};
3
4#[cfg(any(feature = "serde", test))]
5use serde::{Deserialize, Serialize};
6
7#[cfg(any(feature = "serde", test))]
8pub fn get_en() -> Locale<'static> {
9    serde_json::de::from_str(include_str!("en.json")).unwrap()
10}
11#[cfg(any(feature = "serde", test))]
12pub fn get_en_fuck() -> Locale<'static> {
13    serde_json::de::from_str(include_str!("en_fuck.json")).unwrap()
14}
15#[cfg(any(feature = "serde", test))]
16pub fn get_de() -> Locale<'static> {
17    serde_json::de::from_str(include_str!("de.json")).unwrap()
18}
19#[cfg(any(feature = "serde", test))]
20pub fn get_ru() -> Locale<'static> {
21    serde_json::de::from_str(include_str!("ru.json")).unwrap()
22}
23#[cfg(any(feature = "serde", test))]
24pub fn get_it() -> Locale<'static> {
25    serde_json::de::from_str(include_str!("it.json")).unwrap()
26}
27#[cfg(any(feature = "serde", test))]
28pub fn get_all() -> impl Iterator<Item = (&'static str, Locale<'static>)> {
29    [
30        ("en", get_en()),
31        ("en_fuck", get_en_fuck()),
32        ("de", get_de()),
33        ("ru", get_ru()),
34        ("it", get_it()),
35    ]
36    .into_iter()
37}
38
39/// This can be used to retroactively add fields, that exist in all versions.
40macro_rules! get_field {
41    ($t:ty; $($var:ident),*; $field:ident: $ret:ty) => {
42        impl<'a> $t {
43            pub fn $field(&'a self) -> &'a $ret {
44                match self {
45                    $(Self::$var(this) => &this.$field),*
46                }
47            }
48        }
49    };
50}
51macro_rules! set_field {
52    ($t:ty; $($var:ident),*; $field:ident: $ret:ty) => {
53        concat_idents::concat_idents!(set_fn = set_, $field {
54            impl<'a> $t {
55                pub fn set_fn(&mut self, v: $ret) {
56                    match self {
57                        $(Self::$var(this) => this.$field = v),*
58                    }
59                }
60            }
61        });
62    };
63}
64/// This can be used to retroactively add fields, that may not exist in older versions. (currently unused)
65macro_rules! maybe_get_field {
66    ($t:ty; $($var_not:ident),*; $($var_do:ident),*; $field:ident: $ret:ty) => {
67        impl<'a> $t {
68            pub fn $field(&'a self) -> Option<&'a $ret> {
69                match self {
70                    $(Self::$var_do(this) => Some(&this.$field),)*
71                    $(Self::$var_not(_) => None,)*
72                }
73            }
74        }
75    };
76}
77macro_rules! maybe_set_field {
78    ($t:ty; $($var_not:ident),*; $($var_do:ident),*; $field:ident: $ret:ty) => {
79        concat_idents::concat_idents!(set_fn = set_, $field {
80            impl<'a> $t {
81                pub fn set_fn(&mut self, v: $ret) -> bool {
82                    match self {
83                        $(Self::$var_do(this) => {this.$field = v; true})*
84                        $(Self::$var_not(_) => false),*
85                    }
86                }
87            }
88        });
89    };
90}
91
92/// Versioned total locale
93///
94/// Use the getter methods to (maybe) access the fields or setters to (maybe) override them
95#[derive(Debug, Clone)]
96#[cfg_attr(any(feature = "serde", test), derive(Serialize, Deserialize))]
97#[non_exhaustive]
98pub enum Locale<'a> {
99    V1(v1::Locale<'a>),
100    V2(v2::Locale<'a>),
101}
102get_field!(Locale<'a>; V1, V2; bot_disclaimer: Cow<'a, str> );
103set_field!(Locale<'a>; V1, V2; bot_disclaimer: Cow<'a, str> );
104impl<'a> Locale<'a> {
105    pub fn notes(&'a self) -> Notes<'a> {
106        match self {
107            Self::V1(this) => Notes::V1(&this.notes),
108            Self::V2(this) => Notes::V2(&this.notes),
109        }
110    }
111    pub fn notes_mut(&'a mut self) -> NotesMut<'a> {
112        match self {
113            Self::V1(this) => NotesMut::V1(&mut this.notes),
114            Self::V2(this) => NotesMut::V2(&mut this.notes),
115        }
116    }
117    pub fn format(&'a self) -> Format<'a> {
118        match self {
119            Self::V1(this) => Format::V1(&this.format),
120            Self::V2(this) => Format::V1(&this.format),
121        }
122    }
123    pub fn format_mut(&'a mut self) -> FormatMut<'a> {
124        match self {
125            Self::V1(this) => FormatMut::V1(&mut this.format),
126            Self::V2(this) => FormatMut::V1(&mut this.format),
127        }
128    }
129}
130/// Versioned locale just for the notes at the beginning of posts
131///
132/// Use the getter methods to (maybe) access fields
133#[derive(Debug, Clone)]
134#[non_exhaustive]
135pub enum Notes<'a> {
136    V1(&'a v1::Notes<'a>),
137    V2(&'a v2::Notes<'a>),
138}
139get_field!(Notes<'a>; V1, V2; tower: Cow<'a, str>);
140get_field!(Notes<'a>; V1, V2; tower_mult: Cow<'a, str>);
141get_field!(Notes<'a>; V1, V2; digits: Cow<'a, str>);
142get_field!(Notes<'a>; V1, V2; digits_mult: Cow<'a, str>);
143get_field!(Notes<'a>; V1, V2; approx: Cow<'a, str>);
144get_field!(Notes<'a>; V1, V2; approx_mult: Cow<'a, str>);
145get_field!(Notes<'a>; V1, V2; round: Cow<'a, str>);
146get_field!(Notes<'a>; V1, V2; round_mult: Cow<'a, str>);
147get_field!(Notes<'a>; V1, V2; too_big: Cow<'a, str>);
148get_field!(Notes<'a>; V1, V2; too_big_mult: Cow<'a, str>);
149get_field!(Notes<'a>; V1, V2; remove: Cow<'a, str>);
150get_field!(Notes<'a>; V1, V2; tetration: Cow<'a, str>);
151get_field!(Notes<'a>; V1, V2; no_post: Cow<'a, str>);
152get_field!(Notes<'a>; V1, V2; mention: Cow<'a, str>);
153maybe_get_field!(Notes<'a>; V1; V2; limit_hit: Cow<'a, str>);
154/// Versioned locale for the notes at the beginning of posts
155///
156/// Use the setter methods to (possibly) override them
157#[derive(Debug)]
158#[non_exhaustive]
159pub enum NotesMut<'a> {
160    V1(&'a mut v1::Notes<'a>),
161    V2(&'a mut v2::Notes<'a>),
162}
163set_field!(NotesMut<'a>; V1, V2; tower: Cow<'a, str>);
164set_field!(NotesMut<'a>; V1, V2; tower_mult: Cow<'a, str>);
165set_field!(NotesMut<'a>; V1, V2; digits: Cow<'a, str>);
166set_field!(NotesMut<'a>; V1, V2; digits_mult: Cow<'a, str>);
167set_field!(NotesMut<'a>; V1, V2; approx: Cow<'a, str>);
168set_field!(NotesMut<'a>; V1, V2; approx_mult: Cow<'a, str>);
169set_field!(NotesMut<'a>; V1, V2; round: Cow<'a, str>);
170set_field!(NotesMut<'a>; V1, V2; round_mult: Cow<'a, str>);
171set_field!(NotesMut<'a>; V1, V2; too_big: Cow<'a, str>);
172set_field!(NotesMut<'a>; V1, V2; too_big_mult: Cow<'a, str>);
173set_field!(NotesMut<'a>; V1, V2; remove: Cow<'a, str>);
174set_field!(NotesMut<'a>; V1, V2; tetration: Cow<'a, str>);
175set_field!(NotesMut<'a>; V1, V2; no_post: Cow<'a, str>);
176set_field!(NotesMut<'a>; V1, V2; mention: Cow<'a, str>);
177maybe_set_field!(NotesMut<'a>; V1; V2; limit_hit: Cow<'a, str>);
178/// Versioned locale for the formatting of individual calculations
179///
180/// Use the getter methods to (maybe) access fields
181#[derive(Debug, Clone)]
182#[non_exhaustive]
183pub enum Format<'a> {
184    V1(&'a v1::Format<'a>),
185}
186get_field!(Format<'a>; V1; capitalize_calc: bool);
187get_field!(Format<'a>; V1; termial: Cow<'a, str>);
188get_field!(Format<'a>; V1; factorial: Cow<'a, str>);
189get_field!(Format<'a>; V1; uple: Cow<'a, str>);
190get_field!(Format<'a>; V1; sub: Cow<'a, str>);
191get_field!(Format<'a>; V1; negative: Cow<'a, str>);
192get_field!(Format<'a>; V1; num_overrides: HashMap<i32, Cow<'a, str>>);
193get_field!(Format<'a>; V1; force_num: bool);
194get_field!(Format<'a>; V1; nest: Cow<'a, str>);
195get_field!(Format<'a>; V1; rough_number: Cow<'a, str>);
196get_field!(Format<'a>; V1; exact: Cow<'a, str>);
197get_field!(Format<'a>; V1; rough: Cow<'a, str>);
198get_field!(Format<'a>; V1; approx: Cow<'a, str>);
199get_field!(Format<'a>; V1; digits: Cow<'a, str>);
200get_field!(Format<'a>; V1; order: Cow<'a, str>);
201get_field!(Format<'a>; V1; all_that: Cow<'a, str>);
202impl<'a> Format<'a> {
203    pub fn number_format(&'a self) -> NumFormat<'a> {
204        match self {
205            Self::V1(this) => NumFormat::V1(&this.number_format),
206        }
207    }
208}
209/// Versioned locale for the formatting of individual calculations
210///
211/// Use the setter methods to (possibly) override them
212#[derive(Debug)]
213#[non_exhaustive]
214pub enum FormatMut<'a> {
215    V1(&'a mut v1::Format<'a>),
216}
217set_field!(FormatMut<'a>; V1; capitalize_calc: bool);
218set_field!(FormatMut<'a>; V1; termial: Cow<'a, str>);
219set_field!(FormatMut<'a>; V1; factorial: Cow<'a, str>);
220set_field!(FormatMut<'a>; V1; uple: Cow<'a, str>);
221set_field!(FormatMut<'a>; V1; sub: Cow<'a, str>);
222set_field!(FormatMut<'a>; V1; negative: Cow<'a, str>);
223set_field!(FormatMut<'a>; V1; num_overrides: HashMap<i32, Cow<'a, str>>);
224set_field!(FormatMut<'a>; V1; force_num: bool);
225set_field!(FormatMut<'a>; V1; nest: Cow<'a, str>);
226set_field!(FormatMut<'a>; V1; rough_number: Cow<'a, str>);
227set_field!(FormatMut<'a>; V1; exact: Cow<'a, str>);
228set_field!(FormatMut<'a>; V1; rough: Cow<'a, str>);
229set_field!(FormatMut<'a>; V1; approx: Cow<'a, str>);
230set_field!(FormatMut<'a>; V1; digits: Cow<'a, str>);
231set_field!(FormatMut<'a>; V1; order: Cow<'a, str>);
232set_field!(FormatMut<'a>; V1; all_that: Cow<'a, str>);
233impl<'a> FormatMut<'a> {
234    pub fn number_format_mut(&'a mut self) -> NumFormatMut<'a> {
235        match self {
236            Self::V1(this) => NumFormatMut::V1(&mut this.number_format),
237        }
238    }
239}
240/// Versioned locale for how numbers are formatted
241///
242/// Use the getter methods to (maybe) access fields
243#[derive(Debug, Clone)]
244#[non_exhaustive]
245pub enum NumFormat<'a> {
246    V1(&'a v1::NumFormat),
247}
248get_field!(NumFormat<'a>; V1; decimal: char);
249/// Versioned locale for how numbers are formatted
250///
251/// Use the setter methods to (possibly) override them
252#[derive(Debug)]
253#[non_exhaustive]
254pub enum NumFormatMut<'a> {
255    V1(&'a mut v1::NumFormat),
256}
257get_field!(NumFormatMut<'a>; V1; decimal: char);
258
259/// v1 of locales
260pub mod v1 {
261    #[cfg(any(feature = "serde", test))]
262    use serde::{Deserialize, Serialize};
263    use std::{borrow::Cow, collections::HashMap};
264
265    #[derive(Debug, Clone)]
266    #[cfg_attr(any(feature = "serde", test), derive(Serialize, Deserialize))]
267    pub struct Locale<'a> {
268        pub bot_disclaimer: Cow<'a, str>,
269        pub notes: Notes<'a>,
270        pub format: Format<'a>,
271    }
272
273    #[derive(Debug, Clone)]
274    #[cfg_attr(any(feature = "serde", test), derive(Serialize, Deserialize))]
275    pub struct Notes<'a> {
276        pub tower: Cow<'a, str>,
277        pub tower_mult: Cow<'a, str>,
278        pub digits: Cow<'a, str>,
279        pub digits_mult: Cow<'a, str>,
280        pub approx: Cow<'a, str>,
281        pub approx_mult: Cow<'a, str>,
282        pub round: Cow<'a, str>,
283        pub round_mult: Cow<'a, str>,
284        pub too_big: Cow<'a, str>,
285        pub too_big_mult: Cow<'a, str>,
286        pub remove: Cow<'a, str>,
287        pub tetration: Cow<'a, str>,
288        pub no_post: Cow<'a, str>,
289        pub mention: Cow<'a, str>,
290    }
291
292    #[derive(Debug, Clone)]
293    #[cfg_attr(any(feature = "serde", test), derive(Serialize, Deserialize))]
294    pub struct Format<'a> {
295        pub capitalize_calc: bool,
296        pub termial: Cow<'a, str>,
297        pub factorial: Cow<'a, str>,
298        pub uple: Cow<'a, str>,
299        pub sub: Cow<'a, str>,
300        pub negative: Cow<'a, str>,
301        pub num_overrides: HashMap<i32, Cow<'a, str>>,
302        pub force_num: bool,
303        pub nest: Cow<'a, str>,
304        pub rough_number: Cow<'a, str>,
305        pub exact: Cow<'a, str>,
306        pub rough: Cow<'a, str>,
307        pub approx: Cow<'a, str>,
308        pub digits: Cow<'a, str>,
309        pub order: Cow<'a, str>,
310        pub all_that: Cow<'a, str>,
311        pub number_format: NumFormat,
312    }
313
314    #[derive(Debug, Clone)]
315    #[cfg_attr(any(feature = "serde", test), derive(Serialize, Deserialize))]
316    pub struct NumFormat {
317        pub decimal: char,
318    }
319}
320/// v1 of locales
321pub mod v2 {
322    #[cfg(any(feature = "serde", test))]
323    use serde::{Deserialize, Serialize};
324    use std::borrow::Cow;
325
326    #[derive(Debug, Clone)]
327    #[cfg_attr(any(feature = "serde", test), derive(Serialize, Deserialize))]
328    pub struct Locale<'a> {
329        pub bot_disclaimer: Cow<'a, str>,
330        pub notes: Notes<'a>,
331        pub format: super::v1::Format<'a>,
332    }
333
334    #[derive(Debug, Clone)]
335    #[cfg_attr(any(feature = "serde", test), derive(Serialize, Deserialize))]
336    pub struct Notes<'a> {
337        pub tower: Cow<'a, str>,
338        pub tower_mult: Cow<'a, str>,
339        pub digits: Cow<'a, str>,
340        pub digits_mult: Cow<'a, str>,
341        pub approx: Cow<'a, str>,
342        pub approx_mult: Cow<'a, str>,
343        pub round: Cow<'a, str>,
344        pub round_mult: Cow<'a, str>,
345        pub too_big: Cow<'a, str>,
346        pub too_big_mult: Cow<'a, str>,
347        pub remove: Cow<'a, str>,
348        pub tetration: Cow<'a, str>,
349        pub no_post: Cow<'a, str>,
350        pub mention: Cow<'a, str>,
351        pub limit_hit: Cow<'a, str>,
352    }
353}