You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

115 lines
3.2 KiB

use crate::LOCALES;
use askama::i18n::fluent_templates::Loader;
use askama::i18n::FluentValue;
use askama::i18n::{langid, LanguageIdentifier, Locale};
use serde::{Deserialize, Serialize};
use strum::IntoEnumIterator;
use strum_macros::{AsRefStr, EnumCount, EnumIter, EnumVariantNames};
use derive_more::Display;
#[derive(
sqlx::Type,
Serialize,
Deserialize,
Clone,
Copy,
Debug,
Hash,
Display,
EnumIter,
EnumCount,
EnumVariantNames,
AsRefStr,
PartialEq,
Eq,
)]
#[repr(i32)]
pub enum SupportedLanguage {
#[serde(rename = "en-ca")]
#[display(fmt = "en-ca")]
English = 1,
#[serde(rename = "fr-ca")]
#[display(fmt = "fr-ca")]
French = 2,
}
impl From<SupportedLanguage> for i32 {
fn from(lang: SupportedLanguage) -> Self {
match lang {
SupportedLanguage::English => 1,
SupportedLanguage::French => 2,
}
}
}
impl From<SupportedLanguage> for FluentValue<'_> {
fn from(n: SupportedLanguage) -> Self {
n.to_string().into()
}
}
impl From<SupportedLanguage> for LanguageIdentifier {
fn from(lang: SupportedLanguage) -> LanguageIdentifier {
match lang {
SupportedLanguage::English => langid!("en-ca"),
SupportedLanguage::French => langid!("fr-ca"),
}
}
}
impl<'a> From<SupportedLanguage> for Locale<'a> {
fn from(lang: SupportedLanguage) -> Self {
Locale::new(lang.into(), &LOCALES)
}
}
impl SupportedLanguage {
pub fn lookup(self, key: &str) -> String {
LOCALES
.lookup(&self.into(), key)
.expect("Unable to find key {key} in locale {self}.")
}
pub fn other_langs(self) -> impl Iterator<Item = Self> + 'static {
Self::iter().filter(move |lang| lang != &self)
}
pub fn native_name(self) -> String {
match self {
Self::English => "English",
Self::French => "Français",
}
.to_string()
}
pub fn id(self) -> i32 {
match self {
Self::English => 1,
Self::French => 2,
}
}
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct LangLink {
pub href: String,
pub name: String,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct LocalizedName {
pub localizations: std::collections::HashMap<SupportedLanguage, String>,
}
impl LocalizedName {
fn localize(&self, lang: SupportedLanguage) -> Option<String> {
// first, try to find the proper match for a name
self.localizations
.iter()
.find_map(|(translated_lang, string)| if translated_lang == &lang {
Some(string.to_string())
} else {
None
})
// if not found, replace it with ANY localization of the word; this will help when, for example, there is no matching name for a French game, but the game has already been created with the English name.
// if NO localization is found, then we can still return a None value; but hopefully through database, form, and web server restrictions, we can mostly stop that from happening
.or_else(|| if self.localizations.is_empty() {
Some(self.localizations.values().next().unwrap().to_string())
} else {
None
})
}
}