Translation (WIP)
This commit is contained in:
parent
9b0fcec5e2
commit
e9873c1943
29 changed files with 586 additions and 285 deletions
142
backend/src/translation.rs
Normal file
142
backend/src/translation.rs
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
use std::{fs::File, sync::LazyLock};
|
||||
|
||||
use ron::de::from_reader;
|
||||
use rustc_hash::FxHashMap;
|
||||
use serde::Deserialize;
|
||||
use tracing::{event, Level};
|
||||
|
||||
use crate::consts;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Clone)]
|
||||
pub enum Sentence {
|
||||
ProfileTitle,
|
||||
MainTitle,
|
||||
CreateNewRecipe,
|
||||
UnpublishedRecipes,
|
||||
UntitledRecipe,
|
||||
|
||||
EmailAddress,
|
||||
Password,
|
||||
|
||||
// Sign in page.
|
||||
SignInMenu,
|
||||
SignInTitle,
|
||||
SignInButton,
|
||||
WrongEmailOrPassword,
|
||||
|
||||
// Sign up page.
|
||||
SignUpMenu,
|
||||
SignUpTitle,
|
||||
SignUpButton,
|
||||
ChooseAPassword,
|
||||
ReEnterPassword,
|
||||
AccountMustBeValidatedFirst,
|
||||
InvalidEmail,
|
||||
PasswordDontMatch,
|
||||
InvalidPassword,
|
||||
EmailAlreadyTaken,
|
||||
UnableToSendEmail,
|
||||
|
||||
// Reset password page.
|
||||
LostPassword,
|
||||
AskResetButton,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Tr {
|
||||
lang: &'static Language,
|
||||
}
|
||||
|
||||
impl Tr {
|
||||
pub fn new(code: &str) -> Self {
|
||||
for lang in TRANSLATIONS.iter() {
|
||||
if lang.code == code {
|
||||
return Self { lang };
|
||||
}
|
||||
}
|
||||
|
||||
event!(
|
||||
Level::WARN,
|
||||
"Unable to find translation for language {}",
|
||||
code
|
||||
);
|
||||
|
||||
Tr::new("en")
|
||||
}
|
||||
|
||||
pub fn t(&self, sentence: Sentence) -> String {
|
||||
match self.lang.translation.get(&sentence) {
|
||||
Some(str) => str.clone(),
|
||||
None => format!(
|
||||
"Translation missing, lang: {}/{}, element: {:?}",
|
||||
self.lang.name, self.lang.code, sentence
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tp(&self, sentence: Sentence, params: &[Box<dyn ToString>]) -> String {
|
||||
match self.lang.translation.get(&sentence) {
|
||||
Some(str) => {
|
||||
let mut result = str.clone();
|
||||
for p in params {
|
||||
result = result.replacen("{}", &p.to_string(), 1);
|
||||
}
|
||||
result
|
||||
}
|
||||
None => format!(
|
||||
"Translation missing, lang: {}/{}, element: {:?}",
|
||||
self.lang.name, self.lang.code, sentence
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn available_languages() -> Vec<(&'static str, &'static str)> {
|
||||
TRANSLATIONS
|
||||
.iter()
|
||||
.map(|tr| (tr.code.as_ref(), tr.name.as_ref()))
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn available_codes() -> Vec<&'static str> {
|
||||
TRANSLATIONS.iter().map(|tr| tr.code.as_ref()).collect()
|
||||
}
|
||||
}
|
||||
|
||||
// #[macro_export]
|
||||
// macro_rules! t {
|
||||
// ($self:expr, $str:expr) => {
|
||||
// $self.t($str)
|
||||
// };
|
||||
// ($self:expr, $str:expr, $( $x:expr ),+ ) => {
|
||||
// {
|
||||
// let mut result = $self.t($str);
|
||||
// $( result = result.replacen("{}", &$x.to_string(), 1); )+
|
||||
// result
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
|
||||
#[derive(Debug, Deserialize, Clone)]
|
||||
struct Language {
|
||||
code: String,
|
||||
name: String,
|
||||
translation: FxHashMap<Sentence, String>,
|
||||
}
|
||||
|
||||
static TRANSLATIONS: LazyLock<Vec<Language>> =
|
||||
LazyLock::new(|| match File::open(consts::TRANSLATION_FILE) {
|
||||
Ok(file) => from_reader(file).unwrap_or_else(|error| {
|
||||
panic!(
|
||||
"Failed to read translation file {}: {}",
|
||||
consts::TRANSLATION_FILE,
|
||||
error
|
||||
)
|
||||
}),
|
||||
Err(error) => {
|
||||
panic!(
|
||||
"Failed to open translation file {}: {}",
|
||||
consts::TRANSLATION_FILE,
|
||||
error
|
||||
)
|
||||
}
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue