From cafb0e2277eb7f2a6b1f608a8c13bba37926bc5f Mon Sep 17 00:00:00 2001 From: Bat Date: Sun, 17 Jun 2018 15:28:44 +0100 Subject: [PATCH] Use the rocket_i18n crate --- Cargo.lock | 13 ++++++ Cargo.toml | 4 ++ src/i18n.rs | 130 ---------------------------------------------------- src/main.rs | 6 +-- 4 files changed, 20 insertions(+), 133 deletions(-) delete mode 100644 src/i18n.rs diff --git a/Cargo.lock b/Cargo.lock index 099e504b..c6875108 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1014,6 +1014,7 @@ dependencies = [ "rocket 0.4.0-dev (git+https://github.com/SergioBenitez/Rocket?rev=df7111143e466c18d1f56377a8d9530a5a306aba)", "rocket_codegen 0.4.0-dev (git+https://github.com/SergioBenitez/Rocket?rev=df7111143e466c18d1f56377a8d9530a5a306aba)", "rocket_contrib 0.4.0-dev (git+https://github.com/SergioBenitez/Rocket?rev=df7111143e466c18d1f56377a8d9530a5a306aba)", + "rocket_i18n 0.1.1 (git+https://github.com/BaptisteGelez/rocket_i18n?rev=457b88c59ec31905a9193df43df58bee55b4b83d)", "serde 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.43 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1269,6 +1270,17 @@ dependencies = [ "time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rocket_i18n" +version = "0.1.1" +source = "git+https://github.com/BaptisteGelez/rocket_i18n?rev=457b88c59ec31905a9193df43df58bee55b4b83d#457b88c59ec31905a9193df43df58bee55b4b83d" +dependencies = [ + "gettext-rs 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rocket 0.4.0-dev (git+https://github.com/SergioBenitez/Rocket?rev=df7111143e466c18d1f56377a8d9530a5a306aba)", + "serde_json 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", + "tera 0.11.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rustc-demangle" version = "0.1.7" @@ -2085,6 +2097,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rocket_codegen_next 0.4.0-dev (git+https://github.com/SergioBenitez/Rocket?rev=df7111143e466c18d1f56377a8d9530a5a306aba)" = "" "checksum rocket_contrib 0.4.0-dev (git+https://github.com/SergioBenitez/Rocket?rev=df7111143e466c18d1f56377a8d9530a5a306aba)" = "" "checksum rocket_http 0.4.0-dev (git+https://github.com/SergioBenitez/Rocket?rev=df7111143e466c18d1f56377a8d9530a5a306aba)" = "" +"checksum rocket_i18n 0.1.1 (git+https://github.com/BaptisteGelez/rocket_i18n?rev=457b88c59ec31905a9193df43df58bee55b4b83d)" = "" "checksum rustc-demangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11fb43a206a04116ffd7cfcf9bcb941f8eb6cc7ff667272246b0a1c74259a3cb" "checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f" "checksum schannel 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "85fd9df495640643ad2d00443b3d78aae69802ad488debab4f1dd52fc1806ade" diff --git a/Cargo.toml b/Cargo.toml index 7c5f9d98..b1753932 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,3 +45,7 @@ rev = "df7111143e466c18d1f56377a8d9530a5a306aba" features = ["tera_templates", "json"] git = "https://github.com/SergioBenitez/Rocket" rev = "df7111143e466c18d1f56377a8d9530a5a306aba" + +[dependencies.rocket_i18n] +git = "https://github.com/BaptisteGelez/rocket_i18n" +rev = "457b88c59ec31905a9193df43df58bee55b4b83d" diff --git a/src/i18n.rs b/src/i18n.rs deleted file mode 100644 index e8347838..00000000 --- a/src/i18n.rs +++ /dev/null @@ -1,130 +0,0 @@ -use gettextrs::*; -use rocket::{Data, Request, Rocket, fairing::{Fairing, Info, Kind}}; -use serde_json; -use std::collections::HashMap; -use std::env; -use std::fs; -use std::io::{BufRead, BufReader}; -use std::path::{Path, PathBuf}; -use std::process::Command; -use tera::{Tera, Error as TeraError}; - -const ACCEPT_LANG: &'static str = "Accept-Language"; - -pub struct I18n { - domain: &'static str -} - -impl I18n { - pub fn new(domain: &'static str) -> I18n { - I18n { - domain: domain - } - } -} - -impl Fairing for I18n { - fn info(&self) -> Info { - Info { - name: "Gettext I18n", - kind: Kind::Attach | Kind::Request - } - } - - fn on_attach(&self, rocket: Rocket) -> Result { - update_po(self.domain); - compile_po(self.domain); - - bindtextdomain(self.domain, fs::canonicalize(&PathBuf::from("./translations/")).unwrap().to_str().unwrap()); - textdomain(self.domain); - Ok(rocket) - } - - fn on_request(&self, request: &mut Request, _: &Data) { - let lang = request - .headers() - .get_one(ACCEPT_LANG) - .unwrap_or("en") - .split(",") - .nth(0) - .unwrap_or("en"); - - // We can't use setlocale(LocaleCategory::LcAll, lang), because it only accepts system-wide installed - // locales (and most of the time there are only a few of them). - // But, when we set the LANGUAGE environment variable, and an empty string as a second parameter to - // setlocale, gettext will be smart enough to find a matching locale in the locally installed ones. - env::set_var("LANGUAGE", lang); - setlocale(LocaleCategory::LcAll, ""); - } -} - -fn update_po(domain: &str) { - let pot_path = Path::new("po").join(format!("{}.pot", domain)); - - for lang in get_locales() { - let po_path = Path::new("po").join(format!("{}.po", lang.clone())); - if po_path.exists() && po_path.is_file() { - println!("Updating {}", lang.clone()); - // Update it - Command::new("msgmerge") - .arg("-U") - .arg(po_path.to_str().unwrap()) - .arg(pot_path.to_str().unwrap()) - .spawn() - .expect("Couldn't update PO file"); - } else { - println!("Creating {}", lang.clone()); - // Create it from the template - Command::new("msginit") - .arg(format!("--input={}", pot_path.to_str().unwrap())) - .arg(format!("--output-file={}", po_path.to_str().unwrap())) - .arg("-l") - .arg(lang) - .arg("--no-translator") - .spawn() - .expect("Couldn't init PO file"); - } - } -} - -fn compile_po(domain: &str) { - for lang in get_locales() { - let po_path = Path::new("po").join(format!("{}.po", lang.clone())); - let mo_dir = Path::new("translations") - .join(lang.clone()) - .join("LC_MESSAGES"); - fs::create_dir_all(mo_dir.clone()).expect("Couldn't create MO directory"); - let mo_path = mo_dir.join(format!("{}.mo", domain)); - - Command::new("msgfmt") - .arg(format!("--output-file={}", mo_path.to_str().unwrap())) - .arg(po_path) - .spawn() - .expect("Couldn't compile translations"); - } -} - -fn get_locales() -> Vec { - let linguas_file = fs::File::open(Path::new("po").join("LINGUAS")).expect("Couldn't find po/LINGUAS file"); - let linguas = BufReader::new(&linguas_file); - linguas.lines().map(Result::unwrap).collect() -} - -fn tera_gettext(msg: serde_json::Value, ctx: HashMap) -> Result { - let trans = gettext(msg.as_str().unwrap()); - Ok(serde_json::Value::String(Tera::one_off(trans.as_ref(), &ctx, false).unwrap_or(String::from("")))) -} - -fn tera_ngettext(msg: serde_json::Value, ctx: HashMap) -> Result { - let trans = ngettext( - ctx.get("singular").unwrap().as_str().unwrap(), - msg.as_str().unwrap(), - ctx.get("count").unwrap().as_u64().unwrap() as u32 - ); - Ok(serde_json::Value::String(Tera::one_off(trans.as_ref(), &ctx, false).unwrap_or(String::from("")))) -} - -pub fn tera(t: &mut Tera) { - t.register_filter("_", tera_gettext); - t.register_filter("_n", tera_ngettext); -} diff --git a/src/main.rs b/src/main.rs index 45451476..a1ffd406 100644 --- a/src/main.rs +++ b/src/main.rs @@ -25,6 +25,7 @@ extern crate openssl; extern crate reqwest; extern crate rocket; extern crate rocket_contrib; +extern crate rocket_i18n; extern crate serde; #[macro_use] extern crate serde_derive; @@ -40,7 +41,6 @@ use std::env; mod activity_pub; mod db_conn; -mod i18n; mod models; mod schema; mod routes; @@ -130,8 +130,8 @@ fn main() { ]) .manage(init_pool()) .attach(Template::custom(|engines| { - i18n::tera(&mut engines.tera); + rocket_i18n::tera(&mut engines.tera); })) - .attach(i18n::I18n::new("plume")) + .attach(rocket_i18n::I18n::new("plume")) .launch(); }