Moving i18n to sepparate module
This commit is contained in:
@@ -1,97 +0,0 @@
|
||||
//! This modules contains the parts for making the app translatable.
|
||||
use std::sync::Arc;
|
||||
|
||||
use fluent::{FluentArgs, FluentBundle, FluentResource};
|
||||
use pslink_shared::datatypes::Lang;
|
||||
use unic_langid::LanguageIdentifier;
|
||||
|
||||
/// A struct containing the data, functions and the current language to query the localized strings.
|
||||
#[derive(Clone)]
|
||||
pub struct I18n {
|
||||
lang: Lang,
|
||||
ftl_bundle: Arc<FluentBundle<FluentResource>>,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for I18n {
|
||||
/// On debug print skip the bundle
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{:?}", self.lang)
|
||||
}
|
||||
}
|
||||
|
||||
impl I18n {
|
||||
/// Create a new translator struct
|
||||
#[must_use]
|
||||
pub fn new(lang: Lang) -> Self {
|
||||
let ftl_bundle = Arc::new(Self::create_ftl_bundle(lang));
|
||||
Self { lang, ftl_bundle }
|
||||
}
|
||||
|
||||
/// Get the current language
|
||||
#[must_use]
|
||||
pub const fn lang(&self) -> &Lang {
|
||||
&self.lang
|
||||
}
|
||||
|
||||
/// Set the current language
|
||||
pub fn set_lang(&mut self, lang: Lang) {
|
||||
self.lang = lang;
|
||||
self.ftl_bundle = Arc::new(Self::create_ftl_bundle(lang));
|
||||
}
|
||||
|
||||
/// Get a localized string. Optionally with parameters provided in `args`.
|
||||
pub fn translate(&self, key: impl AsRef<str>, args: Option<&FluentArgs>) -> String {
|
||||
// log!(key.as_ref());
|
||||
let msg = self
|
||||
.ftl_bundle
|
||||
.get_message(key.as_ref())
|
||||
.expect("Failed to get fluent message for key {}");
|
||||
|
||||
let pattern = msg.value().expect("Failed to parse pattern");
|
||||
|
||||
self.ftl_bundle
|
||||
.format_pattern(pattern, args, &mut vec![])
|
||||
.to_string()
|
||||
}
|
||||
|
||||
/// Prettyprint the language name
|
||||
#[must_use]
|
||||
pub const fn label(&self) -> &'static str {
|
||||
match self.lang {
|
||||
Lang::EnUS => "English (US)",
|
||||
Lang::DeDE => "Deutsch (Deutschland)",
|
||||
}
|
||||
}
|
||||
|
||||
/// include the fluent messages into the binary
|
||||
#[must_use]
|
||||
pub const fn ftl_messages(lang: Lang) -> &'static str {
|
||||
macro_rules! include_ftl_messages {
|
||||
( $lang_id:literal ) => {
|
||||
include_str!(concat!("../../locales/", $lang_id, "/main.ftl"))
|
||||
};
|
||||
}
|
||||
match lang {
|
||||
Lang::EnUS => include_ftl_messages!("en"),
|
||||
Lang::DeDE => include_ftl_messages!("de"),
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn language_identifier(lang: Lang) -> LanguageIdentifier {
|
||||
lang.as_ref()
|
||||
.parse()
|
||||
.expect("parse Lang to LanguageIdentifier")
|
||||
}
|
||||
|
||||
/// Create and initialize a fluent bundle.
|
||||
#[must_use]
|
||||
pub fn create_ftl_bundle(lang: Lang) -> FluentBundle<FluentResource> {
|
||||
let ftl_resource = FluentResource::try_new(Self::ftl_messages(lang).to_owned())
|
||||
.expect("parse FTL messages");
|
||||
|
||||
let mut bundle = FluentBundle::new(vec![Self::language_identifier(lang)]);
|
||||
bundle.add_resource(ftl_resource).expect("add FTL resource");
|
||||
bundle
|
||||
}
|
||||
}
|
||||
+2
-3
@@ -1,5 +1,4 @@
|
||||
//! The admin interface of pslink. It communicates with the server mostly via https and json.
|
||||
pub mod i18n;
|
||||
pub mod navigation;
|
||||
pub mod pages;
|
||||
|
||||
@@ -13,7 +12,7 @@ use seed::window;
|
||||
use seed::IF;
|
||||
use seed::{attrs, button, div, input, label, log, prelude::*, App, Url, C};
|
||||
|
||||
use crate::i18n::I18n;
|
||||
use pslink_locales::I18n;
|
||||
|
||||
// ------ ------
|
||||
// Init
|
||||
@@ -45,7 +44,7 @@ struct Model {
|
||||
index: usize,
|
||||
location: Location,
|
||||
page: Page,
|
||||
i18n: i18n::I18n,
|
||||
i18n: I18n,
|
||||
user: Loadable<User>,
|
||||
login_form: LoginForm,
|
||||
login_data: LoginUser,
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
//! Create the top menu of the app
|
||||
use fluent::fluent_args;
|
||||
use pslink_locales::I18n;
|
||||
use pslink_shared::{
|
||||
apirequests::users::Role,
|
||||
datatypes::{Lang, User},
|
||||
};
|
||||
use seed::{a, attrs, div, li, nav, nodes, ol, prelude::*, Url, C};
|
||||
|
||||
use crate::{i18n::I18n, Msg};
|
||||
use crate::Msg;
|
||||
|
||||
/// Generate the top navigation menu of all pages.
|
||||
///
|
||||
|
||||
@@ -4,6 +4,7 @@ use std::ops::Deref;
|
||||
use enum_map::EnumMap;
|
||||
use fluent::fluent_args;
|
||||
use image::{DynamicImage, ImageOutputFormat, Luma};
|
||||
use pslink_locales::I18n;
|
||||
use qrcode::{render::svg, QrCode};
|
||||
use seed::{
|
||||
a, attrs, div, h1, img, input, log, nodes, prelude::*, raw, section, span, table, td, th, tr,
|
||||
@@ -20,7 +21,7 @@ use pslink_shared::{
|
||||
datatypes::{FullLink, Lang, Loadable, User},
|
||||
};
|
||||
|
||||
use crate::{get_host, i18n::I18n, unwrap_or_return};
|
||||
use crate::{get_host, unwrap_or_return};
|
||||
|
||||
/// Setup the page
|
||||
pub fn init(mut url: Url, orders: &mut impl Orders<Msg>, i18n: I18n) -> Model {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
//! List all users in case an admin views it, list the "self" user otherwise.
|
||||
|
||||
use enum_map::EnumMap;
|
||||
use pslink_locales::I18n;
|
||||
use pslink_shared::{
|
||||
apirequests::general::{Operation, Ordering},
|
||||
apirequests::{
|
||||
@@ -13,7 +14,7 @@ use seed::{a, attrs, div, h1, input, log, p, prelude::*, section, table, td, th,
|
||||
/*
|
||||
* init
|
||||
*/
|
||||
use crate::{i18n::I18n, unwrap_or_return};
|
||||
use crate::unwrap_or_return;
|
||||
#[must_use]
|
||||
pub fn init(mut url: Url, orders: &mut impl Orders<Msg>, i18n: I18n) -> Model {
|
||||
orders.send_msg(Msg::Query(UserQueryMsg::Fetch));
|
||||
|
||||
Reference in New Issue
Block a user