aboutsummaryrefslogtreecommitdiff
path: root/server/src/routes/ui/node.rs
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/routes/ui/node.rs')
-rw-r--r--server/src/routes/ui/node.rs81
1 files changed, 52 insertions, 29 deletions
diff --git a/server/src/routes/ui/node.rs b/server/src/routes/ui/node.rs
index 57e8562..e94547c 100644
--- a/server/src/routes/ui/node.rs
+++ b/server/src/routes/ui/node.rs
@@ -9,12 +9,14 @@ use super::{
rocket_uri_macro_r_node_thumbnail,
},
error::MyResult,
+ layout::{trs, trsa},
sort::{filter_and_sort_nodes, NodeFilterSort, NodeFilterSortForm, SortOrder, SortProperty},
};
use crate::{
database::Database,
routes::{
api::AcceptJson,
+ locale::AcceptLanguage,
ui::{
account::session::Session,
assets::rocket_uri_macro_r_person_asset,
@@ -30,6 +32,7 @@ use crate::{
};
use anyhow::{anyhow, Result};
use chrono::DateTime;
+use jellybase::locale::Language;
use jellycommon::{
api::ApiNodeResponse,
user::{NodeUserData, WatchedState},
@@ -51,9 +54,11 @@ pub async fn r_library_node_filter<'a>(
db: &'a State<Database>,
aj: AcceptJson,
filter: NodeFilterSort,
+ lang: AcceptLanguage,
parents: bool,
children: bool,
) -> MyResult<Either<DynLayoutPage<'a>, Json<ApiNodeResponse>>> {
+ let AcceptLanguage(lang) = lang;
let (node, udata) = db.get_node_with_userdata(id, &session)?;
let mut children = if !*aj || children {
@@ -100,9 +105,16 @@ pub async fn r_library_node_filter<'a>(
} else {
Either::Left(LayoutPage {
title: node.title.clone().unwrap_or_default(),
- content: markup::new! {
- @NodePage { node: &node, udata: &udata, children: &children, parents: &parents, filter: &filter, player: false, similar: &similar }
- },
+ content: markup::new!(@NodePage {
+ node: &node,
+ udata: &udata,
+ children: &children,
+ parents: &parents,
+ filter: &filter,
+ player: false,
+ similar: &similar,
+ lang: &lang,
+ }),
..Default::default()
})
})
@@ -134,7 +146,7 @@ pub fn get_similar_media(
}
markup::define! {
- NodeCard<'a>(node: &'a Node, udata: &'a NodeUserData) {
+ NodeCard<'a>(node: &'a Node, udata: &'a NodeUserData, lang: &'a Language) {
@let cls = format!("node card poster {}", aspect_class(node.kind));
div[class=cls] {
.poster {
@@ -145,7 +157,7 @@ markup::define! {
@if node.media.is_some() {
a.play.icon[href=&uri!(r_player(&node.slug, PlayerConfig::default()))] { "play_arrow" }
}
- @Props { node, udata, full: false }
+ @Props { node, udata, full: false, lang }
}
}
div.title {
@@ -160,7 +172,7 @@ markup::define! {
}
}
}
- NodeCardWide<'a>(node: &'a Node, udata: &'a NodeUserData) {
+ NodeCardWide<'a>(node: &'a Node, udata: &'a NodeUserData, lang: &'a Language) {
div[class="node card widecard poster"] {
div[class=&format!("poster {}", aspect_class(node.kind))] {
a[href=uri!(r_library_node(&node.slug))] {
@@ -174,12 +186,21 @@ markup::define! {
}
div.details {
a.title[href=uri!(r_library_node(&node.slug))] { @node.title }
- @Props { node, udata, full: false }
+ @Props { node, udata, full: false, lang }
span.overview { @node.description }
}
}
}
- NodePage<'a>(node: &'a Node, udata: &'a NodeUserData, children: &'a [(Arc<Node>, NodeUserData)], parents: &'a [(Arc<Node>, NodeUserData)], similar: &'a [(Arc<Node>, NodeUserData)], filter: &'a NodeFilterSort, player: bool) {
+ NodePage<'a>(
+ node: &'a Node,
+ udata: &'a NodeUserData,
+ children: &'a [(Arc<Node>, NodeUserData)],
+ parents: &'a [(Arc<Node>, NodeUserData)],
+ similar: &'a [(Arc<Node>, NodeUserData)],
+ filter: &'a NodeFilterSort,
+ lang: &'a Language,
+ player: bool,
+ ) {
@if !matches!(node.kind, NodeKind::Collection) && !player {
img.backdrop[src=uri!(r_item_backdrop(&node.slug, Some(2048))), loading="lazy"];
}
@@ -193,26 +214,28 @@ markup::define! {
ul.parents { @for (node, _) in *parents { li {
a.component[href=uri!(r_library_node(&node.slug))] { @node.title }
}}}
- @if node.media.is_some() { a.play[href=&uri!(r_player(&node.slug, PlayerConfig::default()))] { "Watch now" }}
+ @if node.media.is_some() {
+ a.play[href=&uri!(r_player(&node.slug, PlayerConfig::default()))] { @trs(lang, "node.player_link") }
+ }
@if !matches!(node.kind, NodeKind::Collection | NodeKind::Channel) {
@if matches!(udata.watched, WatchedState::None | WatchedState::Pending | WatchedState::Progress(_)) {
form.mark_watched[method="POST", action=uri!(r_node_userdata_watched(&node.slug, UrlWatchedState::Watched))] {
- input[type="submit", value="Mark Watched"];
+ input[type="submit", value=trs(lang, "node.watched.set")];
}
}
@if matches!(udata.watched, WatchedState::Watched) {
form.mark_unwatched[method="POST", action=uri!(r_node_userdata_watched(&node.slug, UrlWatchedState::None))] {
- input[type="submit", value="Mark Unwatched"];
+ input[type="submit", value=trs(lang, "node.watched.unset")];
}
}
@if matches!(udata.watched, WatchedState::None) {
form.mark_unwatched[method="POST", action=uri!(r_node_userdata_watched(&node.slug, UrlWatchedState::Pending))] {
- input[type="submit", value="Add to Watchlist"];
+ input[type="submit", value=trs(lang, "node.watchlist.set")];
}
}
@if matches!(udata.watched, WatchedState::Pending) {
form.mark_unwatched[method="POST", action=uri!(r_node_userdata_watched(&node.slug, UrlWatchedState::None))] {
- input[type="submit", value="Remove from Watchlist"];
+ input[type="submit", value=trs(lang, "node.watchlist.unset")];
}
}
form.rating[method="POST", action=uri!(r_node_userdata_rating(&node.slug))] {
@@ -222,14 +245,14 @@ markup::define! {
}
}
.details {
- @Props { node, udata, full: true }
+ @Props { node, udata, full: true, lang }
h3 { @node.tagline }
@if let Some(description) = &node.description {
p { @for line in description.lines() { @line br; } }
}
@if let Some(media) = &node.media {
@if !media.chapters.is_empty() {
- h2 { "Chapters" }
+ h2 { @trs(lang, "node.chapters") }
ul.children.hlist { @for chap in &media.chapters {
@let (inl, sub) = format_chapter(chap);
li { .card."aspect-thumb" {
@@ -244,7 +267,7 @@ markup::define! {
}}
}
@if !node.people.is_empty() {
- h2 { "Cast & Crew" }
+ h2 { @trs(lang, "node.people") }
@for (group, people) in &node.people {
details[open=group==&PeopleGroup::Cast] {
summary { h3 { @format!("{}", group) } }
@@ -270,7 +293,7 @@ markup::define! {
}
}
details {
- summary { "Tracks" }
+ summary { @trs(lang, "media.tracks") }
ol { @for track in &media.tracks {
li { @format!("{track}") }
}}
@@ -278,7 +301,7 @@ markup::define! {
}
@if !node.tags.is_empty() {
details {
- summary { "Tags" }
+ summary { @trs(lang, "node.tags") }
ol { @for tag in &node.tags {
li { @tag }
}}
@@ -286,30 +309,30 @@ markup::define! {
}
}
@if matches!(node.kind, NodeKind::Collection | NodeKind::Channel) {
- @NodeFilterSortForm { f: filter }
+ @NodeFilterSortForm { f: filter, lang }
}
@if !similar.is_empty() {
- h2 { "Similar Media" }
+ h2 { @trs(lang, "node.similar") }
ul.children.hlist {@for (node, udata) in similar.iter() {
- li { @NodeCard { node, udata } }
+ li { @NodeCard { node, udata, lang } }
}}
}
@match node.kind {
NodeKind::Show | NodeKind::Series | NodeKind::Season => {
ol { @for (node, udata) in children.iter() {
- li { @NodeCardWide { node, udata } }
+ li { @NodeCardWide { node, udata, lang } }
}}
}
NodeKind::Collection | NodeKind::Channel | _ => {
ul.children {@for (node, udata) in children.iter() {
- li { @NodeCard { node, udata } }
+ li { @NodeCard { node, udata, lang } }
}}
}
}
}
}
- Props<'a>(node: &'a Node, udata: &'a NodeUserData, full: bool) {
+ Props<'a>(node: &'a Node, udata: &'a NodeUserData, full: bool, lang: &'a Language) {
.props {
@if let Some(m) = &node.media {
p { @format_duration(m.duration) }
@@ -324,8 +347,8 @@ markup::define! {
}
@match node.visibility {
Visibility::Visible => {}
- Visibility::Reduced => {p.visibility{"Reduced visibility"}}
- Visibility::Hidden => {p.visibility{"Hidden"}}
+ Visibility::Reduced => {p.visibility{@trs(lang, "prop.vis.reduced")}}
+ Visibility::Hidden => {p.visibility{@trs(lang, "prop.vis.hidden")}}
}
// TODO
// @if !node.children.is_empty() {
@@ -349,9 +372,9 @@ markup::define! {
}
@match udata.watched {
WatchedState::None => {}
- WatchedState::Pending => { p.pending { "Watchlisted" } }
- WatchedState::Progress(x) => { p.progress { "Watched up to " @format_duration(x) } }
- WatchedState::Watched => { p.watched { "Watched" } }
+ WatchedState::Pending => { p.pending { @trs(lang, "prop.watched.pending") } }
+ WatchedState::Progress(x) => { p.progress { @trsa(lang, "prop.watched.progress", &[("time", &format_duration(x))]) } }
+ WatchedState::Watched => { p.watched { @trs(lang, "prop.watched.watched") } }
}
}
}