diff options
| author | metamuffin <metamuffin@disroot.org> | 2026-01-23 17:41:45 +0100 |
|---|---|---|
| committer | metamuffin <metamuffin@disroot.org> | 2026-01-23 17:41:45 +0100 |
| commit | 774f64c0789529884dd7a5232f190e347ad29532 (patch) | |
| tree | 6eb85388837c993a054fba5ca59fdd329f5b5840 /ui | |
| parent | 3671a4e07565c86f8071fb2309f463aeaf684ba3 (diff) | |
| download | jellything-774f64c0789529884dd7a5232f190e347ad29532.tar jellything-774f64c0789529884dd7a5232f190e347ad29532.tar.bz2 jellything-774f64c0789529884dd7a5232f190e347ad29532.tar.zst | |
move locale code to own crate
Diffstat (limited to 'ui')
| -rw-r--r-- | ui/Cargo.toml | 5 | ||||
| -rw-r--r-- | ui/locale/Cargo.toml | 7 | ||||
| -rw-r--r-- | ui/locale/src/lib.rs | 73 | ||||
| -rw-r--r-- | ui/src/components/mod.rs | 10 | ||||
| -rw-r--r-- | ui/src/components/node_page.rs | 3 | ||||
| -rw-r--r-- | ui/src/components/props.rs | 2 | ||||
| -rw-r--r-- | ui/src/components/stats.rs | 2 | ||||
| -rw-r--r-- | ui/src/format.rs | 19 | ||||
| -rw-r--r-- | ui/src/lib.rs | 13 | ||||
| -rw-r--r-- | ui/src/locale.rs | 52 | ||||
| -rw-r--r-- | ui/src/scaffold.rs | 6 |
11 files changed, 112 insertions, 80 deletions
diff --git a/ui/Cargo.toml b/ui/Cargo.toml index 8752938..9bf5082 100644 --- a/ui/Cargo.toml +++ b/ui/Cargo.toml @@ -4,10 +4,13 @@ version = "0.1.0" edition = "2024" [dependencies] -markup = "0.15.0" +markup = { git = "https://github.com/metamuffin/markup.rs", rev = "2ee9aee" } jellycommon = { path = "../common" } humansize = "2.1.3" serde = { version = "1.0.228", features = ["derive", "rc"] } serde_json = "1.0.145" vte = "0.15.0" chrono = "0.4.43" +jellyui-client-scripts = { path = "client-scripts" } +jellyui-client-style = { path = "client-style" } +jellyui-locale = { path = "locale" } diff --git a/ui/locale/Cargo.toml b/ui/locale/Cargo.toml new file mode 100644 index 0000000..5e2b14d --- /dev/null +++ b/ui/locale/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "jellyui-locale" +version = "0.1.0" +edition = "2024" + +[features] +reload = [] diff --git a/ui/locale/src/lib.rs b/ui/locale/src/lib.rs new file mode 100644 index 0000000..2028418 --- /dev/null +++ b/ui/locale/src/lib.rs @@ -0,0 +1,73 @@ +/* + This file is part of jellything (https://codeberg.org/metamuffin/jellything) + which is licensed under the GNU Affero General Public License (version 3); see /COPYING. + Copyright (C) 2026 metamuffin <metamuffin.org> +*/ +use std::{borrow::Cow, collections::HashMap, sync::LazyLock}; + +macro_rules! languages { + ($($lang:literal),*) => { + #[cfg(feature = "reload")] + const LANGUAGES: &[&str] = &[$($lang),*]; + #[cfg(not(feature = "reload"))] + const LANGUAGES: &[(&str, &str)] = &[$(($lang, include_str!(concat!("../../../locale/", $lang, ".ini")))),*]; + }; +} +languages!("en", "de"); + +pub static LANG_TABLES: LazyLock<HashMap<&'static str, HashMap<&'static str, &'static str>>> = + LazyLock::new(|| { + let mut langs = LANGUAGES + .iter() + .map(|(k, v)| (*k, parse_ini(v))) + .collect::<HashMap<_, _>>(); + + let fallback = langs["en"].clone(); + for l in langs.values_mut() { + for (k, fv) in &fallback { + if !l.contains_key(k) { + l.insert(k, fv); + } + } + } + langs + }); + +fn parse_ini<'a>(source: &'a str) -> HashMap<&'a str, &'a str> { + source + .lines() + .filter_map(|line| { + let (key, value) = line.split_once("=")?; + Some((key.trim(), value.trim())) + }) + .collect() +} + +pub fn tr(lang: &str, key: &str) -> Cow<'static, str> { + let tr_map = LANG_TABLES.get(&lang).unwrap(); + tr_map + .get(key) + .copied() + .unwrap_or("MISSING TRANSLATION") + .into() +} + +pub fn escape(str: &str) -> String { + let mut o = String::with_capacity(str.len()); + let mut last = 0; + for (index, byte) in str.bytes().enumerate() { + if let Some(esc) = match byte { + b'<' => Some("<"), + b'>' => Some(">"), + b'&' => Some("&"), + b'"' => Some("""), + _ => None, + } { + o += &str[last..index]; + o += esc; + last = index + 1; + } + } + o += &str[last..]; + o +} diff --git a/ui/src/components/mod.rs b/ui/src/components/mod.rs index 4d2dd62..07b050b 100644 --- a/ui/src/components/mod.rs +++ b/ui/src/components/mod.rs @@ -9,8 +9,11 @@ pub mod node_page; pub mod props; pub mod stats; -use crate::{RenderInfo, components::message::Message}; -use jellycommon::{VIEW_MESSAGE, jellyobject::Object}; +use crate::{ + RenderInfo, + components::{message::Message, node_page::NodePage}, +}; +use jellycommon::{jellyobject::Object, *}; use markup::define; define! { @@ -18,5 +21,8 @@ define! { @if let Some(message) = view.get(VIEW_MESSAGE) { @Message { ri, message } } + @if let Some(nku) = view.get(VIEW_NODE_PAGE) { + @NodePage { ri, nku } + } } } diff --git a/ui/src/components/node_page.rs b/ui/src/components/node_page.rs index 4a594d6..405f50a 100644 --- a/ui/src/components/node_page.rs +++ b/ui/src/components/node_page.rs @@ -4,12 +4,13 @@ Copyright (C) 2026 metamuffin <metamuffin.org> */ -use crate::{RenderInfo, components::props::Props, locale::tr}; +use crate::{RenderInfo, components::props::Props}; use jellycommon::{ jellyobject::{Object, Tag, TypedTag}, routes::{u_image, u_node_slug_player}, *, }; +use jellyui_locale::tr; use std::marker::PhantomData; markup::define! { diff --git a/ui/src/components/props.rs b/ui/src/components/props.rs index f23d72e..fa078e7 100644 --- a/ui/src/components/props.rs +++ b/ui/src/components/props.rs @@ -7,13 +7,13 @@ use crate::{ RenderInfo, format::{format_count, format_duration}, - locale::tr, }; use chrono::DateTime; use jellycommon::{ jellyobject::{Object, TypedTag}, *, }; +use jellyui_locale::tr; use std::marker::PhantomData; markup::define! { diff --git a/ui/src/components/stats.rs b/ui/src/components/stats.rs index 8dfb304..698430b 100644 --- a/ui/src/components/stats.rs +++ b/ui/src/components/stats.rs @@ -7,9 +7,9 @@ use crate::{ RenderInfo, format::{format_duration, format_duration_long, format_size}, - locale::tr, }; use jellycommon::{jellyobject::Object, *}; +use jellyui_locale::tr; use markup::raw; markup::define! { diff --git a/ui/src/format.rs b/ui/src/format.rs index 01982af..4eb8f84 100644 --- a/ui/src/format.rs +++ b/ui/src/format.rs @@ -8,17 +8,16 @@ use jellycommon::{ jellyobject::{Object, Tag}, *, }; - -use crate::locale::tr; -use std::fmt::Write; +use jellyui_locale::tr; +use std::{borrow::Cow, fmt::Write}; pub fn format_duration(d: f64) -> String { - format_duration_mode(LANG_ENG.0, d, false) + format_duration_mode("en", d, false) } -pub fn format_duration_long(lang: Language, d: f64) -> String { +pub fn format_duration_long(lang: &str, d: f64) -> String { format_duration_mode(lang, d, true) } -fn format_duration_mode(lang: Language, mut d: f64, long_units: bool) -> String { +fn format_duration_mode(lang: &str, mut d: f64, long_units: bool) -> String { let mut s = String::new(); let sign = if d > 0. { "" } else { "-" }; d = d.abs(); @@ -58,15 +57,15 @@ fn test_duration_short() { #[test] fn test_duration_long() { assert_eq!( - format_duration_long(LANG_ENG.0, 61.).as_str(), + format_duration_long("en", 61.).as_str(), "1 minute and 1 second" ); assert_eq!( - format_duration_long(LANG_ENG.0, 121.).as_str(), + format_duration_long("en", 121.).as_str(), "2 minutes and 1 second" ); assert_eq!( - format_duration_long(LANG_ENG.0, 3661.).as_str(), + format_duration_long("en", 3661.).as_str(), "1 hour, 1 minute and 1 second" ); } @@ -74,7 +73,7 @@ fn test_duration_long() { pub fn format_size(size: u64) -> String { humansize::format_size(size, humansize::DECIMAL) } -pub fn format_kind(lang: Language, kind: Tag) -> &'static str { +pub fn format_kind(lang: &str, kind: Tag) -> Cow<'static, str> { tr( lang, match kind { diff --git a/ui/src/lib.rs b/ui/src/lib.rs index 72109d4..3b04b40 100644 --- a/ui/src/lib.rs +++ b/ui/src/lib.rs @@ -5,18 +5,15 @@ */ mod components; pub(crate) mod format; -pub(crate) mod locale; mod scaffold; +pub use jellyui_client_scripts::*; +pub use jellyui_client_style::*; + use crate::{components::View, scaffold::Scaffold}; -use jellycommon::{ - jellyobject::{Object, Tag}, - *, -}; +use jellycommon::{jellyobject::Object, *}; use serde::{Deserialize, Serialize}; -pub type FlashM = Option<(String, String)>; - #[rustfmt::skip] #[derive(Debug, Deserialize, Serialize, Default)] pub struct Config { @@ -27,7 +24,7 @@ pub struct Config { pub struct RenderInfo<'a> { pub user: Option<Object<'a>>, - pub lang: Tag, + pub lang: &'a str, pub status_message: Option<&'a str>, pub config: &'a Config, } diff --git a/ui/src/locale.rs b/ui/src/locale.rs deleted file mode 100644 index 08c73c2..0000000 --- a/ui/src/locale.rs +++ /dev/null @@ -1,52 +0,0 @@ -/* - This file is part of jellything (https://codeberg.org/metamuffin/jellything) - which is licensed under the GNU Affero General Public License (version 3); see /COPYING. - Copyright (C) 2026 metamuffin <metamuffin.org> -*/ -use jellycommon::*; -use std::{collections::HashMap, sync::LazyLock}; - -pub static LANG_TABLES: LazyLock<HashMap<Language, HashMap<&'static str, &'static str>>> = - LazyLock::new(|| { - let mut k = HashMap::new(); - for (lang, source) in [ - (LANG_ENG.0, include_str!("../../locale/en.ini")), - (LANG_DEU.0, include_str!("../../locale/de.ini")), - ] { - // TODO fallback to english - let tr_map = source - .lines() - .filter_map(|line| { - let (key, value) = line.split_once("=")?; - Some((key.trim(), value.trim())) - }) - .collect::<HashMap<&'static str, &'static str>>(); - k.insert(lang, tr_map); - } - k - }); - -pub fn tr(lang: Language, key: &str) -> &'static str { - let tr_map = LANG_TABLES.get(&lang).unwrap(); - tr_map.get(key).copied().unwrap_or("MISSING TRANSLATION") -} - -pub fn escape(str: &str) -> String { - let mut o = String::with_capacity(str.len()); - let mut last = 0; - for (index, byte) in str.bytes().enumerate() { - if let Some(esc) = match byte { - b'<' => Some("<"), - b'>' => Some(">"), - b'&' => Some("&"), - b'"' => Some("""), - _ => None, - } { - o += &str[last..index]; - o += esc; - last = index + 1; - } - } - o += &str[last..]; - o -} diff --git a/ui/src/scaffold.rs b/ui/src/scaffold.rs index fee311a..8cfb432 100644 --- a/ui/src/scaffold.rs +++ b/ui/src/scaffold.rs @@ -4,10 +4,7 @@ Copyright (C) 2026 metamuffin <metamuffin.org> */ -use crate::{ - RenderInfo, - locale::{escape, tr}, -}; +use crate::RenderInfo; use jellycommon::{ routes::{ u_account_login, u_account_logout, u_account_register, u_account_settings, @@ -15,6 +12,7 @@ use jellycommon::{ }, user::{USER_ADMIN, USER_NAME}, }; +use jellyui_locale::{escape, tr}; use markup::{Render, raw}; markup::define! { |