Update rocket_i18n and add gettext_macros (#431)

Internationalization now uses proc-macros that generate the .pot file
automatically.
This commit is contained in:
Baptiste Gelez
2019-02-02 15:23:50 +01:00
committed by GitHub
parent 8696185d1e
commit 7eef4643c8
57 changed files with 6306 additions and 5484 deletions
+10 -4
View File
@@ -10,6 +10,9 @@ extern crate ctrlc;
extern crate diesel;
extern crate dotenv;
extern crate failure;
#[macro_use]
extern crate gettext_macros;
extern crate gettext_utils;
extern crate guid_create;
extern crate heck;
extern crate multipart;
@@ -21,7 +24,6 @@ extern crate plume_models;
extern crate rocket;
extern crate rocket_contrib;
extern crate rocket_csrf;
#[macro_use]
extern crate rocket_i18n;
extern crate scheduled_thread_pool;
extern crate serde;
@@ -52,12 +54,18 @@ use std::process::exit;
use std::sync::Arc;
use std::time::Duration;
init_i18n!("plume", de, en, fr, gl, it, ja, nb, pl, ru);
mod api;
mod inbox;
#[macro_use]
mod template_utils;
mod routes;
include!(concat!(env!("OUT_DIR"), "/templates.rs"));
compile_i18n!();
type Worker<'a> = State<'a, ScheduledThreadPool>;
type Searcher<'a> = State<'a, Arc<UnmanagedSearcher>>;
@@ -216,7 +224,7 @@ Then try to restart Plume.
.manage(dbpool)
.manage(workpool)
.manage(searcher)
.manage(include_i18n!("plume", [ "de", "en", "fr", "gl", "it", "ja", "nb", "pl", "ru" ]))
.manage(include_i18n!())
.attach(CsrfFairingBuilder::new()
.set_default_target("/csrf-violation?target=<uri>".to_owned(), rocket::http::Method::Post)
.add_exceptions(vec![
@@ -229,5 +237,3 @@ Then try to restart Plume.
.finalize().expect("main: csrf fairing creation error"))
.launch();
}
include!(concat!(env!("OUT_DIR"), "/templates.rs"));
+2 -2
View File
@@ -62,7 +62,7 @@ pub fn new(user: User, conn: DbConn, intl: I18n) -> Ructe {
#[get("/blogs/new", rank = 2)]
pub fn new_auth(i18n: I18n) -> Flash<Redirect>{
utils::requires_login(
i18n!(i18n.catalog, "You need to be logged in order to create a new blog"),
&i18n!(i18n.catalog, "You need to be logged in order to create a new blog"),
uri!(new)
)
}
@@ -133,7 +133,7 @@ pub fn delete(conn: DbConn, name: String, user: Option<User>, intl: I18n, search
// TODO actually return 403 error code
Err(render!(errors::not_authorized(
&(&*conn, &intl.catalog, user),
"You are not allowed to delete this blog."
i18n!(intl.catalog, "You are not allowed to delete this blog.")
)))
}
}
+1 -1
View File
@@ -38,7 +38,7 @@ pub fn create(blog: String, slug: String, user: User, conn: DbConn, worker: Work
#[post("/~/<blog>/<slug>/like", rank = 2)]
pub fn create_auth(blog: String, slug: String, i18n: I18n) -> Flash<Redirect>{
utils::requires_login(
i18n!(i18n.catalog, "You need to be logged in order to like a post"),
&i18n!(i18n.catalog, "You need to be logged in order to like a post"),
uri!(create: blog = blog, slug = slug)
)
}
+1 -1
View File
@@ -20,7 +20,7 @@ pub fn notifications(conn: DbConn, user: User, page: Option<Page>, intl: I18n) -
#[get("/notifications?<page>", rank = 2)]
pub fn notifications_auth(i18n: I18n, page: Option<Page>) -> Flash<Redirect>{
utils::requires_login(
i18n!(i18n.catalog, "You need to be logged in order to see your notifications"),
&i18n!(i18n.catalog, "You need to be logged in order to see your notifications"),
uri!(notifications: page = page)
)
}
+9 -4
View File
@@ -78,7 +78,7 @@ pub fn details(blog: String, slug: String, conn: DbConn, user: Option<User>, res
} else {
Ok(render!(errors::not_authorized(
&(&*conn, &intl.catalog, user.clone()),
"This post isn't published yet."
i18n!(intl.catalog, "This post isn't published yet.")
)))
}
}
@@ -97,7 +97,7 @@ pub fn activity_details(blog: String, slug: String, conn: DbConn, _ap: ApRequest
#[get("/~/<blog>/new", rank = 2)]
pub fn new_auth(blog: String, i18n: I18n) -> Flash<Redirect> {
utils::requires_login(
i18n!(i18n.catalog, "You need to be logged in order to write a new post"),
&i18n!(i18n.catalog, "You need to be logged in order to write a new post"),
uri!(new: blog = blog)
)
}
@@ -110,12 +110,13 @@ pub fn new(blog: String, user: User, cl: ContentLen, conn: DbConn, intl: I18n) -
// TODO actually return 403 error code
Ok(render!(errors::not_authorized(
&(&*conn, &intl.catalog, Some(user)),
"You are not author in this blog."
i18n!(intl.catalog, "You are not author in this blog.")
)))
} else {
let medias = Media::for_user(&*conn, user.id)?;
Ok(render!(posts::new(
&(&*conn, &intl.catalog, Some(user)),
i18n!(intl.catalog, "New post"),
b,
false,
&NewPostForm {
@@ -139,7 +140,7 @@ pub fn edit(blog: String, slug: String, user: User, cl: ContentLen, conn: DbConn
if !user.is_author_in(&*conn, &b)? {
Ok(render!(errors::not_authorized(
&(&*conn, &intl.catalog, Some(user)),
"You are not author in this blog."
i18n!(intl.catalog, "You are not author in this blog.")
)))
} else {
let source = if !post.source.is_empty() {
@@ -149,8 +150,10 @@ pub fn edit(blog: String, slug: String, user: User, cl: ContentLen, conn: DbConn
};
let medias = Media::for_user(&*conn, user.id)?;
let title = post.title.clone();
Ok(render!(posts::new(
&(&*conn, &intl.catalog, Some(user)),
i18n!(intl.catalog, "Edit {0}"; &title),
b,
true,
&NewPostForm {
@@ -257,6 +260,7 @@ pub fn update(blog: String, slug: String, user: User, cl: ContentLen, form: Leni
let medias = Media::for_user(&*conn, user.id).expect("posts:update: medias error");
Err(render!(posts::new(
&(&*conn, &intl.catalog, Some(user)),
i18n!(intl.catalog, "Edit {0}"; &form.title),
b,
true,
&*form,
@@ -381,6 +385,7 @@ pub fn create(blog_name: String, form: LenientForm<NewPostForm>, user: User, cl:
let medias = Media::for_user(&*conn, user.id).expect("posts::create: medias error");
Err(Ok(render!(posts::new(
&(&*conn, &intl.catalog, Some(user)),
i18n!(intl.catalog, "New post"),
blog,
false,
&*form,
+1 -1
View File
@@ -38,7 +38,7 @@ pub fn create(blog: String, slug: String, user: User, conn: DbConn, worker: Work
#[post("/~/<blog>/<slug>/reshare", rank=1)]
pub fn create_auth(blog: String, slug: String, i18n: I18n) -> Flash<Redirect> {
utils::requires_login(
i18n!(i18n.catalog, "You need to be logged in order to reshare a post"),
&i18n!(i18n.catalog, "You need to be logged in order to reshare a post"),
uri!(create: blog = blog, slug = slug)
)
}
+3 -3
View File
@@ -128,7 +128,7 @@ pub fn dashboard(user: User, conn: DbConn, intl: I18n) -> Result<Ructe, ErrorPag
#[get("/dashboard", rank = 2)]
pub fn dashboard_auth(i18n: I18n) -> Flash<Redirect> {
utils::requires_login(
i18n!(i18n.catalog, "You need to be logged in order to access your dashboard"),
&i18n!(i18n.catalog, "You need to be logged in order to access your dashboard"),
uri!(dashboard),
)
}
@@ -161,7 +161,7 @@ pub fn follow(name: String, conn: DbConn, user: User, worker: Worker) -> Result<
#[post("/@/<name>/follow", rank = 2)]
pub fn follow_auth(name: String, i18n: I18n) -> Flash<Redirect> {
utils::requires_login(
i18n!(i18n.catalog, "You need to be logged in order to follow someone"),
&i18n!(i18n.catalog, "You need to be logged in order to follow someone"),
uri!(follow: name = name),
)
}
@@ -224,7 +224,7 @@ pub fn edit(name: String, user: User, conn: DbConn, intl: I18n) -> Result<Ructe,
#[get("/@/<name>/edit", rank = 2)]
pub fn edit_auth(name: String, i18n: I18n) -> Flash<Redirect> {
utils::requires_login(
i18n!(i18n.catalog, "You need to be logged in order to edit your profile"),
&i18n!(i18n.catalog, "You need to be logged in order to edit your profile"),
uri!(edit: name = name),
)
}
+21 -7
View File
@@ -1,4 +1,4 @@
use plume_models::{Connection, users::User};
use plume_models::{Connection, notifications::*, users::User};
use rocket::response::Content;
use rocket_i18n::Catalog;
use templates::Html;
@@ -28,6 +28,18 @@ macro_rules! render {
}
}
pub fn translate_notification(ctx: BaseContext, notif: Notification) -> String {
let name = notif.get_actor(ctx.0).unwrap().name(ctx.0);
match notif.kind.as_ref() {
notification_kind::COMMENT => i18n!(ctx.1, "{0} commented your article."; &name),
notification_kind::FOLLOW => i18n!(ctx.1, "{0} is now following you."; &name),
notification_kind::LIKE => i18n!(ctx.1, "{0} liked your article."; &name),
notification_kind::MENTION => i18n!(ctx.1, "{0} mentioned you."; &name),
notification_kind::RESHARE => i18n!(ctx.1, "{0} boosted your article."; &name),
_ => unreachable!("translate_notification: Unknow type"),
}
}
pub enum Size {
Small,
Medium,
@@ -57,7 +69,7 @@ pub fn avatar(conn: &Connection, user: &User, size: Size, pad: bool, catalog: &C
))
}
pub fn tabs(links: &[(&str, &str, bool)]) -> Html<String> {
pub fn tabs(links: &[(&str, String, bool)]) -> Html<String> {
let mut res = String::from(r#"<div class="tabs">"#);
for (url, title, selected) in links {
res.push_str(r#"<a href=""#);
@@ -117,6 +129,7 @@ macro_rules! input {
{
use validator::ValidationErrorsKind;
use std::borrow::Cow;
let cat = $catalog;
Html(format!(r#"
<label for="{name}">
@@ -128,16 +141,16 @@ macro_rules! input {
<input type="{kind}" id="{name}" name="{name}" value="{val}" {props}/>
"#,
name = stringify!($name),
label = i18n!($catalog, $label),
label = i18n!(cat, $label),
kind = stringify!($kind),
optional = if $optional { format!("<small>{}</small>", i18n!($catalog, "Optional")) } else { String::new() },
optional = if $optional { format!("<small>{}</small>", i18n!(cat, "Optional")) } else { String::new() },
details = if $details.len() > 0 {
format!("<small>{}</small>", i18n!($catalog, $details))
format!("<small>{}</small>", i18n!(cat, $details))
} else {
String::new()
},
error = if let Some(ValidationErrorsKind::Field(errs)) = $err.errors().get(stringify!($name)) {
format!(r#"<p class="error">{}</p>"#, i18n!($catalog, &*errs[0].message.clone().unwrap_or(Cow::from("Unknown error"))))
format!(r#"<p class="error">{}</p>"#, errs[0].message.clone().unwrap_or(Cow::from("Unknown error")))
} else {
String::new()
},
@@ -163,12 +176,13 @@ macro_rules! input {
};
($catalog:expr, $name:tt ($kind:tt), $label:expr, $props:expr) => {
{
let cat = $catalog;
Html(format!(r#"
<label for="{name}">{label}</label>
<input type="{kind}" id="{name}" name="{name}" {props}/>
"#,
name = stringify!($name),
label = i18n!($catalog, $label),
label = i18n!(cat, $label),
kind = stringify!($kind),
props = $props
))