translations #2
This commit is contained in:
parent
07c02052fd
commit
6efbfc0e9c
15
Cargo.lock
generated
15
Cargo.lock
generated
@ -1288,6 +1288,7 @@ dependencies = [
|
|||||||
"fluent-resmgr",
|
"fluent-resmgr",
|
||||||
"log",
|
"log",
|
||||||
"ovlach_data",
|
"ovlach_data",
|
||||||
|
"phf",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"rocket",
|
"rocket",
|
||||||
"rocket_dyn_templates",
|
"rocket_dyn_templates",
|
||||||
@ -1410,6 +1411,7 @@ version = "0.11.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc"
|
checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"phf_macros",
|
||||||
"phf_shared",
|
"phf_shared",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -1433,6 +1435,19 @@ dependencies = [
|
|||||||
"rand",
|
"rand",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "phf_macros"
|
||||||
|
version = "0.11.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b"
|
||||||
|
dependencies = [
|
||||||
|
"phf_generator",
|
||||||
|
"phf_shared",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "phf_shared"
|
name = "phf_shared"
|
||||||
version = "0.11.2"
|
version = "0.11.2"
|
||||||
|
@ -20,3 +20,4 @@ sha256 = "1.4.0"
|
|||||||
fluent-bundle = "0.15.2"
|
fluent-bundle = "0.15.2"
|
||||||
fluent-resmgr = "0.0.6"
|
fluent-resmgr = "0.0.6"
|
||||||
unic-langid = "0.9.1"
|
unic-langid = "0.9.1"
|
||||||
|
phf = { version = "0.11.2", features = ["macros"] }
|
@ -1,8 +1,6 @@
|
|||||||
|
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
use rocket::{*, fairing::AdHoc};
|
use rocket::{*, fairing::AdHoc};
|
||||||
use rocket_dyn_templates::{Template, tera::Value};
|
use rocket_dyn_templates::Template;
|
||||||
use ::serde::Deserialize;
|
use ::serde::Deserialize;
|
||||||
use tools::tera::{static_filter, translate_filter, calculate_age, insert_space_every, lang_entity, gravatar_link};
|
use tools::tera::{static_filter, translate_filter, calculate_age, insert_space_every, lang_entity, gravatar_link};
|
||||||
|
|
||||||
@ -44,7 +42,10 @@ pub fn rocket_builder() -> Rocket<Build> {
|
|||||||
AdHoc::config::<PresentationConfig>()
|
AdHoc::config::<PresentationConfig>()
|
||||||
).attach(
|
).attach(
|
||||||
AdHoc::config::<CVBackendConfig>()
|
AdHoc::config::<CVBackendConfig>()
|
||||||
|
).attach(
|
||||||
|
tools::rocket::RequestTimer
|
||||||
).mount("/", routes![
|
).mount("/", routes![
|
||||||
routes::root::index
|
routes::root::index,
|
||||||
|
routes::root::index_without_lang
|
||||||
])
|
])
|
||||||
}
|
}
|
@ -1,10 +1,10 @@
|
|||||||
use log::error;
|
use log::error;
|
||||||
use ovlach_data::cv::cv::CV;
|
use ovlach_data::cv::cv::CV;
|
||||||
use rocket::{get, State, response::status::NotFound, http::Status};
|
use rocket::{get, State, response::Redirect, http::Status};
|
||||||
use rocket_dyn_templates::{Template, context};
|
use rocket_dyn_templates::Template;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
use crate::{PresentationConfig, services::cv::fetch_cv_data_from_backend, CVBackendConfig};
|
use crate::{PresentationConfig, services::cv::fetch_cv_data_from_backend, CVBackendConfig, tools::rocket::RequestLanguage};
|
||||||
|
|
||||||
#[derive(Serialize, Debug)]
|
#[derive(Serialize, Debug)]
|
||||||
struct RootPage {
|
struct RootPage {
|
||||||
@ -14,14 +14,14 @@ struct RootPage {
|
|||||||
lang: String,
|
lang: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/")]
|
#[get("/<language>")]
|
||||||
pub async fn index(presentation_config: &State<PresentationConfig>, cv_config: &State<CVBackendConfig>) -> Result<Template, Status> {
|
pub async fn index(presentation_config: &State<PresentationConfig>, cv_config: &State<CVBackendConfig>, language: RequestLanguage) -> Result<Template, Status> {
|
||||||
let context = match fetch_cv_data_from_backend(cv_config.cv_backend_path.clone()).await {
|
let context = match fetch_cv_data_from_backend(cv_config.cv_backend_path.clone()).await {
|
||||||
Ok(cv) => RootPage {
|
Ok(cv) => RootPage {
|
||||||
static_host: presentation_config.static_route.clone(),
|
static_host: presentation_config.static_route.clone(),
|
||||||
cv,
|
cv,
|
||||||
download_cv_url: "FIXME!".to_string(),
|
download_cv_url: "FIXME!".to_string(),
|
||||||
lang: "en".to_string(),
|
lang: language.language,
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
error!("Can't fetch CV data from backend {:?}", e);
|
error!("Can't fetch CV data from backend {:?}", e);
|
||||||
@ -29,7 +29,12 @@ pub async fn index(presentation_config: &State<PresentationConfig>, cv_config: &
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//return Templ;
|
|
||||||
|
|
||||||
Ok(Template::render("default", &context))
|
Ok(Template::render("default", &context))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[get("/")]
|
||||||
|
pub fn index_without_lang() -> Redirect {
|
||||||
|
// Default language is czech (TODO: config)
|
||||||
|
Redirect::to(format!("{}/{}", "", "cs"))
|
||||||
|
}
|
||||||
|
@ -1 +1,2 @@
|
|||||||
pub mod tera;
|
pub mod tera;
|
||||||
|
pub mod rocket;
|
||||||
|
83
src/tools/rocket.rs
Normal file
83
src/tools/rocket.rs
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
use std::time::SystemTime;
|
||||||
|
use log::info;
|
||||||
|
use rocket::{Request, Response, Data, fairing::{Kind, Info, Fairing}, request::{self, FromRequest, FromParam}, http::Status};
|
||||||
|
use phf::phf_map;
|
||||||
|
|
||||||
|
|
||||||
|
pub struct RequestLanguage {
|
||||||
|
pub language: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
static LANG_TO_CODES: phf::Map<&'static str, &'static str> = phf_map! {
|
||||||
|
"cs" => "cs-CZ",
|
||||||
|
"en" => "en-US",
|
||||||
|
};
|
||||||
|
|
||||||
|
impl<'r> FromParam<'r> for RequestLanguage {
|
||||||
|
type Error = &'r str;
|
||||||
|
|
||||||
|
fn from_param(param: &'r str) -> Result<Self, Self::Error> {
|
||||||
|
match LANG_TO_CODES.get(param) {
|
||||||
|
Some(val) => Ok(RequestLanguage {
|
||||||
|
language: val.to_string(),
|
||||||
|
}),
|
||||||
|
None => Ok(RequestLanguage {
|
||||||
|
language: LANG_TO_CODES["en"].to_string(),
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Fairing for timing requests.
|
||||||
|
pub struct RequestTimer;
|
||||||
|
|
||||||
|
/// Value stored in request-local state.
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
struct TimerStart(Option<SystemTime>);
|
||||||
|
|
||||||
|
#[rocket::async_trait]
|
||||||
|
impl Fairing for RequestTimer {
|
||||||
|
fn info(&self) -> Info {
|
||||||
|
Info {
|
||||||
|
name: "Request Timer",
|
||||||
|
kind: Kind::Request | Kind::Response
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Stores the start time of the request in request-local state.
|
||||||
|
async fn on_request(&self, request: &mut Request<'_>, _: &mut Data<'_>) {
|
||||||
|
// Store a `TimerStart` instead of directly storing a `SystemTime`
|
||||||
|
// to ensure that this usage doesn't conflict with anything else
|
||||||
|
// that might store a `SystemTime` in request-local cache.
|
||||||
|
request.local_cache(|| TimerStart(Some(SystemTime::now())));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Adds a header to the response indicating how long the server took to
|
||||||
|
/// process the request.
|
||||||
|
async fn on_response<'r>(&self, req: &'r Request<'_>, res: &mut Response<'r>) {
|
||||||
|
let start_time = req.local_cache(|| TimerStart(None));
|
||||||
|
if let Some(Ok(duration)) = start_time.0.map(|st| st.elapsed()) {
|
||||||
|
let ms = duration.as_secs() * 1000 + duration.subsec_millis() as u64;
|
||||||
|
res.set_raw_header("X-Response-Time", format!("{} ms", ms));
|
||||||
|
info!("Response time: {} ms", ms);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Request guard used to retrieve the start time of a request.
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct StartTime(pub SystemTime);
|
||||||
|
|
||||||
|
// Allows a route to access the time a request was initiated.
|
||||||
|
#[rocket::async_trait]
|
||||||
|
impl<'r> FromRequest<'r> for StartTime {
|
||||||
|
type Error = ();
|
||||||
|
|
||||||
|
async fn from_request(request: &'r Request<'_>) -> request::Outcome<Self, ()> {
|
||||||
|
match *request.local_cache(|| TimerStart(None)) {
|
||||||
|
TimerStart(Some(time)) => request::Outcome::Success(StartTime(time)),
|
||||||
|
TimerStart(None) => request::Outcome::Error((Status::InternalServerError, ())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,9 +4,8 @@ use chrono::{Utc, Datelike};
|
|||||||
use log::error;
|
use log::error;
|
||||||
use rocket_dyn_templates::tera::{Value, Error};
|
use rocket_dyn_templates::tera::{Value, Error};
|
||||||
use ovlach_data::cv::chrono::from_string;
|
use ovlach_data::cv::chrono::from_string;
|
||||||
use sha256::{digest, try_digest};
|
use sha256::digest;
|
||||||
use fluent_resmgr::resource_manager::ResourceManager;
|
use fluent_resmgr::resource_manager::ResourceManager;
|
||||||
use tokio::sync::broadcast::error;
|
|
||||||
use unic_langid::LanguageIdentifier;
|
use unic_langid::LanguageIdentifier;
|
||||||
|
|
||||||
// TODO: tenhle modul je trochu prasacky..
|
// TODO: tenhle modul je trochu prasacky..
|
||||||
@ -23,9 +22,10 @@ pub fn translate_filter(
|
|||||||
value: &Value,
|
value: &Value,
|
||||||
args: &HashMap<String, rocket_dyn_templates::tera::Value>
|
args: &HashMap<String, rocket_dyn_templates::tera::Value>
|
||||||
) -> Result<Value, Error> {
|
) -> Result<Value, Error> {
|
||||||
|
// TODO: prepis me!
|
||||||
let mgr = ResourceManager::new("./resources/{locale}/{res_id}".into());
|
let mgr = ResourceManager::new("./resources/{locale}/{res_id}".into());
|
||||||
let locales = vec![LanguageIdentifier::from_str("en-US").unwrap()];
|
let lang = args["lang"].as_str().unwrap();
|
||||||
let val_id = vec![value.as_str().unwrap().to_string()];
|
let locales = vec![LanguageIdentifier::from_str(lang).unwrap()];
|
||||||
let val = value.as_str().unwrap().to_string();
|
let val = value.as_str().unwrap().to_string();
|
||||||
|
|
||||||
let bundle = mgr.get_bundle(locales, vec!["ovlach_frontend".to_string()]);
|
let bundle = mgr.get_bundle(locales, vec!["ovlach_frontend".to_string()]);
|
||||||
@ -54,7 +54,7 @@ pub fn translate_filter(
|
|||||||
|
|
||||||
pub fn lang_entity(
|
pub fn lang_entity(
|
||||||
value: &Value,
|
value: &Value,
|
||||||
args: &HashMap<String, rocket_dyn_templates::tera::Value>
|
_: &HashMap<String, rocket_dyn_templates::tera::Value>
|
||||||
) -> Result<Value, Error> {
|
) -> Result<Value, Error> {
|
||||||
error!("{:?}", value); // TODO: rewrite me!!!
|
error!("{:?}", value); // TODO: rewrite me!!!
|
||||||
return Ok(rocket_dyn_templates::tera::Value::String(format!("{}", value["en"].as_str().unwrap()))); // TODO: fix-me here!
|
return Ok(rocket_dyn_templates::tera::Value::String(format!("{}", value["en"].as_str().unwrap()))); // TODO: fix-me here!
|
||||||
@ -62,7 +62,7 @@ pub fn lang_entity(
|
|||||||
|
|
||||||
pub fn gravatar_link(
|
pub fn gravatar_link(
|
||||||
value: &Value,
|
value: &Value,
|
||||||
args: &HashMap<String, rocket_dyn_templates::tera::Value>
|
_: &HashMap<String, rocket_dyn_templates::tera::Value>
|
||||||
) -> Result<Value, Error> {
|
) -> Result<Value, Error> {
|
||||||
let val = digest(value.as_str().unwrap());
|
let val = digest(value.as_str().unwrap());
|
||||||
return Ok(rocket_dyn_templates::tera::Value::String(format!("https://gravatar.com/avatar/{}", val))); // TODO: fix-me here!
|
return Ok(rocket_dyn_templates::tera::Value::String(format!("https://gravatar.com/avatar/{}", val))); // TODO: fix-me here!
|
||||||
@ -72,7 +72,7 @@ pub fn insert_space_every(
|
|||||||
value: &Value,
|
value: &Value,
|
||||||
args: &HashMap<String, rocket_dyn_templates::tera::Value>
|
args: &HashMap<String, rocket_dyn_templates::tera::Value>
|
||||||
) -> Result<Value, Error> {
|
) -> Result<Value, Error> {
|
||||||
let mut input = value.as_u64().unwrap().to_string();
|
let input = value.as_u64().unwrap().to_string();
|
||||||
let times = args.get("times").unwrap().as_u64().unwrap();
|
let times = args.get("times").unwrap().as_u64().unwrap();
|
||||||
let mut result = String::new();
|
let mut result = String::new();
|
||||||
|
|
||||||
@ -88,7 +88,7 @@ pub fn insert_space_every(
|
|||||||
|
|
||||||
pub fn calculate_age(
|
pub fn calculate_age(
|
||||||
value: &Value,
|
value: &Value,
|
||||||
args: &HashMap<String, rocket_dyn_templates::tera::Value>
|
_: &HashMap<String, rocket_dyn_templates::tera::Value>
|
||||||
) -> Result<Value, Error> {
|
) -> Result<Value, Error> {
|
||||||
error!("{:?}", value.as_str());
|
error!("{:?}", value.as_str());
|
||||||
//let s = value.to_string().trim_matches('"'); // TODO: unwrap here!
|
//let s = value.to_string().trim_matches('"'); // TODO: unwrap here!
|
||||||
|
Loading…
Reference in New Issue
Block a user