language support
This commit is contained in:
parent
f5ec5db460
commit
cd705c1153
4 changed files with 140 additions and 36 deletions
140
src/iotro.rs
140
src/iotro.rs
|
@ -1,11 +1,125 @@
|
||||||
//! A module for writing intros and outros
|
//! A module for writing intros and outros
|
||||||
|
|
||||||
use crate::{time::format_date_long, ProjectLecture, Resolution};
|
use crate::{time::Date, ProjectLecture, Resolution};
|
||||||
|
use anyhow::anyhow;
|
||||||
|
use std::{
|
||||||
|
fmt::{self, Debug, Display, Formatter},
|
||||||
|
str::FromStr
|
||||||
|
};
|
||||||
use svgwriter::{
|
use svgwriter::{
|
||||||
tags::{Group, Rect, TagWithPresentationAttributes, Text},
|
tags::{Group, Rect, TagWithPresentationAttributes, Text},
|
||||||
Graphic
|
Graphic
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Language<'a> {
|
||||||
|
lang: &'a str,
|
||||||
|
format_date_long: fn(Date) -> String,
|
||||||
|
// intro
|
||||||
|
lecture_from: &'a str,
|
||||||
|
video_created_by_us: &'a str,
|
||||||
|
// outro
|
||||||
|
video_created_by: &'a str,
|
||||||
|
our_website: &'a str,
|
||||||
|
download_videos: &'a str,
|
||||||
|
questions_feedback: &'a str
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const GERMAN: Language<'static> = Language {
|
||||||
|
lang: "de",
|
||||||
|
|
||||||
|
// Format a date in DD. MMMM YYYY format.
|
||||||
|
format_date_long: |d: Date| {
|
||||||
|
let month = match d.month {
|
||||||
|
1 => "Januar",
|
||||||
|
2 => "Februar",
|
||||||
|
3 => "März",
|
||||||
|
4 => "April",
|
||||||
|
5 => "Mai",
|
||||||
|
6 => "Juni",
|
||||||
|
7 => "Juli",
|
||||||
|
8 => "August",
|
||||||
|
9 => "September",
|
||||||
|
10 => "Oktober",
|
||||||
|
11 => "November",
|
||||||
|
12 => "Dezember",
|
||||||
|
_ => unreachable!()
|
||||||
|
};
|
||||||
|
format!("{:02}. {month} {:04}", d.day, d.year)
|
||||||
|
},
|
||||||
|
|
||||||
|
lecture_from: "Vorlesung vom",
|
||||||
|
video_created_by_us: "Video erstellt von der Video AG, Fachschaft I/1",
|
||||||
|
|
||||||
|
video_created_by: "Video erstellt von der",
|
||||||
|
our_website: "Website der Fachschaft",
|
||||||
|
download_videos: "Videos herunterladen",
|
||||||
|
questions_feedback: "Fragen, Vorschläge und Feedback"
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const BRITISH: Language<'static> = Language {
|
||||||
|
lang: "uk",
|
||||||
|
|
||||||
|
// Format a date in DDth MMMM YYYY format.
|
||||||
|
format_date_long: |d: Date| {
|
||||||
|
let month = match d.month {
|
||||||
|
1 => "January",
|
||||||
|
2 => "February",
|
||||||
|
3 => "March",
|
||||||
|
4 => "April",
|
||||||
|
5 => "May",
|
||||||
|
6 => "June",
|
||||||
|
7 => "July",
|
||||||
|
8 => "August",
|
||||||
|
9 => "September",
|
||||||
|
10 => "October",
|
||||||
|
11 => "November",
|
||||||
|
12 => "December",
|
||||||
|
_ => unreachable!()
|
||||||
|
};
|
||||||
|
let th = match d.day {
|
||||||
|
1 | 21 | 31 => "st",
|
||||||
|
2 | 22 => "nd",
|
||||||
|
3 | 23 => "rd",
|
||||||
|
_ => "th"
|
||||||
|
};
|
||||||
|
format!("{:02}{th} {month} {:04}", d.day, d.year)
|
||||||
|
},
|
||||||
|
|
||||||
|
lecture_from: "Lecture from",
|
||||||
|
video_created_by_us: "Video created by the Video AG, Fachschaft I/1",
|
||||||
|
video_created_by: "Video created by the",
|
||||||
|
our_website: "The Fachschaft's website",
|
||||||
|
download_videos: "Download videos",
|
||||||
|
questions_feedback: "Questions, Suggestions and Feedback"
|
||||||
|
};
|
||||||
|
|
||||||
|
impl FromStr for Language<'static> {
|
||||||
|
type Err = anyhow::Error;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
match s {
|
||||||
|
"de" => Ok(GERMAN),
|
||||||
|
"en" | "uk" => Ok(BRITISH),
|
||||||
|
lang => Err(anyhow!("Unknown language {lang:?}"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Language<'_> {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||||
|
f.write_str(self.lang)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for Language<'_> {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||||
|
f.debug_struct("Language")
|
||||||
|
.field("lang", &self.lang)
|
||||||
|
.finish_non_exhaustive()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[repr(u16)]
|
#[repr(u16)]
|
||||||
enum FontSize {
|
enum FontSize {
|
||||||
Huge = 72,
|
Huge = 72,
|
||||||
|
@ -74,6 +188,7 @@ impl Iotro {
|
||||||
pub(crate) fn intro(res: Resolution, lecture: &ProjectLecture) -> Graphic {
|
pub(crate) fn intro(res: Resolution, lecture: &ProjectLecture) -> Graphic {
|
||||||
use self::{FontSize::*, FontWeight::*};
|
use self::{FontSize::*, FontWeight::*};
|
||||||
|
|
||||||
|
let lang = &lecture.lang;
|
||||||
let mut intro = Iotro::new(res);
|
let mut intro = Iotro::new(res);
|
||||||
intro.add_text(Huge, Bold, 110, &lecture.label);
|
intro.add_text(Huge, Bold, 110, &lecture.label);
|
||||||
intro.add_text(Huge, SemiBold, 250, &lecture.docent);
|
intro.add_text(Huge, SemiBold, 250, &lecture.docent);
|
||||||
|
@ -81,31 +196,30 @@ pub(crate) fn intro(res: Resolution, lecture: &ProjectLecture) -> Graphic {
|
||||||
Huge,
|
Huge,
|
||||||
SemiBold,
|
SemiBold,
|
||||||
460,
|
460,
|
||||||
format!("Vorlesung vom {}", format_date_long(lecture.date))
|
format!(
|
||||||
);
|
"{} {}",
|
||||||
intro.add_text(
|
lang.lecture_from,
|
||||||
Big,
|
(lang.format_date_long)(lecture.date)
|
||||||
Normal,
|
)
|
||||||
870,
|
|
||||||
"Video erstellt von der Video AG, Fachschaft I/1"
|
|
||||||
);
|
);
|
||||||
|
intro.add_text(Big, Normal, 870, lang.video_created_by_us);
|
||||||
intro.add_text(Big, Normal, 930, "https://video.fsmpi.rwth-aachen.de");
|
intro.add_text(Big, Normal, 930, "https://video.fsmpi.rwth-aachen.de");
|
||||||
intro.add_text(Big, Normal, 990, "video@fsmpi.rwth-aachen.de");
|
intro.add_text(Big, Normal, 990, "video@fsmpi.rwth-aachen.de");
|
||||||
|
|
||||||
intro.finish()
|
intro.finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn outro(res: Resolution) -> Graphic {
|
pub(crate) fn outro(lang: &Language<'_>, res: Resolution) -> Graphic {
|
||||||
use self::{FontSize::*, FontWeight::*};
|
use self::{FontSize::*, FontWeight::*};
|
||||||
|
|
||||||
let mut outro = Iotro::new(res);
|
let mut outro = Iotro::new(res);
|
||||||
outro.add_text(Large, SemiBold, 50, "Video erstellt von der");
|
outro.add_text(Large, SemiBold, 50, lang.video_created_by);
|
||||||
outro.add_text(Huge, Bold, 210, "Video AG, Fachschaft I/1");
|
outro.add_text(Huge, Bold, 210, "Video AG, Fachschaft I/1");
|
||||||
outro.add_text(Large, Normal, 360, "Website der Fachschaft:");
|
outro.add_text(Large, Normal, 360, format!("{}:", lang.our_website));
|
||||||
outro.add_text(Large, Normal, 430, "https://www.fsmpi.rwth-aachen.de");
|
outro.add_text(Large, Normal, 430, "https://www.fsmpi.rwth-aachen.de");
|
||||||
outro.add_text(Large, Normal, 570, "Videos herunterladen:");
|
outro.add_text(Large, Normal, 570, format!("{}:", lang.download_videos));
|
||||||
outro.add_text(Large, Normal, 640, "https://video.fsmpi.rwth-aachen.de");
|
outro.add_text(Large, Normal, 640, "https://video.fsmpi.rwth-aachen.de");
|
||||||
outro.add_text(Large, Normal, 780, "Fragen, Vorschläge und Feedback:");
|
outro.add_text(Large, Normal, 780, format!("{}:", lang.questions_feedback));
|
||||||
outro.add_text(Large, Normal, 850, "video@fsmpi.rwth-aachen.de");
|
outro.add_text(Large, Normal, 850, "video@fsmpi.rwth-aachen.de");
|
||||||
|
|
||||||
outro.finish()
|
outro.finish()
|
||||||
|
|
12
src/main.rs
12
src/main.rs
|
@ -12,6 +12,7 @@ use crate::{
|
||||||
};
|
};
|
||||||
use camino::Utf8PathBuf as PathBuf;
|
use camino::Utf8PathBuf as PathBuf;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
use iotro::Language;
|
||||||
use rational::Rational;
|
use rational::Rational;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_with::{serde_as, DisplayFromStr};
|
use serde_with::{serde_as, DisplayFromStr};
|
||||||
|
@ -44,6 +45,10 @@ struct Args {
|
||||||
#[clap(short, long, default_value = "Prof. E. Grädel")]
|
#[clap(short, long, default_value = "Prof. E. Grädel")]
|
||||||
docent: String,
|
docent: String,
|
||||||
|
|
||||||
|
/// The language of the lecture. Used for the intro and outro frame.
|
||||||
|
#[clap(short = 'L', long, default_value = "de")]
|
||||||
|
lang: Language<'static>,
|
||||||
|
|
||||||
/// The memory limit for external tools like ffmpeg.
|
/// The memory limit for external tools like ffmpeg.
|
||||||
#[clap(short, long, default_value = "12G")]
|
#[clap(short, long, default_value = "12G")]
|
||||||
mem_limit: String,
|
mem_limit: String,
|
||||||
|
@ -145,7 +150,9 @@ struct ProjectLecture {
|
||||||
label: String,
|
label: String,
|
||||||
docent: String,
|
docent: String,
|
||||||
#[serde_as(as = "DisplayFromStr")]
|
#[serde_as(as = "DisplayFromStr")]
|
||||||
date: Date
|
date: Date,
|
||||||
|
#[serde_as(as = "DisplayFromStr")]
|
||||||
|
lang: Language<'static>
|
||||||
}
|
}
|
||||||
|
|
||||||
#[serde_as]
|
#[serde_as]
|
||||||
|
@ -271,7 +278,8 @@ fn main() {
|
||||||
course,
|
course,
|
||||||
label: args.label,
|
label: args.label,
|
||||||
docent: args.docent,
|
docent: args.docent,
|
||||||
date
|
date,
|
||||||
|
lang: args.lang
|
||||||
},
|
},
|
||||||
source: ProjectSource {
|
source: ProjectSource {
|
||||||
files,
|
files,
|
||||||
|
|
|
@ -272,7 +272,9 @@ impl<'a> Renderer<'a> {
|
||||||
let outro_svg = self.target.join("outro.svg");
|
let outro_svg = self.target.join("outro.svg");
|
||||||
fs::write(
|
fs::write(
|
||||||
&outro_svg,
|
&outro_svg,
|
||||||
outro(source_res).to_string_pretty().into_bytes()
|
outro(&project.lecture.lang, source_res)
|
||||||
|
.to_string_pretty()
|
||||||
|
.into_bytes()
|
||||||
)?;
|
)?;
|
||||||
let outro_mkv = self.outro_mkv();
|
let outro_mkv = self.outro_mkv();
|
||||||
svg2mkv(metadata, outro_svg, outro_mkv, self.format, OUTRO_LEN)?;
|
svg2mkv(metadata, outro_svg, outro_mkv, self.format, OUTRO_LEN)?;
|
||||||
|
|
20
src/time.rs
20
src/time.rs
|
@ -57,26 +57,6 @@ pub fn format_date(d: Date) -> String {
|
||||||
format!("{:02}{:02}{:02}", d.year % 100, d.month, d.day)
|
format!("{:02}{:02}{:02}", d.year % 100, d.month, d.day)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Format a date in DD. MMMM YYYY format.
|
|
||||||
pub fn format_date_long(d: Date) -> String {
|
|
||||||
let month = match d.month {
|
|
||||||
1 => "Januar",
|
|
||||||
2 => "Februar",
|
|
||||||
3 => "März",
|
|
||||||
4 => "April",
|
|
||||||
5 => "Mai",
|
|
||||||
6 => "Juni",
|
|
||||||
7 => "Juli",
|
|
||||||
8 => "August",
|
|
||||||
9 => "September",
|
|
||||||
10 => "Oktober",
|
|
||||||
11 => "November",
|
|
||||||
12 => "Dezember",
|
|
||||||
_ => unreachable!()
|
|
||||||
};
|
|
||||||
format!("{:02}. {month} {:04}", d.day, d.year)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)]
|
||||||
pub struct Time {
|
pub struct Time {
|
||||||
pub seconds: u32,
|
pub seconds: u32,
|
||||||
|
|
Loading…
Reference in a new issue