From 4ae19c6fa773ab1b0fb96a3beecb2778fd52477c Mon Sep 17 00:00:00 2001 From: Stephen Burgess Date: Mon, 11 Jun 2018 18:30:31 -0500 Subject: [PATCH 01/39] feat(Posts): Show username if no display name is present --- templates/posts/details.html.tera | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/templates/posts/details.html.tera b/templates/posts/details.html.tera index 5c658d3..e126f22 100644 --- a/templates/posts/details.html.tera +++ b/templates/posts/details.html.tera @@ -9,8 +9,13 @@ {% endblock header %} {% block content %} +{% if author.display_name %} + {% set name = author.display_name %} +{% else %} + {% set name = author.username %} +{% endif %}

- Written by {{ author.display_name }} + Written by {{name }}{{ date | date(format="%B %e, %Y") }}

@@ -49,8 +54,13 @@

Comments

{% for comment in comments %} + {% if comment.author.display_name %} + {% set commentAuthorName = comment.author.display_name %} + {% else %} + {% set commentAuthorName = comment.author.username %} + {% endif %}
- {{ comment.author.display_name }} + {{ name }}
{{ comment.content | safe }}
Respond
From 4b0114917d603c7ed204aeabcb2967106351be37 Mon Sep 17 00:00:00 2001 From: Stephen Burgess Date: Mon, 11 Jun 2018 18:31:44 -0500 Subject: [PATCH 02/39] chore(Posts): Fix typo --- templates/posts/details.html.tera | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/posts/details.html.tera b/templates/posts/details.html.tera index e126f22..1935da0 100644 --- a/templates/posts/details.html.tera +++ b/templates/posts/details.html.tera @@ -15,7 +15,7 @@ {% set name = author.username %} {% endif %}

- Written by {{name }} + Written by {{ name }}{{ date | date(format="%B %e, %Y") }}

From df0fcb886d19a756986ddd97bc9810d1317e1ed1 Mon Sep 17 00:00:00 2001 From: Stephen Burgess Date: Tue, 12 Jun 2018 07:17:02 -0500 Subject: [PATCH 03/39] feat(UI): Fallback to username where ever display name is shown --- templates/macros.html.tera | 7 ++++++- templates/posts/details.html.tera | 6 +++--- templates/users/details.html.tera | 8 ++++++-- templates/users/followers.html.tera | 17 ++++++++++++++--- 4 files changed, 29 insertions(+), 9 deletions(-) diff --git a/templates/macros.html.tera b/templates/macros.html.tera index 4943265..900f96c 100644 --- a/templates/macros.html.tera +++ b/templates/macros.html.tera @@ -1,7 +1,12 @@ {% macro post_card(article) %} +{% if article.author.display_name %} + {% set name = article.author.display_name %} +{% else %} + {% set name = article.author.username %} +{% endif %}

{{ article.post.title }}

{{ article.post.content | striptags | truncate(length=200) }}

-

By {{ article.author.display_name }} ⋅ {{ article.date | date(format="%B %e") }}

+

By {{ name }} ⋅ {{ article.date | date(format="%B %e") }}

{% endmacro post_card %} diff --git a/templates/posts/details.html.tera b/templates/posts/details.html.tera index 1935da0..13e3e5a 100644 --- a/templates/posts/details.html.tera +++ b/templates/posts/details.html.tera @@ -55,12 +55,12 @@
{% for comment in comments %} {% if comment.author.display_name %} - {% set commentAuthorName = comment.author.display_name %} + {% set comment_author_name = comment.author.display_name %} {% else %} - {% set commentAuthorName = comment.author.username %} + {% set comment_author_name = comment.author.username %} {% endif %}
- {{ name }} + {{ comment_author_name }}
{{ comment.content | safe }}
Respond
diff --git a/templates/users/details.html.tera b/templates/users/details.html.tera index d225a30..1eb6325 100644 --- a/templates/users/details.html.tera +++ b/templates/users/details.html.tera @@ -2,13 +2,17 @@ {% import "macros" as macros %} {% block title %} -{{ user.display_name }} +{% if author.display_name %} + {% set name = author.display_name %} +{% else %} + {% set name = user.username %} +{% endif %} {% endblock title %} {% block content %}

- {{ user.display_name }} + {{ name }} {% if user.is_admin %} Admin {% endif %} diff --git a/templates/users/followers.html.tera b/templates/users/followers.html.tera index 5d6a956..9b0bdf2 100644 --- a/templates/users/followers.html.tera +++ b/templates/users/followers.html.tera @@ -1,13 +1,19 @@ {% extends "base" %} {% block title %} -{{ user.display_name }}'s Followers +{% if user.display_name %} + {% set name = user.display_name %} +{% else %} + {% set name = user.username %} +{% endif %} + +{{ name }}'s Followers {% endblock title %} {% block content %}

- {{ user.display_name }} + {{ name }} {% if user.is_admin %} Admin {% endif %} @@ -21,8 +27,13 @@

Followers

{% for follower in followers %} + {% if follower.display_name %} + {% set follower_name = follower.display_name %} + {% else %} + {% set follower_name = follower.username %} + {% endif %}
-

{{ follower.display_name }} — @{{ follower.fqn }}

+

{{ follower_name }} — @{{ follower.fqn }}

{{ follower.summary | safe }}

{% endfor %} From 23bb405c92d98a6b0c3966090f865376a2ce27dc Mon Sep 17 00:00:00 2001 From: Stephen Burgess Date: Tue, 12 Jun 2018 07:42:34 -0500 Subject: [PATCH 04/39] fix(User/Details): Use user variable --- templates/users/details.html.tera | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/users/details.html.tera b/templates/users/details.html.tera index 1eb6325..6e091c3 100644 --- a/templates/users/details.html.tera +++ b/templates/users/details.html.tera @@ -2,8 +2,8 @@ {% import "macros" as macros %} {% block title %} -{% if author.display_name %} - {% set name = author.display_name %} +{% if user.display_name %} + {% set name = user.display_name %} {% else %} {% set name = user.username %} {% endif %} From d32c7e4b66ea85032155ea9d7722ddb8a89adca9 Mon Sep 17 00:00:00 2001 From: Stephen Burgess Date: Tue, 12 Jun 2018 07:45:53 -0500 Subject: [PATCH 05/39] fix(User/Details): Display name --- templates/users/details.html.tera | 1 + 1 file changed, 1 insertion(+) diff --git a/templates/users/details.html.tera b/templates/users/details.html.tera index 6e091c3..15d4404 100644 --- a/templates/users/details.html.tera +++ b/templates/users/details.html.tera @@ -7,6 +7,7 @@ {% else %} {% set name = user.username %} {% endif %} +{{ name }} {% endblock title %} {% block content %} From 438778db398c5b0700683ea25ba52928afac05f4 Mon Sep 17 00:00:00 2001 From: Stephen Burgess Date: Tue, 12 Jun 2018 12:05:33 -0500 Subject: [PATCH 06/39] fix(Style): Adjust code style for consistency --- templates/macros.html.tera | 10 +++++----- templates/posts/details.html.tera | 3 ++- templates/users/details.html.tera | 3 ++- templates/users/followers.html.tera | 2 +- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/templates/macros.html.tera b/templates/macros.html.tera index 900f96c..3cce728 100644 --- a/templates/macros.html.tera +++ b/templates/macros.html.tera @@ -1,9 +1,9 @@ {% macro post_card(article) %} -{% if article.author.display_name %} - {% set name = article.author.display_name %} -{% else %} - {% set name = article.author.username %} -{% endif %} + {% if article.author.display_name %} + {% set name = article.author.display_name %} + {% else %} + {% set name = article.author.username %} + {% endif %}

{{ article.post.title }}

{{ article.post.content | striptags | truncate(length=200) }}

diff --git a/templates/posts/details.html.tera b/templates/posts/details.html.tera index 13e3e5a..52e71b3 100644 --- a/templates/posts/details.html.tera +++ b/templates/posts/details.html.tera @@ -8,12 +8,13 @@ {{ blog.title }} {% endblock header %} -{% block content %} {% if author.display_name %} {% set name = author.display_name %} {% else %} {% set name = author.username %} {% endif %} + +{% block content %}

Written by {{ name }} — diff --git a/templates/users/details.html.tera b/templates/users/details.html.tera index 15d4404..51d6f94 100644 --- a/templates/users/details.html.tera +++ b/templates/users/details.html.tera @@ -1,12 +1,13 @@ {% extends "base" %} {% import "macros" as macros %} -{% block title %} {% if user.display_name %} {% set name = user.display_name %} {% else %} {% set name = user.username %} {% endif %} + +{% block title %} {{ name }} {% endblock title %} diff --git a/templates/users/followers.html.tera b/templates/users/followers.html.tera index 9b0bdf2..595f6ae 100644 --- a/templates/users/followers.html.tera +++ b/templates/users/followers.html.tera @@ -1,12 +1,12 @@ {% extends "base" %} -{% block title %} {% if user.display_name %} {% set name = user.display_name %} {% else %} {% set name = user.username %} {% endif %} +{% block title %} {{ name }}'s Followers {% endblock title %} From 36c11182f4cffa21be113179e2ab3516420355c1 Mon Sep 17 00:00:00 2001 From: Bat Date: Tue, 12 Jun 2018 20:10:08 +0100 Subject: [PATCH 07/39] Introduce some traits for handling incoming activities --- src/activity_pub/inbox.rs | 151 ++++++++++++-------------------------- src/activity_pub/mod.rs | 6 ++ src/models/comments.rs | 21 +++++- src/models/follows.rs | 36 +++++++++ src/models/likes.rs | 25 +++++++ src/models/posts.rs | 15 ++++ src/models/reshares.rs | 24 ++++-- 7 files changed, 168 insertions(+), 110 deletions(-) diff --git a/src/activity_pub/inbox.rs b/src/activity_pub/inbox.rs index 789ab13..cbd67f3 100644 --- a/src/activity_pub/inbox.rs +++ b/src/activity_pub/inbox.rs @@ -1,27 +1,21 @@ use activitypub::{ - Actor, - activity::{Accept, Announce, Create, Follow, Like, Undo}, - object::{Article, Note} + Activity, Object, + activity::{Create, Like, Undo} }; use diesel::PgConnection; use failure::Error; use serde_json; use activity_pub::{ - broadcast, Id, IntoId, - actor::Actor as APActor, - sign::* + Id }; use models::{ - blogs::Blog, comments::*, - follows, + follows::Follow, likes, posts::*, - reshares::*, - users::User + reshares::* }; -use safe_string::SafeString; #[derive(Fail, Debug)] enum InboxError { @@ -33,98 +27,69 @@ enum InboxError { CantUndo } +pub trait FromActivity: Sized { + fn from_activity(conn: &PgConnection, obj: T, actor: Id) -> Self; + + fn try_from_activity(conn: &PgConnection, act: Create) -> bool { + if let Ok(obj) = act.create_props.object_object() { + Self::from_activity(conn, obj, act.create_props.actor_link::().unwrap()); + true + } else { + false + } + } +} + +pub trait Notify { + fn notify(conn: &PgConnection, act: T, actor: Id); +} + +pub trait Deletable { + /// true if success + fn delete_activity(conn: &PgConnection, id: Id) -> bool; +} + pub trait Inbox { fn received(&self, conn: &PgConnection, act: serde_json::Value); - fn new_article(&self, conn: &PgConnection, article: Article) -> Result<(), Error> { - Post::insert(conn, NewPost { - blog_id: 0, // TODO - slug: String::from(""), // TODO - title: article.object_props.name_string().unwrap(), - content: SafeString::new(&article.object_props.content_string().unwrap()), - published: true, - license: String::from("CC-0"), - ap_url: article.object_props.url_string()? - }); - Ok(()) - } - - fn new_comment(&self, conn: &PgConnection, note: Note, actor_id: String) -> Result<(), Error> { - let previous_url = note.object_props.in_reply_to.clone().unwrap().as_str().unwrap().to_string(); - let previous_comment = Comment::find_by_ap_url(conn, previous_url.clone()); - Comment::insert(conn, NewComment { - content: SafeString::new(¬e.object_props.content_string().unwrap()), - spoiler_text: note.object_props.summary_string().unwrap_or(String::from("")), - ap_url: note.object_props.id_string().ok(), - in_response_to_id: previous_comment.clone().map(|c| c.id), - post_id: previous_comment - .map(|c| c.post_id) - .unwrap_or_else(|| Post::find_by_ap_url(conn, previous_url).unwrap().id), - author_id: User::from_url(conn, actor_id).unwrap().id, - sensitive: false // "sensitive" is not a standard property, we need to think about how to support it with the activitystreams crate - }); - Ok(()) - } - - fn follow(&self, conn: &PgConnection, follow: Follow) -> Result<(), Error> { - let from = User::from_url(conn, follow.follow_props.actor.as_str().unwrap().to_string()).unwrap(); - match User::from_url(conn, follow.follow_props.object.as_str().unwrap().to_string()) { - Some(u) => self.accept_follow(conn, &from, &u, follow, from.id, u.id), - None => { - let blog = Blog::from_url(conn, follow.follow_props.object.as_str().unwrap().to_string()).unwrap(); - self.accept_follow(conn, &from, &blog, follow, from.id, blog.id) - } - }; - Ok(()) - } - - fn like(&self, conn: &PgConnection, like: Like) -> Result<(), Error> { - let liker = User::from_url(conn, like.like_props.actor.as_str().unwrap().to_string()); - let post = Post::find_by_ap_url(conn, like.like_props.object.as_str().unwrap().to_string()); - likes::Like::insert(conn, likes::NewLike { - post_id: post.unwrap().id, - user_id: liker.unwrap().id, - ap_url: like.object_props.id_string()? - }); - Ok(()) - } - fn unlike(&self, conn: &PgConnection, undo: Undo) -> Result<(), Error> { let like = likes::Like::find_by_ap_url(conn, undo.undo_props.object_object::()?.object_props.id_string()?).unwrap(); like.delete(conn); Ok(()) } - fn announce(&self, conn: &PgConnection, announce: Announce) -> Result<(), Error> { - let user = User::from_url(conn, announce.announce_props.actor.as_str().unwrap().to_string()); - let post = Post::find_by_ap_url(conn, announce.announce_props.object.as_str().unwrap().to_string()); - Reshare::insert(conn, NewReshare { - post_id: post.unwrap().id, - user_id: user.unwrap().id, - ap_url: announce.object_props.id_string()? - }); - Ok(()) - } - fn save(&self, conn: &PgConnection, act: serde_json::Value) -> Result<(), Error> { + let actor_id = Id::new(act["actor"].as_str().unwrap()); match act["type"].as_str() { Some(t) => { match t { - "Announce" => self.announce(conn, serde_json::from_value(act.clone())?), + "Announce" => { + Reshare::from_activity(conn, serde_json::from_value(act.clone())?, actor_id); + Ok(()) + }, "Create" => { let act: Create = serde_json::from_value(act.clone())?; - match act.create_props.object["type"].as_str().unwrap() { - "Article" => self.new_article(conn, act.create_props.object_object()?), - "Note" => self.new_comment(conn, act.create_props.object_object()?, act.create_props.actor_link::()?.0), - _ => Err(InboxError::InvalidType)? + if Post::try_from_activity(conn, act.clone()) || Comment::try_from_activity(conn, act) { + Ok(()) + } else { + Err(InboxError::InvalidType)? } }, - "Follow" => self.follow(conn, serde_json::from_value(act.clone())?), - "Like" => self.like(conn, serde_json::from_value(act.clone())?), + "Follow" => { + Follow::from_activity(conn, serde_json::from_value(act.clone())?, actor_id); + Ok(()) + }, + "Like" => { + likes::Like::from_activity(conn, serde_json::from_value(act.clone())?, actor_id); + Ok(()) + }, "Undo" => { let act: Undo = serde_json::from_value(act.clone())?; match act.undo_props.object["type"].as_str().unwrap() { - "Like" => self.unlike(conn, act), + "Like" => { + likes::Like::delete_activity(conn, Id::new(act.undo_props.object_object::()?.object_props.id_string()?)); + Ok(()) + }, _ => Err(InboxError::CantUndo)? } } @@ -134,26 +99,6 @@ pub trait Inbox { None => Err(InboxError::NoType)? } } - - fn accept_follow( - &self, - conn: &PgConnection, - from: &A, - target: &B, - follow: Follow, - from_id: i32, - target_id: i32 - ) { - follows::Follow::insert(conn, follows::NewFollow { - follower_id: from_id, - following_id: target_id - }); - - let mut accept = Accept::default(); - accept.accept_props.set_actor_link::(from.clone().into_id()).unwrap(); - accept.accept_props.set_object_object(follow).unwrap(); - broadcast(conn, &*from, accept, vec![target.clone()]); - } } pub trait WithInbox { diff --git a/src/activity_pub/mod.rs b/src/activity_pub/mod.rs index febd959..fc49c75 100644 --- a/src/activity_pub/mod.rs +++ b/src/activity_pub/mod.rs @@ -111,6 +111,12 @@ impl Id { } } +impl Into for Id { + fn into(self) -> String { + self.0.clone() + } +} + pub trait IntoId { fn into_id(self) -> Id; } diff --git a/src/models/comments.rs b/src/models/comments.rs index e763e90..be66f87 100644 --- a/src/models/comments.rs +++ b/src/models/comments.rs @@ -7,8 +7,9 @@ use diesel::{self, PgConnection, RunQueryDsl, QueryDsl, ExpressionMethods, dsl:: use serde_json; use activity_pub::{ - ap_url, IntoId, PUBLIC_VISIBILTY, + ap_url, Id, IntoId, PUBLIC_VISIBILTY, actor::Actor, + inbox::FromActivity, object::Object }; use models::{ @@ -123,6 +124,24 @@ impl Comment { } } +impl FromActivity for Comment { + fn from_activity(conn: &PgConnection, note: Note, actor: Id) -> Comment { + let previous_url = note.object_props.in_reply_to.clone().unwrap().as_str().unwrap().to_string(); + let previous_comment = Comment::find_by_ap_url(conn, previous_url.clone()); + Comment::insert(conn, NewComment { + content: SafeString::new(¬e.object_props.content_string().unwrap()), + spoiler_text: note.object_props.summary_string().unwrap_or(String::from("")), + ap_url: note.object_props.id_string().ok(), + in_response_to_id: previous_comment.clone().map(|c| c.id), + post_id: previous_comment + .map(|c| c.post_id) + .unwrap_or_else(|| Post::find_by_ap_url(conn, previous_url).unwrap().id), + author_id: User::from_url(conn, actor.into()).unwrap().id, + sensitive: false // "sensitive" is not a standard property, we need to think about how to support it with the activitypub crate + }) + } +} + impl Object for Comment { fn serialize(&self, conn: &PgConnection) -> serde_json::Value { let mut to = self.get_author(conn).get_followers(conn).into_iter().map(|f| f.ap_url).collect::>(); diff --git a/src/models/follows.rs b/src/models/follows.rs index 6debe46..fa5f66f 100644 --- a/src/models/follows.rs +++ b/src/models/follows.rs @@ -1,5 +1,8 @@ +use activitypub::{Actor, activity::{Accept, Follow as FollowAct}}; use diesel::{self, PgConnection, ExpressionMethods, QueryDsl, RunQueryDsl}; +use activity_pub::{broadcast, Id, IntoId, actor::Actor as ApActor, inbox::{FromActivity, WithInbox}, sign::Signer}; +use models::blogs::Blog; use models::users::User; use schema::follows; @@ -33,4 +36,37 @@ impl Follow { .expect("Unable to load follow by id") .into_iter().nth(0) } + + pub fn accept_follow( + conn: &PgConnection, + from: &A, + target: &B, + follow: FollowAct, + from_id: i32, + target_id: i32 + ) -> Follow { + let res = Follow::insert(conn, NewFollow { + follower_id: from_id, + following_id: target_id + }); + + let mut accept = Accept::default(); + accept.accept_props.set_actor_link::(from.clone().into_id()).unwrap(); + accept.accept_props.set_object_object(follow).unwrap(); + broadcast(conn, &*from, accept, vec![target.clone()]); + res + } +} + +impl FromActivity for Follow { + fn from_activity(conn: &PgConnection, follow: FollowAct, _actor: Id) -> Follow { + let from = User::from_url(conn, follow.follow_props.actor.as_str().unwrap().to_string()).unwrap(); + match User::from_url(conn, follow.follow_props.object.as_str().unwrap().to_string()) { + Some(u) => Follow::accept_follow(conn, &from, &u, follow, from.id, u.id), + None => { + let blog = Blog::from_url(conn, follow.follow_props.object.as_str().unwrap().to_string()).unwrap(); + Follow::accept_follow(conn, &from, &blog, follow, from.id, blog.id) + } + } + } } diff --git a/src/models/likes.rs b/src/models/likes.rs index 65b24ff..59bd48b 100644 --- a/src/models/likes.rs +++ b/src/models/likes.rs @@ -4,8 +4,10 @@ use diesel::{self, PgConnection, QueryDsl, RunQueryDsl, ExpressionMethods}; use serde_json; use activity_pub::{ + Id, IntoId, actor::Actor, + inbox::{FromActivity, Deletable}, object::Object }; use models::{ @@ -94,6 +96,29 @@ impl Like { } } +impl FromActivity for Like { + fn from_activity(conn: &PgConnection, like: activity::Like, _actor: Id) -> Like { + let liker = User::from_url(conn, like.like_props.actor.as_str().unwrap().to_string()); + let post = Post::find_by_ap_url(conn, like.like_props.object.as_str().unwrap().to_string()); + Like::insert(conn, NewLike { + post_id: post.unwrap().id, + user_id: liker.unwrap().id, + ap_url: like.object_props.id_string().unwrap_or(String::from("")) + }) + } +} + +impl Deletable for Like { + fn delete_activity(conn: &PgConnection, id: Id) -> bool { + if let Some(like) = Like::find_by_ap_url(conn, id.into()) { + like.delete(conn); + true + } else { + false + } + } +} + impl Object for Like { fn serialize(&self, conn: &PgConnection) -> serde_json::Value { json!({ diff --git a/src/models/posts.rs b/src/models/posts.rs index be2ce42..6e3f489 100644 --- a/src/models/posts.rs +++ b/src/models/posts.rs @@ -10,6 +10,7 @@ use BASE_URL; use activity_pub::{ PUBLIC_VISIBILTY, ap_url, Id, IntoId, actor::Actor, + inbox::FromActivity, object::Object }; use models::{ @@ -195,6 +196,20 @@ impl Post { } } +impl FromActivity

for Post { + fn from_activity(conn: &PgConnection, article: Article, _actor: Id) -> Post { + Post::insert(conn, NewPost { + blog_id: 0, // TODO + slug: String::from(""), // TODO + title: article.object_props.name_string().unwrap(), + content: SafeString::new(&article.object_props.content_string().unwrap()), + published: true, + license: String::from("CC-0"), + ap_url: article.object_props.url_string().unwrap_or(String::from("")) + }) + } +} + impl IntoId for Post { fn into_id(self) -> Id { Id::new(self.ap_url.clone()) diff --git a/src/models/reshares.rs b/src/models/reshares.rs index 65c4739..2e2896d 100644 --- a/src/models/reshares.rs +++ b/src/models/reshares.rs @@ -1,8 +1,8 @@ -use activitypub::activity; +use activitypub::activity::{Announce, Undo}; use chrono::NaiveDateTime; use diesel::{self, PgConnection, QueryDsl, RunQueryDsl, ExpressionMethods}; -use activity_pub::{IntoId, actor::Actor, object::Object}; +use activity_pub::{Id, IntoId, actor::Actor, inbox::FromActivity, object::Object}; use models::{posts::Post, users::User}; use schema::reshares; @@ -80,17 +80,17 @@ impl Reshare { Post::get(conn, self.post_id) } - pub fn delete(&self, conn: &PgConnection) -> activity::Undo { + pub fn delete(&self, conn: &PgConnection) -> Undo { diesel::delete(self).execute(conn).unwrap(); - let mut act = activity::Undo::default(); + let mut act = Undo::default(); act.undo_props.set_actor_link(User::get(conn, self.user_id).unwrap().into_id()).unwrap(); act.undo_props.set_object_object(self.into_activity(conn)).unwrap(); act } - pub fn into_activity(&self, conn: &PgConnection) -> activity::Announce { - let mut act = activity::Announce::default(); + pub fn into_activity(&self, conn: &PgConnection) -> Announce { + let mut act = Announce::default(); act.announce_props.set_actor_link(User::get(conn, self.user_id).unwrap().into_id()).unwrap(); act.announce_props.set_object_link(Post::get(conn, self.post_id).unwrap().into_id()).unwrap(); act.object_props.set_id_string(self.ap_url.clone()).unwrap(); @@ -98,3 +98,15 @@ impl Reshare { act } } + +impl FromActivity for Reshare { + fn from_activity(conn: &PgConnection, announce: Announce, _actor: Id) -> Reshare { + let user = User::from_url(conn, announce.announce_props.actor.as_str().unwrap().to_string()); + let post = Post::find_by_ap_url(conn, announce.announce_props.object.as_str().unwrap().to_string()); + Reshare::insert(conn, NewReshare { + post_id: post.unwrap().id, + user_id: user.unwrap().id, + ap_url: announce.object_props.id_string().unwrap_or(String::from("")) + }) + } +} From 4185ba230e1fb4b5a8a3c2a43e8ecc7eaf879c00 Mon Sep 17 00:00:00 2001 From: Bat Date: Tue, 12 Jun 2018 21:14:49 +0100 Subject: [PATCH 08/39] Add a link to user profile in comments And move back {% if %} inside of {% block %}, so they get interpreted. --- src/routes/posts.rs | 7 ++++++- templates/posts/details.html.tera | 14 +++++++------- templates/users/details.html.tera | 4 ++-- templates/users/followers.html.tera | 2 +- 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/routes/posts.rs b/src/routes/posts.rs index 893670e..07d4b55 100644 --- a/src/routes/posts.rs +++ b/src/routes/posts.rs @@ -36,7 +36,12 @@ fn details(blog: String, slug: String, conn: DbConn, user: Option) -> Temp json!({ "id": c.id, "content": c.content, - "author": c.get_author(&*conn) + "author": ({ + let author = &c.get_author(&*conn); + let mut json = serde_json::to_value(author).unwrap(); + json["fqn"] = serde_json::Value::String(author.get_fqn(&*conn)); + json + }) }) }).collect::>(), "n_likes": post.get_likes(&*conn).len(), diff --git a/templates/posts/details.html.tera b/templates/posts/details.html.tera index 52e71b3..8b4043c 100644 --- a/templates/posts/details.html.tera +++ b/templates/posts/details.html.tera @@ -8,13 +8,13 @@ {{ blog.title }} {% endblock header %} -{% if author.display_name %} - {% set name = author.display_name %} -{% else %} - {% set name = author.username %} -{% endif %} - {% block content %} + {% if author.display_name %} + {% set name = author.display_name %} + {% else %} + {% set name = author.username %} + {% endif %} +

Written by {{ name }} — @@ -61,7 +61,7 @@ {% set comment_author_name = comment.author.username %} {% endif %}

- {{ comment_author_name }} + {{ comment_author_name }}
{{ comment.content | safe }}
Respond
diff --git a/templates/users/details.html.tera b/templates/users/details.html.tera index 51d6f94..df9c915 100644 --- a/templates/users/details.html.tera +++ b/templates/users/details.html.tera @@ -1,13 +1,13 @@ {% extends "base" %} {% import "macros" as macros %} +{% block title %} {% if user.display_name %} {% set name = user.display_name %} {% else %} {% set name = user.username %} {% endif %} -{% block title %} {{ name }} {% endblock title %} @@ -30,7 +30,7 @@
diff --git a/templates/users/followers.html.tera b/templates/users/followers.html.tera index 595f6ae..9b0bdf2 100644 --- a/templates/users/followers.html.tera +++ b/templates/users/followers.html.tera @@ -1,12 +1,12 @@ {% extends "base" %} +{% block title %} {% if user.display_name %} {% set name = user.display_name %} {% else %} {% set name = user.username %} {% endif %} -{% block title %} {{ name }}'s Followers {% endblock title %} From 1f15a10b9d3468109f30b1cc1da446c6aefecd20 Mon Sep 17 00:00:00 2001 From: Stephen Burgess Date: Tue, 12 Jun 2018 23:01:29 -0500 Subject: [PATCH 09/39] feat(Docs): Development guide --- DEVELOPMENT.md | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 DEVELOPMENT.md diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md new file mode 100644 index 0000000..f9bb02b --- /dev/null +++ b/DEVELOPMENT.md @@ -0,0 +1,70 @@ +# Development Guide +## Running Plume locally +### Mac OSX +All commands are run in the Mac Terminal or terminal emulator of your choice, such as iTerm2. First, you will need [Git](https://git-scm.com/download/mac), [Homebrew](https://brew.sh/), [Rust](https://www.rust-lang.org/en-US/), and [Postgres](https://www.postgresql.org/). Follow the instructions to install Homebrew before continuing if you don't already have it. +#### Download the Repository +Navigate to the directory on your machine where you would like to install the repository, such as in `~/dev` by running `cd dev`. Now, clone the remote repository by running `git clone https://github.com/Plume-org/Plume.git`. This will install the codebase to the `Plume` subdirectory. Navigate into that directory by running `cd Plume`. +#### Rust +If you think you might already have rust on your machine, you can check by running +``` +rustc --version +# Should output something like +# rustc 1.28.0-nightly (a805a2a5e 2018-06-10) +``` +If you don't already have Rust, install it by running +``` +curl https://sh.rustup.rs -sSf | sh +``` +In the interactive installation, choose the option of the nightly toolchain. Restart your console so that the `rustc` CLI tool is available. +#### Postgres +Now we will use Homebrew to install Postgres. If you think you might already have it, try running `brew info postgres`. If it is not available, continue to install Postgres by running the following: +``` +brew install postgres +``` +Now, you can use the following command to start Postgres on a one-time basis. +``` +pg_ctl -D /usr/local/var/postgres start +``` +After starting Postgres, we need to enter [PSQL](http://postgresguide.com/utilities/psql.html), the interactive terminal for running postgres queries. We'll be running this as the user `postgres` which is an admin-type postgres user. +``` +psql postgres +``` +Now that you are in psql, enter the following queries to prepare the database for Plume. +``` +CREATE DATABASE plume; +CREATE USER plume WITH PASSWORD 'plume'; +GRANT ALL PRIVILEGES ON DATABASE plume to plume; +\q +``` +The final command `\q` lets us exit psql and returns us to the Terminal. Now, we will open psql again, this time as the `plume` user we just created. Then we'll give all privileges on all tables and sequences to our `plume` user. This is for local development use only and it's not recommend to give complete access to this user in a production environment. +``` +psql plume +GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO plume; +GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO plume; +\q +``` +#### Database Migration +Now that the Postgres database is set up and the `plume` user has the privileges it needs, we can set up the database using the diesel CLI. If this was your time installing Rust, you will probably need to run that using `cargo`. `cargo` is installed with `rustc` so if you followed the earlier instructions it will already be available. +``` +cargo install diesel_cli +``` +The first time you run this, you can run setup. After that, every time you pull the repository you will want to run the migration command in case there were any migrations. Those commands are +``` +diesel setup --database-url='postgres://localhost/plume' +diesel migration run --database-url='postgres://localhost/plume' +``` +#### Configuration +Now Plume should be running on your machine at [http://localhost:8000](http://localhost:8000). The first time you run the application, you'll want to configure your blog name on the [http://localhost:8000/configuration](http://localhost:8000/configuration) page. You'll be able to change this name later. + +#### Running Plume +To run Plume locally, make sure you are once again in the Plume directory, such as `~/dev/Plume`. Now you will be able to run the application using the command +``` +cargo run +``` +#### Making a Pull Request +To create an upstream fork of the repository in GitHub, click "Fork" in the top right button on the main page of the [Plume repository](https://github.com/Plume-org/Plume). Now, in the command line, set another remote for the repository by running the following command, replacing `myname` with the name under which you forked the repo. You can use another name besides `upstream` if you prefer +``` +git remote add upstream https://github.com/myname/Plume.git +``` +Now, make any changes to the code you want. After committing your changes, push to the upstream fork. Once your changes are made, visit the GitHub page for your fork and select "Make Pull Request". Add descriptive text, any issue numbers using hashtags to reference the issue number, screenshots of your changes if relevant, a description of how you tested your changes, and any other information that will help the project maintainers be able to quickly accept your pull requests. +The project maintainers may suggestion further changes to improve the pull request even more. After implementing this locally, you can push to your upstream fork again and the changes will immediately show up in the pull request after pushing. Once all the suggested changes are made, the pull request may be accepted. Thanks for contributing. \ No newline at end of file From 4cfa0060eaba67b8a5a2d1312493dd30bae67049 Mon Sep 17 00:00:00 2001 From: Stephen Burgess Date: Wed, 13 Jun 2018 07:44:04 -0500 Subject: [PATCH 10/39] feat(Docs): Development docs --- DEVELOPMENT.md | 33 +++++++++++++++++++++------ README.md | 61 +------------------------------------------------- 2 files changed, 27 insertions(+), 67 deletions(-) diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index f9bb02b..171d1e7 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -53,18 +53,37 @@ The first time you run this, you can run setup. After that, every time you pull diesel setup --database-url='postgres://localhost/plume' diesel migration run --database-url='postgres://localhost/plume' ``` -#### Configuration -Now Plume should be running on your machine at [http://localhost:8000](http://localhost:8000). The first time you run the application, you'll want to configure your blog name on the [http://localhost:8000/configuration](http://localhost:8000/configuration) page. You'll be able to change this name later. - #### Running Plume To run Plume locally, make sure you are once again in the Plume directory, such as `~/dev/Plume`. Now you will be able to run the application using the command ``` cargo run ``` +#### Configuration +Now Plume should be running on your machine at [http://localhost:8000](http://localhost:8000). The first time you run the application, you'll want to configure your blog name on the [http://localhost:8000/configuration](http://localhost:8000/configuration) page. You'll be able to change this name later. +#### Testing the federation + +To test the federation, you'll need to setup another database (see "Setup the database"), +also owned by the "plume" user, but with a different name. Then, you'll need to run the +migrations for this database too. + +``` +diesel migration run --database-url postgres://plume:plume@localhost/my_other_plume_db +``` + +To run this other instance, you'll need to give two environment variables: + +- `ROCKET_PORT`, the port on which your app will run +- `DB_NAME`, the name of the database you just created + +``` +ROCKET_PORT=3033 DB_NAME=my_other_plume_db cargo run +``` #### Making a Pull Request -To create an upstream fork of the repository in GitHub, click "Fork" in the top right button on the main page of the [Plume repository](https://github.com/Plume-org/Plume). Now, in the command line, set another remote for the repository by running the following command, replacing `myname` with the name under which you forked the repo. You can use another name besides `upstream` if you prefer +To create an upstream fork of the repository in GitHub, click "Fork" in the top right button on the main page of the [Plume repository](https://github.com/Plume-org/Plume). Now, in the command line, set another remote for the repository by running the following command, replacing `myname` with the name under which you forked the repo. You can use another name besides `upstream` if you prefer. Using [SSH](https://help.github.com/articles/connecting-to-github-with-ssh/) is recommended. ``` -git remote add upstream https://github.com/myname/Plume.git +git remote add upstream git@github.com/myname/Plume.git +# Alt # git remote add upstream https://github.com/myname/Plume.git ``` -Now, make any changes to the code you want. After committing your changes, push to the upstream fork. Once your changes are made, visit the GitHub page for your fork and select "Make Pull Request". Add descriptive text, any issue numbers using hashtags to reference the issue number, screenshots of your changes if relevant, a description of how you tested your changes, and any other information that will help the project maintainers be able to quickly accept your pull requests. -The project maintainers may suggestion further changes to improve the pull request even more. After implementing this locally, you can push to your upstream fork again and the changes will immediately show up in the pull request after pushing. Once all the suggested changes are made, the pull request may be accepted. Thanks for contributing. \ No newline at end of file +Now, make any changes to the code you want. After committing your changes, push to the upstream fork. Once your changes are made, visit the GitHub page for your fork and select "New pull request". Add descriptive text, any issue numbers using hashtags to reference the issue number, screenshots of your changes if relevant, a description of how you tested your changes, and any other information that will help the project maintainers be able to quickly accept your pull requests. + +The project maintainers may suggest further changes to improve the pull request even more. After implementing this locally, you can push to your upstream fork again and the changes will immediately show up in the pull request after pushing. Once all the suggested changes are made, the pull request may be accepted. Thanks for contributing. diff --git a/README.md b/README.md index bec7304..4c55247 100644 --- a/README.md +++ b/README.md @@ -3,63 +3,4 @@ Federated blogging engine, based on ActivityPub. [**Demo instance**](https://baptiste.gelez.xyz/) - -## Setup the database - -You'll need Postgres. - -``` -sudo su postgres - -psql - -CREATE DATABASE plume; -CREATE USER plume WITH PASSWORD 'plume'; -GRANT ALL PRIVILEGES ON DATABASE plume to plume; -\q - -exit -``` - -Then run the migrations - -``` -diesel migrations run # Install diesel with `cargo install diesel_cli` if needed -``` - -You should repeat this operation every time the database schema has been modified. -A good practice is to run it after every `git pull`. - -## Starting the app - -Just use: - -``` -cargo run -``` - -You'll need Rust nightly. - -Once the app started, try to visit [localhost:8000](http://localhost:8000). - -To configure the instance (needed before you can do anything else), -go on [/configure](http://localhost:8000/configure). - -## Testing the federation - -To test the federation, you'll need to setup another database (see "Setup the database"), -also owned by the "plume" user, but with a different name. Then, you'll need to run the -migrations for this database too. - -``` -diesel migration run --database-url postgres://plume:plume@localhost/my_other_plume_db -``` - -To run this other instance, you'll need to give two environment variables: - -- `ROCKET_PORT`, the port on which your app will run -- `DB_NAME`, the name of the database you just created - -``` -ROCKET_PORT=3033 DB_NAME=my_other_plume_db cargo run -``` +[Development Guide](https://github.com/Plume-org/Plume/blob/master/DEVELOPMENT.md) From 54ec94da8ab1fa811ced10df761973c8fa88e5b6 Mon Sep 17 00:00:00 2001 From: Baptiste Gelez Date: Wed, 13 Jun 2018 13:58:26 +0100 Subject: [PATCH 11/39] Update README.md --- README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4c55247..e375e40 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,9 @@ # Plume [![Build Status](https://travis-ci.org/Plume-org/Plume.svg?branch=master)](https://travis-ci.org/Plume-org/Plume) -Federated blogging engine, based on ActivityPub. +Federated blogging engine, based on ActivityPub. It uses the Rocket framework, and Diesel to interact with the database. + +It is not yet ready for production use, but we have all the basic features (account management, blogs, articles, comments, etc) and a basic federation. [**Demo instance**](https://baptiste.gelez.xyz/) -[Development Guide](https://github.com/Plume-org/Plume/blob/master/DEVELOPMENT.md) + +If you are interested in coding, check out the [development guide](https://github.com/Plume-org/Plume/blob/master/DEVELOPMENT.md). You can also help by reporting issues, suggesting features, or writing documentation for instance. From 51c598a0fc4ebebb66c90cd61d375eccf3b940ee Mon Sep 17 00:00:00 2001 From: Baptiste Gelez Date: Wed, 13 Jun 2018 14:00:02 +0100 Subject: [PATCH 12/39] Add a link to the Matrix room --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e375e40..e135789 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,10 @@ Federated blogging engine, based on ActivityPub. It uses the Rocket framework, and Diesel to interact with the database. -It is not yet ready for production use, but we have all the basic features (account management, blogs, articles, comments, etc) and a basic federation. - [**Demo instance**](https://baptiste.gelez.xyz/) +It is not yet ready for production use, but we have all the basic features (account management, blogs, articles, comments, etc) and a basic federation. + +Feel free to join our Matrix room: `#plume:disroot.org` to discuss about the project! + If you are interested in coding, check out the [development guide](https://github.com/Plume-org/Plume/blob/master/DEVELOPMENT.md). You can also help by reporting issues, suggesting features, or writing documentation for instance. From 1c287c6dfe81cf6c2041ae2ce35cf2d4b2c674be Mon Sep 17 00:00:00 2001 From: Bat Date: Wed, 13 Jun 2018 18:48:37 +0100 Subject: [PATCH 13/39] View remote profiles locally Add a link to the profile on the real instance --- src/routes/user.rs | 6 +++++- templates/users/details.html.tera | 4 ++++ templates/users/followers.html.tera | 6 +++++- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/routes/user.rs b/src/routes/user.rs index 49023c6..7bb7b98 100644 --- a/src/routes/user.rs +++ b/src/routes/user.rs @@ -41,7 +41,9 @@ fn details(name: String, conn: DbConn, account: Option) -> Template { let n_followers = user.get_followers(&*conn).len(); Template::render("users/details", json!({ - "user": serde_json::to_value(user).unwrap(), + "user": serde_json::to_value(user.clone()).unwrap(), + "instance_url": user.get_instance(&*conn).public_domain, + "is_remote": user.instance_id != Instance::local_id(&*conn), "account": account, "recents": recents.into_iter().map(|p| { json!({ @@ -116,6 +118,8 @@ fn followers(name: String, conn: DbConn, account: Option) -> Template { Template::render("users/followers", json!({ "user": serde_json::to_value(user.clone()).unwrap(), + "instance_url": user.get_instance(&*conn).public_domain, + "is_remote": user.instance_id != Instance::local_id(&*conn), "followers": user.get_followers(&*conn).into_iter().map(|f| { let fqn = f.get_fqn(&*conn); let mut json = serde_json::to_value(f).unwrap(); diff --git a/templates/users/details.html.tera b/templates/users/details.html.tera index df9c915..6bc5c2c 100644 --- a/templates/users/details.html.tera +++ b/templates/users/details.html.tera @@ -27,6 +27,10 @@ {% if is_self %} Edit your profile {% endif %} + + {% if is_remote %} + Open on {{ instance_url }} + {% endif %}
diff --git a/templates/users/followers.html.tera b/templates/users/followers.html.tera index 9b0bdf2..e8af7cd 100644 --- a/templates/users/followers.html.tera +++ b/templates/users/followers.html.tera @@ -22,6 +22,10 @@ It is you {% endif %}

+ + {% if is_remote %} + Open on {{ instance_url }} + {% endif %}

Followers

@@ -33,7 +37,7 @@ {% set follower_name = follower.username %} {% endif %}
-

{{ follower_name }} — @{{ follower.fqn }}

+

{{ follower_name }} — @{{ follower.fqn }}

{{ follower.summary | safe }}

{% endfor %} From 7b61da9c7f0c1dac650c9224d27ad1a7b14b3471 Mon Sep 17 00:00:00 2001 From: Bat Date: Wed, 13 Jun 2018 18:52:26 +0100 Subject: [PATCH 14/39] Add a button to follow people --- templates/users/details.html.tera | 4 ++++ templates/users/followers.html.tera | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/templates/users/details.html.tera b/templates/users/details.html.tera index 6bc5c2c..0d86c41 100644 --- a/templates/users/details.html.tera +++ b/templates/users/details.html.tera @@ -31,6 +31,10 @@ {% if is_remote %} Open on {{ instance_url }} {% endif %} + + {% if not is_self %} + Follow + {% endif %}
diff --git a/templates/users/followers.html.tera b/templates/users/followers.html.tera index e8af7cd..802316f 100644 --- a/templates/users/followers.html.tera +++ b/templates/users/followers.html.tera @@ -26,6 +26,10 @@ {% if is_remote %} Open on {{ instance_url }} {% endif %} + + {% if not is_self %} + Follow + {% endif %}

Followers

From a4a8446d45e8df2151de71a01d64187b447c646c Mon Sep 17 00:00:00 2001 From: Bat Date: Wed, 13 Jun 2018 19:06:14 +0100 Subject: [PATCH 15/39] Make the follow button a bit smarter --- src/models/users.rs | 10 ++++++++++ src/routes/user.rs | 2 ++ templates/users/details.html.tera | 8 ++++++-- templates/users/followers.html.tera | 8 ++++++-- 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/models/users.rs b/src/models/users.rs index 8677154..0b10dfc 100644 --- a/src/models/users.rs +++ b/src/models/users.rs @@ -285,6 +285,16 @@ impl User { users::table.filter(users::id.eq(any(follows))).load::(conn).unwrap() } + pub fn is_following(&self, conn: &PgConnection, other_id: i32) -> bool { + use schema::follows; + follows::table + .filter(follows::follower_id.eq(other_id)) + .filter(follows::following_id.eq(self.id)) + .load::(conn) + .expect("Couldn't load follow relationship") + .len() > 0 + } + pub fn has_liked(&self, conn: &PgConnection, post: &Post) -> bool { use schema::likes; use models::likes::Like; diff --git a/src/routes/user.rs b/src/routes/user.rs index 7bb7b98..bb096c8 100644 --- a/src/routes/user.rs +++ b/src/routes/user.rs @@ -44,6 +44,7 @@ fn details(name: String, conn: DbConn, account: Option) -> Template { "user": serde_json::to_value(user.clone()).unwrap(), "instance_url": user.get_instance(&*conn).public_domain, "is_remote": user.instance_id != Instance::local_id(&*conn), + "follows": account.clone().map(|x| x.is_following(&*conn, user.id)).unwrap_or(false), "account": account, "recents": recents.into_iter().map(|p| { json!({ @@ -120,6 +121,7 @@ fn followers(name: String, conn: DbConn, account: Option) -> Template { "user": serde_json::to_value(user.clone()).unwrap(), "instance_url": user.get_instance(&*conn).public_domain, "is_remote": user.instance_id != Instance::local_id(&*conn), + "follows": account.clone().map(|x| x.is_following(&*conn, user.id)).unwrap_or(false), "followers": user.get_followers(&*conn).into_iter().map(|f| { let fqn = f.get_fqn(&*conn); let mut json = serde_json::to_value(f).unwrap(); diff --git a/templates/users/details.html.tera b/templates/users/details.html.tera index 0d86c41..a918474 100644 --- a/templates/users/details.html.tera +++ b/templates/users/details.html.tera @@ -32,8 +32,12 @@ Open on {{ instance_url }} {% endif %} - {% if not is_self %} - Follow + {% if not is_self and account %} + {% if follows %} + Follow + {% else %} + Unfollow + {% endif %} {% endif %}
diff --git a/templates/users/followers.html.tera b/templates/users/followers.html.tera index 802316f..827813c 100644 --- a/templates/users/followers.html.tera +++ b/templates/users/followers.html.tera @@ -27,8 +27,12 @@ Open on {{ instance_url }} {% endif %} - {% if not is_self %} - Follow + {% if not is_self and account %} + {% if follows %} + Follow + {% else %} + Unfollow + {% endif %} {% endif %} From 560f59fa45b012f6450bfb2fc233a0509c3d5009 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczak?= Date: Wed, 13 Jun 2018 20:11:26 +0200 Subject: [PATCH 16/39] Fix typo --- DEVELOPMENT.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index 171d1e7..b734db9 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -59,7 +59,7 @@ To run Plume locally, make sure you are once again in the Plume directory, such cargo run ``` #### Configuration -Now Plume should be running on your machine at [http://localhost:8000](http://localhost:8000). The first time you run the application, you'll want to configure your blog name on the [http://localhost:8000/configuration](http://localhost:8000/configuration) page. You'll be able to change this name later. +Now Plume should be running on your machine at [http://localhost:8000](http://localhost:8000). The first time you run the application, you'll want to configure your blog name on the [http://localhost:8000/configure](http://localhost:8000/configure) page. You'll be able to change this name later. #### Testing the federation To test the federation, you'll need to setup another database (see "Setup the database"), From c9b4c40fa191818b867882b32cbaf67beeeb80e6 Mon Sep 17 00:00:00 2001 From: Bat Date: Fri, 15 Jun 2018 14:08:38 +0100 Subject: [PATCH 17/39] Add the gettext-rs crate --- Cargo.lock | 32 ++++++++++++++++++++++++++++++++ Cargo.toml | 3 ++- src/main.rs | 1 + src/routes/user.rs | 2 +- 4 files changed, 36 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cb86b4e..a4a2a82 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -518,6 +518,23 @@ dependencies = [ "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "gettext-rs" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "gettext-sys 0.19.8 (registry+https://github.com/rust-lang/crates.io-index)", + "locale_config 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "gettext-sys" +version = "0.19.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "glob" version = "0.2.11" @@ -699,6 +716,17 @@ dependencies = [ "crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "locale_config" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "log" version = "0.3.9" @@ -1019,6 +1047,7 @@ dependencies = [ "dotenv 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "gettext-rs 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "heck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.11.25 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1992,6 +2021,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" "checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb" "checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d" +"checksum gettext-rs 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3b8c2412d5758f68a9eeba161f9ecb9a55f56bfdbf17857650b98f2b9b281a47" +"checksum gettext-sys 0.19.8 (registry+https://github.com/rust-lang/crates.io-index)" = "62c644c0b8b73706fb8c7420533fd30abf6f41c2703994bc6f0826fceb7fb3d6" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum heck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea04fa3ead4e05e51a7c806fc07271fdbde4e246a6c6d1efd52e72230b771b82" "checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" @@ -2013,6 +2044,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum lazycell 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a6f08839bc70ef4a3fe1d566d5350f519c5912ea86be0df1740a7d247c7fc0ef" "checksum libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)" = "6fd41f331ac7c5b8ac259b8bf82c75c0fb2e469bbf37d2becbba9a6a2221965b" "checksum libflate 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "1a429b86418868c7ea91ee50e9170683f47fd9d94f5375438ec86ec3adb74e8e" +"checksum locale_config 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "14fbee0e39bc2dd6a2427c4fdea66e9826cc1fd09b0a0b7550359f5f6efe1dab" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2" "checksum mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" diff --git a/Cargo.toml b/Cargo.toml index 819d8a4..c36984b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,7 @@ name = "plume" version = "0.1.0" [dependencies] activitypub = "0.1.1" +ammonia = "1.1.0" array_tool = "1.0" base64 = "0.9" bcrypt = "0.2" @@ -11,6 +12,7 @@ comrak = "0.2" dotenv = "*" failure = "0.1" failure_derive = "0.1" +gettext-rs = "0.4" heck = "0.3.0" hex = "0.3" hyper = "*" @@ -23,7 +25,6 @@ serde = "*" serde_derive = "1.0" serde_json = "1.0" url = "1.7" -ammonia = "1.1.0" [dependencies.chrono] features = ["serde"] diff --git a/src/main.rs b/src/main.rs index ce8f78d..55a49e0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,6 +10,7 @@ extern crate comrak; extern crate failure; #[macro_use] extern crate failure_derive; +extern crate gettextrs; extern crate heck; extern crate hex; #[macro_use] diff --git a/src/routes/user.rs b/src/routes/user.rs index bb096c8..8705b25 100644 --- a/src/routes/user.rs +++ b/src/routes/user.rs @@ -116,7 +116,7 @@ fn follow_auth(name: String) -> Flash { fn followers(name: String, conn: DbConn, account: Option) -> Template { let user = User::find_by_fqn(&*conn, name.clone()).unwrap(); let user_id = user.id.clone(); - + Template::render("users/followers", json!({ "user": serde_json::to_value(user.clone()).unwrap(), "instance_url": user.get_instance(&*conn).public_domain, From 327768d3fe412f8cb993bff36945727a5eca385e Mon Sep 17 00:00:00 2001 From: Bat Date: Fri, 15 Jun 2018 14:55:14 +0100 Subject: [PATCH 18/39] I18n fairing --- src/i18n.rs | 42 ++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 2 ++ 2 files changed, 44 insertions(+) create mode 100644 src/i18n.rs diff --git a/src/i18n.rs b/src/i18n.rs new file mode 100644 index 0000000..6a65559 --- /dev/null +++ b/src/i18n.rs @@ -0,0 +1,42 @@ +use gettextrs::*; +use rocket::{Data, Request, Rocket, fairing::{Fairing, Info, Kind}}; + +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 { + bindtextdomain(self.domain, "/usr/local/share/locale"); + 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"); + setlocale(LocaleCategory::LcAll, format!("{}.UTF-8", lang.replace("-", "_"))); + } +} diff --git a/src/main.rs b/src/main.rs index 55a49e0..57b316e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -39,6 +39,7 @@ use std::env; mod activity_pub; mod db_conn; +mod i18n; mod models; mod schema; mod routes; @@ -128,5 +129,6 @@ fn main() { ]) .manage(init_pool()) .attach(Template::fairing()) + .attach(i18n::I18n::new("plume")) .launch(); } From 978104b51831c5d24cf83a654b8096c187d30b1f Mon Sep 17 00:00:00 2001 From: Bat Date: Fri, 15 Jun 2018 17:23:32 +0100 Subject: [PATCH 19/39] Add a build script to update/create translation files --- build.rs | 45 +++++++++++++++++++++++++++++++++++++++++++++ po/LINGUAS | 2 ++ po/en.po | 16 ++++++++++++++++ po/fr.po | 16 ++++++++++++++++ po/plume.pot | 16 ++++++++++++++++ 5 files changed, 95 insertions(+) create mode 100644 build.rs create mode 100644 po/LINGUAS create mode 100644 po/en.po create mode 100644 po/fr.po create mode 100644 po/plume.pot diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..2599769 --- /dev/null +++ b/build.rs @@ -0,0 +1,45 @@ +use std::fs::File; +use std::io::{BufReader, prelude::*}; +use std::path::Path; +use std::process::Command; + +fn main() { + update_po(); + compile_po(); + install_po(); +} + +fn update_po() { + let pot_path = Path::new("po").join("plume.pot"); + + let linguas_file = File::open(Path::new("po").join("LINGUAS")).expect("Couldn't find po/LINGUAS file"); + let linguas = BufReader::new(&linguas_file); + for lang in linguas.lines() { + let lang = lang.unwrap(); + 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(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() {} + +fn install_po() {} diff --git a/po/LINGUAS b/po/LINGUAS new file mode 100644 index 0000000..7e6d9e4 --- /dev/null +++ b/po/LINGUAS @@ -0,0 +1,2 @@ +en +fr diff --git a/po/en.po b/po/en.po new file mode 100644 index 0000000..4ffaf0d --- /dev/null +++ b/po/en.po @@ -0,0 +1,16 @@ +msgid "" +msgstr "" +"Project-Id-Version: plume\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-06-15 16:33-0700\n" +"PO-Revision-Date: 2018-06-15 16:35+0100\n" +"Last-Translator: baptiste \n" +"Language-Team: English\n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Welcome on %s" +msgstr "Welcome on %s" diff --git a/po/fr.po b/po/fr.po new file mode 100644 index 0000000..dadf304 --- /dev/null +++ b/po/fr.po @@ -0,0 +1,16 @@ +msgid "" +msgstr "" +"Project-Id-Version: plume\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-06-15 16:33-0700\n" +"PO-Revision-Date: 2018-06-15 16:33-0700\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "Welcome on %s" +msgstr "" diff --git a/po/plume.pot b/po/plume.pot new file mode 100644 index 0000000..e536d0d --- /dev/null +++ b/po/plume.pot @@ -0,0 +1,16 @@ +msgid "" +msgstr "" +"Project-Id-Version: plume\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-06-15 16:33-0700\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" + +msgid "Welcome on %s" +msgstr "" From 7313f60d1472ea13a98c352fa246da227f13da85 Mon Sep 17 00:00:00 2001 From: Bat Date: Fri, 15 Jun 2018 18:43:24 +0100 Subject: [PATCH 20/39] Compile .po files Since cargo is usually not run as root, we can't install .mo files to the standard location (/usr/local/share/locale/), so we install them to ./translations and load them from there. --- build.rs | 31 ++++++++++++++++++++------- src/i18n.rs | 4 +++- translations/en/LC_MESSAGES/plume.mo | Bin 0 -> 459 bytes translations/fr/LC_MESSAGES/plume.mo | Bin 0 -> 394 bytes 4 files changed, 26 insertions(+), 9 deletions(-) create mode 100644 translations/en/LC_MESSAGES/plume.mo create mode 100644 translations/fr/LC_MESSAGES/plume.mo diff --git a/build.rs b/build.rs index 2599769..f85f7ce 100644 --- a/build.rs +++ b/build.rs @@ -1,4 +1,4 @@ -use std::fs::File; +use std::fs::{create_dir_all, File}; use std::io::{BufReader, prelude::*}; use std::path::Path; use std::process::Command; @@ -6,16 +6,12 @@ use std::process::Command; fn main() { update_po(); compile_po(); - install_po(); } fn update_po() { let pot_path = Path::new("po").join("plume.pot"); - let linguas_file = File::open(Path::new("po").join("LINGUAS")).expect("Couldn't find po/LINGUAS file"); - let linguas = BufReader::new(&linguas_file); - for lang in linguas.lines() { - let lang = lang.unwrap(); + 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()); @@ -40,6 +36,25 @@ fn update_po() { } } -fn compile_po() {} +fn compile_po() { + 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"); + create_dir_all(mo_dir.clone()).expect("Couldn't create MO directory"); + let mo_path = mo_dir.join("plume.mo"); -fn install_po() {} + 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 = 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() +} diff --git a/src/i18n.rs b/src/i18n.rs index 6a65559..96e73df 100644 --- a/src/i18n.rs +++ b/src/i18n.rs @@ -1,5 +1,7 @@ use gettextrs::*; use rocket::{Data, Request, Rocket, fairing::{Fairing, Info, Kind}}; +use std::fs; +use std::path::PathBuf; const ACCEPT_LANG: &'static str = "Accept-Language"; @@ -24,7 +26,7 @@ impl Fairing for I18n { } fn on_attach(&self, rocket: Rocket) -> Result { - bindtextdomain(self.domain, "/usr/local/share/locale"); + bindtextdomain(self.domain, fs::canonicalize(&PathBuf::from("./translations")).unwrap().to_str().unwrap()); textdomain(self.domain); Ok(rocket) } diff --git a/translations/en/LC_MESSAGES/plume.mo b/translations/en/LC_MESSAGES/plume.mo new file mode 100644 index 0000000000000000000000000000000000000000..27705383d0b74ed386957ce20f0a6a15851e3d46 GIT binary patch literal 459 zcmZvY!Ab)$5QbOL%Yqlr9^yezG#?FGvS|PG9SBJZystB*+Wi{ZKQ)#ijf`U4td(}yvcX|jxnyUI^5QJ1exj_ zh*splda=6xujCw3(REt1`1R(Tw=zQ%D7qVI-VM-#)9mE38=$dngOSO=u@6J2H? zVO3i!R~KkkS;;e?3Gkeep30=K^WS4eKuyN?{%|ntt$!5O0>7)31BFj53+&m!!kre9 z3)Lp+oEr-+8Yg|)TKlS&p25(bO7%>rjFHwSpgxBL)xGe3) zC;jAqpT0Za@9D|Uh;&4p5$D7)aYYQuh>{-fX&pR!mEL_~9bwhL8~UJ~6}&Tji)@3P z^AU=mbOTSl3Q#%0S@}}I+@p+Sg=ZO2@Ntr6kW3-H<>^#RCXn1E2^nF7UwVlA*SD4- zLgl3mMn>laf9#`cDZiG+?6^XUp2{?AEv@RMLa0!-f?H>Ce<%3Xvtm^&4!=mR6E=4? zqNVs8jyIi=+UC6ekUn6Xy;e)e4!)s{EqYkk+BMoL!LxTAS!sGN4J@5+168I0 V(J{=%`7kTm&Mqu};OS+~Mt}A6Z*Kqq literal 0 HcmV?d00001 From b18aa33c70ce3d02464f32be21ad21829b84a9cd Mon Sep 17 00:00:00 2001 From: Bat Date: Sat, 16 Jun 2018 18:39:22 +0100 Subject: [PATCH 21/39] Update to the latest version of Rocket, to use rocket_contrib::Template::custom --- Cargo.lock | 259 +++++++++++++++++++--------------------- Cargo.toml | 14 ++- rust-toolchain | 2 +- src/activity_pub/mod.rs | 2 +- src/i18n.rs | 11 ++ src/main.rs | 9 +- src/routes/blogs.rs | 2 +- src/routes/comments.rs | 2 +- src/routes/instance.rs | 2 +- src/routes/likes.rs | 2 +- src/routes/posts.rs | 2 +- src/routes/reshares.rs | 2 +- src/routes/session.rs | 8 +- src/routes/user.rs | 6 +- src/utils.rs | 7 +- 15 files changed, 168 insertions(+), 162 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a4a2a82..099e504 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -263,11 +263,11 @@ dependencies = [ [[package]] name = "cookie" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" +version = "0.11.0-dev" +source = "git+https://github.com/alexcrichton/cookie-rs?rev=0365a18#0365a18e4518e498ac6a508dab6b006add7f162e" dependencies = [ - "base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.13.0-alpha5 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -297,15 +297,6 @@ dependencies = [ "build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "crossbeam-deque" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "crossbeam-deque" version = "0.3.0" @@ -315,20 +306,6 @@ dependencies = [ "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "crossbeam-epoch" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "crossbeam-epoch" version = "0.4.1" @@ -420,14 +397,6 @@ name = "entities" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "error-chain" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "backtrace 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "error-chain" version = "0.11.0" @@ -505,11 +474,6 @@ dependencies = [ "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "gcc" -version = "0.3.54" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "generic-array" version = "0.9.0" @@ -642,6 +606,11 @@ dependencies = [ "unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "indexmap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "iovec" version = "0.1.2" @@ -773,14 +742,6 @@ name = "matches" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "memchr" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "memchr" version = "2.0.1" @@ -948,21 +909,22 @@ dependencies = [ "vcpkg 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "ordermap" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "pear" -version = "0.0.16" -source = "registry+https://github.com/rust-lang/crates.io-index" +version = "0.1.0" +source = "git+http://github.com/SergioBenitez/Pear?rev=54667ae#54667aefef084f2411e86392402a955770f1e7aa" +dependencies = [ + "pear_codegen 0.1.0 (git+http://github.com/SergioBenitez/Pear?rev=54667ae)", +] [[package]] name = "pear_codegen" -version = "0.0.16" -source = "registry+https://github.com/rust-lang/crates.io-index" +version = "0.1.0" +source = "git+http://github.com/SergioBenitez/Pear?rev=54667ae#54667aefef084f2411e86392402a955770f1e7aa" dependencies = [ + "proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.14.2 (registry+https://github.com/rust-lang/crates.io-index)", "version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "yansi 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -972,11 +934,6 @@ name = "percent-encoding" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "pest" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "pest" version = "1.0.6" @@ -1054,12 +1011,13 @@ dependencies = [ "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "openssl 0.10.6 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rocket 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rocket_codegen 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rocket_contrib 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "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)", "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)", + "tera 0.11.7 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1092,6 +1050,14 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "proc-macro2" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "quote" version = "0.3.15" @@ -1113,6 +1079,14 @@ dependencies = [ "proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "quote" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "r2d2" version = "0.8.2" @@ -1143,26 +1117,6 @@ dependencies = [ "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "rayon" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rayon-core 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rayon-core" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "redox_syscall" version = "0.1.37" @@ -1238,62 +1192,81 @@ dependencies = [ [[package]] name = "ring" -version = "0.11.0" +version = "0.13.0-alpha5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rocket" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" +version = "0.4.0-dev" +source = "git+https://github.com/SergioBenitez/Rocket?rev=df7111143e466c18d1f56377a8d9530a5a306aba#df7111143e466c18d1f56377a8d9530a5a306aba" dependencies = [ - "base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cookie 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", "isatty 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ordermap 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "pear 0.0.16 (registry+https://github.com/rust-lang/crates.io-index)", - "pear_codegen 0.0.16 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "state 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pear 0.1.0 (git+http://github.com/SergioBenitez/Pear?rev=54667ae)", + "rocket_codegen_next 0.4.0-dev (git+https://github.com/SergioBenitez/Rocket?rev=df7111143e466c18d1f56377a8d9530a5a306aba)", + "rocket_http 0.4.0-dev (git+https://github.com/SergioBenitez/Rocket?rev=df7111143e466c18d1f56377a8d9530a5a306aba)", + "state 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "yansi 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rocket_codegen" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" +version = "0.4.0-dev" +source = "git+https://github.com/SergioBenitez/Rocket?rev=df7111143e466c18d1f56377a8d9530a5a306aba#df7111143e466c18d1f56377a8d9530a5a306aba" dependencies = [ - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "rocket 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rocket_http 0.4.0-dev (git+https://github.com/SergioBenitez/Rocket?rev=df7111143e466c18d1f56377a8d9530a5a306aba)", "version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "yansi 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rocket_codegen_next" +version = "0.4.0-dev" +source = "git+https://github.com/SergioBenitez/Rocket?rev=df7111143e466c18d1f56377a8d9530a5a306aba#df7111143e466c18d1f56377a8d9530a5a306aba" +dependencies = [ + "proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.14.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rocket_contrib" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" +version = "0.4.0-dev" +source = "git+https://github.com/SergioBenitez/Rocket?rev=df7111143e466c18d1f56377a8d9530a5a306aba#df7111143e466c18d1f56377a8d9530a5a306aba" dependencies = [ "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "rocket 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rocket 0.4.0-dev (git+https://github.com/SergioBenitez/Rocket?rev=df7111143e466c18d1f56377a8d9530a5a306aba)", "serde 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", - "tera 0.10.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tera 0.11.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rocket_http" +version = "0.4.0-dev" +source = "git+https://github.com/SergioBenitez/Rocket?rev=df7111143e466c18d1f56377a8d9530a5a306aba#df7111143e466c18d1f56377a8d9530a5a306aba" +dependencies = [ + "cookie 0.11.0-dev (git+https://github.com/alexcrichton/cookie-rs?rev=0365a18)", + "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pear 0.1.0 (git+http://github.com/SergioBenitez/Pear?rev=54667ae)", + "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1429,12 +1402,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "smallvec" -version = "0.4.4" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "state" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1503,6 +1476,16 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "syn" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "synom" version = "0.11.3" @@ -1554,15 +1537,16 @@ dependencies = [ [[package]] name = "tera" -version = "0.10.10" +version = "0.11.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "chrono 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "humansize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "pest 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pest 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "pest_derive 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1866,7 +1850,7 @@ dependencies = [ [[package]] name = "untrusted" -version = "0.5.1" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1991,13 +1975,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum chrono 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1cce36c92cb605414e9b824f866f5babe0a0368e39ea07393b9b63cf3844c0e6" "checksum clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0f16b89cbb9ee36d87483dc939fe9f1e13c05898d56d7b230a0d4dff033a536" "checksum comrak 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "053b26c8ce23b4c505a9479beace98f95899e0bf5c5255cf0219e9b0f48cf6ea" -"checksum cookie 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "477eb650753e319be2ae77ec368a58c638f9f0c4d941c39bad95e950fb1d1d0d" +"checksum cookie 0.11.0-dev (git+https://github.com/alexcrichton/cookie-rs?rev=0365a18)" = "" "checksum core-foundation 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25bfd746d203017f7d5cbd31ee5d8e17f94b6521c7af77ece6c9e4b2d4b16c67" "checksum core-foundation-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "065a5d7ffdcbc8fa145d6f0746f3555025b9097a9e9cda59f7467abae670c78d" "checksum crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" -"checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" "checksum crossbeam-deque 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c1bdc73742c36f7f35ebcda81dbb33a7e0d33757d03a06d9ddca762712ec5ea2" -"checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150" "checksum crossbeam-epoch 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9b4e2817eb773f770dcb294127c011e22771899c21d18fce7dd739c0b9832e81" "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" "checksum crossbeam-utils 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d636a8b3bcc1b409d7ffd3facef8f21dcb4009626adbd0c5e6c4305c07253c7b" @@ -2008,7 +1990,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" "checksum encoding_rs 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "98fd0f24d1fb71a4a6b9330c8ca04cbd4e7cc5d846b54ca74ff376bc7c9f798d" "checksum entities 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b5320ae4c3782150d900b79807611a59a99fc9a1d61d686faafc24b93fc8d7ca" -"checksum error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9435d864e017c3c6afeac1654189b06cdb491cf2ff73dbf0d73b0f292f42ff8" "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" "checksum failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "934799b6c1de475a012a02dab0ace1ace43789ee4b99bcfbf1a2e3e8ced5de82" "checksum failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c7cdda555bb90c9bb67a3b670a0f42de8e73f5981524123ad8578aafec8ddb8b" @@ -2019,7 +2000,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum futf 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7c9c1ce3fa9336301af935ab852c437817d14cd33690446569392e65170aac3b" "checksum futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "1a70b146671de62ec8c8ed572219ca5d594d9b06c0b364d5e67b722fc559b48c" "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" -"checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb" "checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d" "checksum gettext-rs 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3b8c2412d5758f68a9eeba161f9ecb9a55f56bfdbf17857650b98f2b9b281a47" "checksum gettext-sys 0.19.8 (registry+https://github.com/rust-lang/crates.io-index)" = "62c644c0b8b73706fb8c7420533fd30abf6f41c2703994bc6f0826fceb7fb3d6" @@ -2033,6 +2013,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum hyper 0.11.25 (registry+https://github.com/rust-lang/crates.io-index)" = "549dbb86397490ce69d908425b9beebc85bbaad25157d67479d4995bb56fdf9a" "checksum hyper-tls 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a5aa51f6ae9842239b0fac14af5f22123b8432b4cc774a44ff059fcba0f675ca" "checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d" +"checksum indexmap 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08173ba1e906efb6538785a8844dd496f5d34f0a2d88038e95195172fc667220" "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" "checksum isatty 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a118a53ba42790ef25c82bb481ecf36e2da892646cccd361e69a6bb881e19398" "checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c" @@ -2051,7 +2032,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08cbb6b4fef96b6d77bfc40ec491b1690c779e77b05cd9f07f787ed376fd4c43" "checksum markup5ever 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfedc97d5a503e96816d10fedcd5b42f760b2e525ce2f7ec71f6a41780548475" "checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376" -"checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a" "checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" "checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" @@ -2070,11 +2050,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum openssl 0.10.6 (registry+https://github.com/rust-lang/crates.io-index)" = "63246f69962e8d5ef865f82a65241d6483c8a2905a1801e2f7feb5d187d51320" "checksum openssl 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)" = "a3605c298474a3aa69de92d21139fb5e2a81688d308262359d85cdd0d12a7985" "checksum openssl-sys 0.9.28 (registry+https://github.com/rust-lang/crates.io-index)" = "0bbd90640b148b46305c1691eed6039b5c8509bed16991e3562a01eeb76902a3" -"checksum ordermap 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b81cf3b8cb96aa0e73bbedfcdc9708d09fec2854ba8d474be4e6f666d7379e8b" -"checksum pear 0.0.16 (registry+https://github.com/rust-lang/crates.io-index)" = "b9b645aa07cf1010a67e9f67b4b9b96d6c5fb9315eee678a061d6ab58e9cb77f" -"checksum pear_codegen 0.0.16 (registry+https://github.com/rust-lang/crates.io-index)" = "ca34109829349aeefe22772916da5404b3f5cd0e63a72c5d91209fc809342265" +"checksum pear 0.1.0 (git+http://github.com/SergioBenitez/Pear?rev=54667ae)" = "" +"checksum pear_codegen 0.1.0 (git+http://github.com/SergioBenitez/Pear?rev=54667ae)" = "" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" -"checksum pest 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3e2e823a5967bb4cdc6d3e46f47baaf4ecfeae44413a642b74ad44e59e49c7f6" "checksum pest 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0fce5d8b5cc33983fc74f78ad552b5522ab41442c4ca91606e4236eb4b5ceefc" "checksum pest_derive 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "ab94faafeb93f4c5e3ce81ca0e5a779529a602ad5d09ae6d21996bfb8b6a52bf" "checksum phf 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "7d37a244c75a9748e049225155f56dbcb98fe71b192fd25fd23cb914b5ad62f2" @@ -2086,14 +2064,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" "checksum proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cd07deb3c6d1d9ff827999c7f9b04cdfd66b1b17ae508e14fe47b620f2282ae0" "checksum proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "49b6a521dc81b643e9a51e0d1cf05df46d5a2f3c0280ea72bcb68276ba64a118" +"checksum proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "effdb53b25cdad54f8f48843d67398f7ef2e14f12c1b4cb4effc549a6462a4d6" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" "checksum quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1eca14c727ad12702eb4b6bfb5a232287dcf8385cb8ca83a3eeaf6519c44c408" "checksum quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8" +"checksum quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e44651a0dc4cdd99f71c83b561e221f714912d11af1a4dff0631f923d53af035" "checksum r2d2 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f9078ca6a8a5568ed142083bb2f7dc9295b69d16f867ddcc9849e51b17d8db46" "checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1" "checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" -"checksum rayon 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a77c51c07654ddd93f6cb543c7a849863b03abc7e82591afda6dc8ad4ac3ac4a" -"checksum rayon-core 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9d24ad214285a7729b174ed6d3bcfcb80177807f959d95fafd5bfc5c4f201ac8" "checksum redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "aec3f58d903a7d2a9dc2bf0e41a746f4530e0cab6b615494e058f67a3ef947fb" @@ -2101,10 +2079,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum relay 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1576e382688d7e9deecea24417e350d3062d97e32e45d70b1cde65994ff1489a" "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" "checksum reqwest 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)" = "241faa9a8ca28a03cbbb9815a5d085f271d4c0168a19181f106aa93240c22ddb" -"checksum ring 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2a6dc7fc06a05e6de183c5b97058582e9da2de0c136eafe49609769c507724" -"checksum rocket 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c000cf7233aa997a19a43f77ddc80db11b58cdbbc12e2c1385bd62cbbace3964" -"checksum rocket_codegen 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "645dd494d1340a4c16ba8decc4bb94d3e687a7e6b57552e2341dbf436b75ffaa" -"checksum rocket_contrib 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "2b1f97dc98bf6fa9a861e3c0c71f150f1110350eaaebe56516377d7f4316a51a" +"checksum ring 0.13.0-alpha5 (registry+https://github.com/rust-lang/crates.io-index)" = "3845516753f91b4511f9b17c917ea6fa4bc5a7853a9947b0f66731aff51cdef5" +"checksum rocket 0.4.0-dev (git+https://github.com/SergioBenitez/Rocket?rev=df7111143e466c18d1f56377a8d9530a5a306aba)" = "" +"checksum rocket_codegen 0.4.0-dev (git+https://github.com/SergioBenitez/Rocket?rev=df7111143e466c18d1f56377a8d9530a5a306aba)" = "" +"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 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" @@ -2123,8 +2103,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum slab 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fdeff4cd9ecff59ec7e3744cbca73dfe5ac35c2aedb2cfba8a1c715a18912e9d" "checksum slug 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "797bcb4d24e91239a8615415814f4afb2d8ca400c472de3c73f803a5a7689e11" "checksum smallvec 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c8cbcd6df1e117c2210e13ab5109635ad68a929fcbb8964dc965b76cb5ee013" -"checksum smallvec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ee4f357e8cd37bf8822e1b964e96fd39e2cb5a0424f8aaa284ccaccc2162411c" -"checksum state 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d5562ac59585fe3d9a1ccf6b4e298ce773f5063db80d59f783776b410c1714c2" +"checksum smallvec 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "312a7df010092e73d6bbaf141957e868d4f30efd2bfd9bb1028ad91abec58514" +"checksum state 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7345c971d1ef21ffdbd103a75990a15eb03604fc8b8852ca8cb418ee1a099028" "checksum string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25d70109977172b127fe834e5449e5ab1740b9ba49fa18a2020f509174f25423" "checksum string_cache_codegen 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "35293b05cf1494e8ddd042a7df6756bf18d07f42d234f32e71dce8a7aabb0191" "checksum string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1884d1bc09741d466d9b14e6d37ac89d6909cbcac41dd9ae982d4d063bbedfc" @@ -2132,13 +2112,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" "checksum syn 0.12.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c97c05b8ebc34ddd6b967994d5c6e9852fa92f8b82b3858c39451f97346dcce5" "checksum syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "91b52877572087400e83d24b9178488541e3d535259e04ff17a63df1e5ceff59" +"checksum syn 0.14.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c67da57e61ebc7b7b6fff56bb34440ca3a83db037320b0507af4c10368deda7d" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" "checksum synstructure 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a761d12e6d8dcb4dcf952a7a89b475e3a9d69e4a69307e01a470977642914bd" "checksum syntex_fmt_macros 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5e5386bdc48758d136af85b3880548e1f3a9fad8d7dc2b38bdb48c36a9cdefc0" "checksum take 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b157868d8ac1f56b64604539990685fa7611d8fa9e5476cf0c02cf34d32917c5" "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" "checksum tendril 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9de21546595a0873061940d994bbbc5c35f024ae4fd61ec5c5b159115684f508" -"checksum tera 0.10.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d706c3bec8103f346fc7b8a3887a2ff4195cf704bdbc6307069f32ea8a2b3af5" +"checksum tera 0.11.7 (registry+https://github.com/rust-lang/crates.io-index)" = "e815b67d44c26feb06630011fb58b5b243f4e9585aac1ed0592c5795de64cd75" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693" "checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963" @@ -2173,7 +2154,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum unicode_categories 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" "checksum unidecode 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "402bb19d8e03f1d1a7450e2bd613980869438e0666331be3e073089124aa1adc" "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" -"checksum untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f392d7819dbe58833e26872f5f6f0d68b7bbbe90fc3667e98731c4a15ad9a7ae" +"checksum untrusted 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "70afa43c8c5d23a53a3c39ec9b56232c5badc19f6bb5ad529c1d6448a7241365" "checksum url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f808aadd8cfec6ef90e4a14eb46f24511824d1ac596b9682703c87056c8678b7" "checksum utf-8 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1262dfab4c30d5cb7c07026be00ee343a6cf5027fdc0104a9160f354e5db75c" "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" diff --git a/Cargo.toml b/Cargo.toml index c36984b..7c5f9d9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,11 +19,10 @@ hyper = "*" lazy_static = "*" openssl = "0.10.6" reqwest = "0.8" -rocket = "*" -rocket_codegen = "*" serde = "*" serde_derive = "1.0" serde_json = "1.0" +tera = "0.11" url = "1.7" [dependencies.chrono] @@ -34,6 +33,15 @@ version = "0.4" features = ["postgres", "r2d2", "chrono"] version = "*" +[dependencies.rocket] +git = "https://github.com/SergioBenitez/Rocket" +rev = "df7111143e466c18d1f56377a8d9530a5a306aba" + +[dependencies.rocket_codegen] +git = "https://github.com/SergioBenitez/Rocket" +rev = "df7111143e466c18d1f56377a8d9530a5a306aba" + [dependencies.rocket_contrib] features = ["tera_templates", "json"] -version = "*" +git = "https://github.com/SergioBenitez/Rocket" +rev = "df7111143e466c18d1f56377a8d9530a5a306aba" diff --git a/rust-toolchain b/rust-toolchain index 7b08dcc..27aefed 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1 +1 @@ -nightly-2018-04-18 +nightly-2018-05-31 diff --git a/src/activity_pub/mod.rs b/src/activity_pub/mod.rs index fc49c75..af544ac 100644 --- a/src/activity_pub/mod.rs +++ b/src/activity_pub/mod.rs @@ -19,7 +19,7 @@ pub mod request; pub mod sign; pub mod webfinger; -pub type ActivityPub = Content; +pub type ActivityPub = Content>; pub const CONTEXT_URL: &'static str = "https://www.w3.org/ns/activitystreams"; pub const PUBLIC_VISIBILTY: &'static str = "https://www.w3.org/ns/activitystreams#Public"; diff --git a/src/i18n.rs b/src/i18n.rs index 96e73df..ca2f685 100644 --- a/src/i18n.rs +++ b/src/i18n.rs @@ -1,7 +1,10 @@ use gettextrs::*; use rocket::{Data, Request, Rocket, fairing::{Fairing, Info, Kind}}; +use serde_json; +use std::collections::HashMap; use std::fs; use std::path::PathBuf; +use tera::{Tera, Error as TeraError}; const ACCEPT_LANG: &'static str = "Accept-Language"; @@ -42,3 +45,11 @@ impl Fairing for I18n { setlocale(LocaleCategory::LcAll, format!("{}.UTF-8", lang.replace("-", "_"))); } } + +fn tera_gettext(ctx: HashMap) -> Result { + Ok(serde_json::Value::String(String::from(""))) +} + +pub fn tera(t: &mut Tera) { + t.register_global_function("gettext", Box::new(tera_gettext)) +} diff --git a/src/main.rs b/src/main.rs index 57b316e..4545147 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,8 @@ -#![feature(plugin, custom_derive, iterator_find_map)] +#![feature(plugin, custom_derive, decl_macro, iterator_find_map)] #![plugin(rocket_codegen)] extern crate activitypub; +extern crate ammonia; extern crate array_tool; extern crate base64; extern crate bcrypt; @@ -29,8 +30,8 @@ extern crate serde; extern crate serde_derive; #[macro_use] extern crate serde_json; +extern crate tera; extern crate url; -extern crate ammonia; use diesel::{pg::PgConnection, r2d2::{ConnectionManager, Pool}}; use dotenv::dotenv; @@ -128,7 +129,9 @@ fn main() { routes::well_known::webfinger ]) .manage(init_pool()) - .attach(Template::fairing()) + .attach(Template::custom(|engines| { + i18n::tera(&mut engines.tera); + })) .attach(i18n::I18n::new("plume")) .launch(); } diff --git a/src/routes/blogs.rs b/src/routes/blogs.rs index 1131a06..0a64e9e 100644 --- a/src/routes/blogs.rs +++ b/src/routes/blogs.rs @@ -83,7 +83,7 @@ fn create(conn: DbConn, data: Form, user: User) -> Redirect { is_owner: true }); - Redirect::to(format!("/~/{}/", slug).as_str()) + Redirect::to(format!("/~/{}/", slug)) } #[get("/~//outbox")] diff --git a/src/routes/comments.rs b/src/routes/comments.rs index 86542a1..7c039ee 100644 --- a/src/routes/comments.rs +++ b/src/routes/comments.rs @@ -55,5 +55,5 @@ fn create(blog: String, slug: String, query: CommentQuery, data: Form String { } #[get("/nodeinfo")] -fn nodeinfo(conn: DbConn) -> Json { +fn nodeinfo(conn: DbConn) -> Json { Json(json!({ "version": "2.0", "software": { diff --git a/src/routes/likes.rs b/src/routes/likes.rs index 55dce94..f99782e 100644 --- a/src/routes/likes.rs +++ b/src/routes/likes.rs @@ -29,7 +29,7 @@ fn create(blog: String, slug: String, user: User, conn: DbConn) -> Redirect { broadcast(&*conn, &user, delete_act, user.get_followers(&*conn)); } - Redirect::to(format!("/~/{}/{}/", blog, slug).as_ref()) + Redirect::to(format!("/~/{}/{}/", blog, slug)) } #[get("/~///like", rank = 2)] diff --git a/src/routes/posts.rs b/src/routes/posts.rs index 07d4b55..fef302a 100644 --- a/src/routes/posts.rs +++ b/src/routes/posts.rs @@ -120,5 +120,5 @@ fn create(blog_name: String, data: Form, user: User, conn: DbConn) let act = post.create_activity(&*conn); broadcast(&*conn, &user, act, user.get_followers(&*conn)); - Redirect::to(format!("/~/{}/{}/", blog_name, slug).as_str()) + Redirect::to(format!("/~/{}/{}/", blog_name, slug)) } diff --git a/src/routes/reshares.rs b/src/routes/reshares.rs index 19f6933..5069864 100644 --- a/src/routes/reshares.rs +++ b/src/routes/reshares.rs @@ -29,7 +29,7 @@ fn create(blog: String, slug: String, user: User, conn: DbConn) -> Redirect { broadcast(&*conn, &user, delete_act, user.get_followers(&*conn)); } - Redirect::to(format!("/~/{}/{}/", blog, slug).as_ref()) + Redirect::to(format!("/~/{}/{}/", blog, slug)) } #[get("/~///reshare", rank=1)] diff --git a/src/routes/session.rs b/src/routes/session.rs index bf7d5e6..2b72879 100644 --- a/src/routes/session.rs +++ b/src/routes/session.rs @@ -1,5 +1,5 @@ use rocket::{ - http::{Cookie, Cookies}, + http::{Cookie, Cookies, uri::Uri}, response::{Redirect, status::NotFound}, request::{Form,FlashMessage} }; @@ -49,10 +49,10 @@ fn create(conn: DbConn, data: Form, flash: Option, mut Ok(usr) => { if usr.auth(form.password.to_string()) { cookies.add_private(Cookie::new(AUTH_COOKIE, usr.id.to_string())); - Ok(Redirect::to(&flash - .and_then(|f| if f.name()=="callback" { Some(f.msg().to_owned()) } else { None }) + Ok(Redirect::to(Uri::new(flash + .and_then(|f| if f.name() == "callback" { Some(f.msg().to_owned()) } else { None }) .unwrap_or("/".to_owned())) - ) + )) } else { Err(NotFound(String::from("Invalid username or password"))) } diff --git a/src/routes/user.rs b/src/routes/user.rs index 8705b25..8e6e5cd 100644 --- a/src/routes/user.rs +++ b/src/routes/user.rs @@ -27,7 +27,7 @@ use utils; #[get("/me")] fn me(user: Option) -> Result> { match user { - Some(user) => Ok(Redirect::to(format!("/@/{}/", user.username).as_ref())), + Some(user) => Ok(Redirect::to(format!("/@/{}/", user.username))), None => Err(utils::requires_login("", "/me")) } } @@ -104,7 +104,7 @@ fn follow(name: String, conn: DbConn, user: User) -> Redirect { act.follow_props.set_object_object(user.into_activity(&*conn)).unwrap(); act.object_props.set_id_string(format!("{}/follow/{}", user.ap_url, target.ap_url)).unwrap(); broadcast(&*conn, &user, act, vec![target]); - Redirect::to(format!("/@/{}/", name).as_ref()) + Redirect::to(format!("/@/{}/", name)) } #[get("/@//follow", rank = 2)] @@ -208,7 +208,7 @@ fn create(conn: DbConn, data: Form) -> Result { User::hash_pass(form.password.to_string()), inst.id )).update_boxes(&*conn); - Ok(Redirect::to(format!("/@/{}/", data.get().username).as_str())) + Ok(Redirect::to(format!("/@/{}/", data.get().username))) } else { Err(String::from("Passwords don't match")) } diff --git a/src/utils.rs b/src/utils.rs index eb6d110..5adac6d 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,5 +1,8 @@ use heck::CamelCase; -use rocket::response::{Redirect, Flash}; +use rocket::{ + http::uri::Uri, + response::{Redirect, Flash} +}; /// Remove non alphanumeric characters and CamelCase a string pub fn make_actor_id(name: String) -> String { @@ -12,5 +15,5 @@ pub fn make_actor_id(name: String) -> String { } pub fn requires_login(message: &str, url: &str) -> Flash { - Flash::new(Redirect::to(&format!("/login?m={}", message)), "callback", url) + Flash::new(Redirect::to(Uri::new(format!("/login?m={}", message))), "callback", url) } From 1092ceba7617bea9b5629635264c90986f77dd4e Mon Sep 17 00:00:00 2001 From: Bat Date: Sat, 16 Jun 2018 23:49:44 +0100 Subject: [PATCH 22/39] Fix locale switching + Make the gettext Tera function work --- po/en.po | 12 ++++++------ po/fr.po | 4 ++-- po/plume.pot | 2 +- src/i18n.rs | 16 ++++++++++++---- templates/instance/index.html.tera | 2 +- translations/en/LC_MESSAGES/plume.mo | Bin 459 -> 481 bytes translations/fr/LC_MESSAGES/plume.mo | Bin 394 -> 483 bytes 7 files changed, 22 insertions(+), 14 deletions(-) diff --git a/po/en.po b/po/en.po index 4ffaf0d..01a565e 100644 --- a/po/en.po +++ b/po/en.po @@ -3,14 +3,14 @@ msgstr "" "Project-Id-Version: plume\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2018-06-15 16:33-0700\n" -"PO-Revision-Date: 2018-06-15 16:35+0100\n" -"Last-Translator: baptiste \n" -"Language-Team: English\n" -"Language: en_US\n" +"PO-Revision-Date: 2018-06-15 16:33-0700\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: en\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgid "Welcome on %s" -msgstr "Welcome on %s" +msgid "Welcome on {{ instance_name }}" +msgstr "Welcome on {{ instance_name }}" diff --git a/po/fr.po b/po/fr.po index dadf304..2e3a767 100644 --- a/po/fr.po +++ b/po/fr.po @@ -12,5 +12,5 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -msgid "Welcome on %s" -msgstr "" +msgid "Welcome on {{ instance_name }}" +msgstr "Bienvenue sur {{ instance_name }}" diff --git a/po/plume.pot b/po/plume.pot index e536d0d..8d2f16a 100644 --- a/po/plume.pot +++ b/po/plume.pot @@ -12,5 +12,5 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" -msgid "Welcome on %s" +msgid "Welcome on {{ instance_name }}" msgstr "" diff --git a/src/i18n.rs b/src/i18n.rs index ca2f685..2cf5f42 100644 --- a/src/i18n.rs +++ b/src/i18n.rs @@ -2,6 +2,7 @@ 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::path::PathBuf; use tera::{Tera, Error as TeraError}; @@ -29,7 +30,7 @@ impl Fairing for I18n { } fn on_attach(&self, rocket: Rocket) -> Result { - bindtextdomain(self.domain, fs::canonicalize(&PathBuf::from("./translations")).unwrap().to_str().unwrap()); + bindtextdomain(self.domain, fs::canonicalize(&PathBuf::from("./translations/")).unwrap().to_str().unwrap()); textdomain(self.domain); Ok(rocket) } @@ -42,14 +43,21 @@ impl Fairing for I18n { .split(",") .nth(0) .unwrap_or("en"); - setlocale(LocaleCategory::LcAll, format!("{}.UTF-8", lang.replace("-", "_"))); + + // 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 tera_gettext(ctx: HashMap) -> Result { - Ok(serde_json::Value::String(String::from(""))) + let trans = gettext(ctx.get("t").unwrap().as_str().unwrap()); + 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_global_function("gettext", Box::new(tera_gettext)) + t.register_global_function("_", Box::new(tera_gettext)) } diff --git a/templates/instance/index.html.tera b/templates/instance/index.html.tera index 480c758..28cbe06 100644 --- a/templates/instance/index.html.tera +++ b/templates/instance/index.html.tera @@ -6,7 +6,7 @@ {% endblock title %} {% block content %} -

Welcome on {{ instance.name }}

+

{{ _(t="Welcome on {{ instance_name }}", instance_name=instance.name) }}

Latest articles

diff --git a/translations/en/LC_MESSAGES/plume.mo b/translations/en/LC_MESSAGES/plume.mo index 27705383d0b74ed386957ce20f0a6a15851e3d46..a6d290ee1571194d025268269cbe00e96ac7dc0f 100644 GIT binary patch delta 191 zcmX@j{E&HqinkmC14AGPGcqs~0BI2a5ReT-aKHp(g{S5u=jWy>U>y`6L#X=!O&}<`w58mgE;%DL9svV~8y=2|J_<>#fs#jF%k^Cp`yP7=Xl7Xtt#T{g-9 delta 169 zcmaFJe42TJiWM&d14AGX$1*Z7!~?L<~$oi~_<_bCUCOQx)>_6jX~R=GVlS zY8x0D7;yO{7MJLT6eZ>r=OmWo7g;GJB^H!q7MG+d*uYp0>8UxXReBYbRdzt-dFiEz l>8ZLQsfoE(3a)wSIhn;7aA7Nj)V%o6;K|mElbBVD830H_EcpNc diff --git a/translations/fr/LC_MESSAGES/plume.mo b/translations/fr/LC_MESSAGES/plume.mo index ca4fa88801de6f2481185754ad892be0f40f26e3..bdee9a784b83ccabae5aa15850cd43efc4d0c692 100644 GIT binary patch delta 171 zcmeBTe#~5dPl#nI0}wC)u?!IF05K~N+W;{L1OTxd5C?+Tj0_9~Kw1%q4+7ah1P37f zU=W^~lboNMs*si{tbSO9SVP|^}egVeyl#{3{g0PZXW+W-In From 657a0837e22adbb213a63a3b57d69b68112f06a0 Mon Sep 17 00:00:00 2001 From: Bat Date: Sun, 17 Jun 2018 10:38:59 +0100 Subject: [PATCH 23/39] Use filters for gettext in Tera --- src/i18n.rs | 6 +++--- templates/instance/index.html.tera | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/i18n.rs b/src/i18n.rs index 2cf5f42..96c699f 100644 --- a/src/i18n.rs +++ b/src/i18n.rs @@ -53,11 +53,11 @@ impl Fairing for I18n { } } -fn tera_gettext(ctx: HashMap) -> Result { - let trans = gettext(ctx.get("t").unwrap().as_str().unwrap()); +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("")))) } pub fn tera(t: &mut Tera) { - t.register_global_function("_", Box::new(tera_gettext)) + t.register_filter("_", tera_gettext) } diff --git a/templates/instance/index.html.tera b/templates/instance/index.html.tera index 28cbe06..b859fc8 100644 --- a/templates/instance/index.html.tera +++ b/templates/instance/index.html.tera @@ -6,7 +6,7 @@ {% endblock title %} {% block content %} -

{{ _(t="Welcome on {{ instance_name }}", instance_name=instance.name) }}

+

{{ "Welcome on {{ instance_name }}" | _(instance_name=instance.name) }}

Latest articles

From 25ec318f3f39aec064f656126172dbd7f7ab824f Mon Sep 17 00:00:00 2001 From: Bat Date: Sun, 17 Jun 2018 11:16:20 +0100 Subject: [PATCH 24/39] Inject ngettext into Tera templates Fix .po updating (without the -U option, the result was written to stdout, not the .po file) --- build.rs | 1 + po/en.po | 5 +++++ po/en.po~ | 16 ++++++++++++++++ po/fr.po | 5 +++++ po/fr.po~ | 16 ++++++++++++++++ po/plume.pot | 5 +++++ src/i18n.rs | 14 ++++++++++++-- templates/users/details.html.tera | 2 +- translations/en/LC_MESSAGES/plume.mo | Bin 481 -> 567 bytes translations/fr/LC_MESSAGES/plume.mo | Bin 483 -> 586 bytes 10 files changed, 61 insertions(+), 3 deletions(-) create mode 100644 po/en.po~ create mode 100644 po/fr.po~ diff --git a/build.rs b/build.rs index f85f7ce..2e0afde 100644 --- a/build.rs +++ b/build.rs @@ -17,6 +17,7 @@ fn update_po() { println!("Updating {}", lang.clone()); // Update it Command::new("msgmerge") + .arg("-U") .arg(po_path.to_str().unwrap()) .arg(pot_path.to_str().unwrap()) .spawn() diff --git a/po/en.po b/po/en.po index 01a565e..bbe17a7 100644 --- a/po/en.po +++ b/po/en.po @@ -14,3 +14,8 @@ msgstr "" msgid "Welcome on {{ instance_name }}" msgstr "Welcome on {{ instance_name }}" + +msgid "One follower" +msgid_plural "{{ count }} followers" +msgstr[0] "One follower" +msgstr[1] "{{ count }} followers" diff --git a/po/en.po~ b/po/en.po~ new file mode 100644 index 0000000..01a565e --- /dev/null +++ b/po/en.po~ @@ -0,0 +1,16 @@ +msgid "" +msgstr "" +"Project-Id-Version: plume\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-06-15 16:33-0700\n" +"PO-Revision-Date: 2018-06-15 16:33-0700\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: en\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Welcome on {{ instance_name }}" +msgstr "Welcome on {{ instance_name }}" diff --git a/po/fr.po b/po/fr.po index 2e3a767..ad0a929 100644 --- a/po/fr.po +++ b/po/fr.po @@ -14,3 +14,8 @@ msgstr "" msgid "Welcome on {{ instance_name }}" msgstr "Bienvenue sur {{ instance_name }}" + +msgid "One follower" +msgid_plural "{{ count }} followers" +msgstr[0] "{{ count }} abonné⋅e" +msgstr[1] "{{ count }} abonné⋅e⋅s" diff --git a/po/fr.po~ b/po/fr.po~ new file mode 100644 index 0000000..2e3a767 --- /dev/null +++ b/po/fr.po~ @@ -0,0 +1,16 @@ +msgid "" +msgstr "" +"Project-Id-Version: plume\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-06-15 16:33-0700\n" +"PO-Revision-Date: 2018-06-15 16:33-0700\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "Welcome on {{ instance_name }}" +msgstr "Bienvenue sur {{ instance_name }}" diff --git a/po/plume.pot b/po/plume.pot index 8d2f16a..e654621 100644 --- a/po/plume.pot +++ b/po/plume.pot @@ -14,3 +14,8 @@ msgstr "" msgid "Welcome on {{ instance_name }}" msgstr "" + +msgid "One follower" +msgid_plural "{{ count }} followers" +msgstr[0] "" +msgstr[1] "" diff --git a/src/i18n.rs b/src/i18n.rs index 96c699f..caad569 100644 --- a/src/i18n.rs +++ b/src/i18n.rs @@ -58,6 +58,16 @@ fn tera_gettext(msg: serde_json::Value, ctx: HashMap) 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) +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/templates/users/details.html.tera b/templates/users/details.html.tera index a918474..524754d 100644 --- a/templates/users/details.html.tera +++ b/templates/users/details.html.tera @@ -42,7 +42,7 @@
diff --git a/translations/en/LC_MESSAGES/plume.mo b/translations/en/LC_MESSAGES/plume.mo index a6d290ee1571194d025268269cbe00e96ac7dc0f..cfc0f640a794367d1d99f94834ac6f63069f810a 100644 GIT binary patch delta 184 zcmaFJyq%@~o)F7a1|VPtVi_Pd0b*7l_5orLNC09bAWj5gIUsHU;y^|QhQ&Y{B>ol1 z28l~BF)#p`U;r`;$b|s^yi|p>{G6Qp^3)=R>S~4L{L;J`!ju94#M36E delta 97 zcmdna@{l>;o)F7a1|VPpVi_RT0b*7lwgF-g2moR^APxj!Mh1ogDE|K_B z*@{3~gNcCw$OHqBSwJoX_~)f6q~+)2%wF;rJ8Bj`2eFb08XthZvX%Q delta 93 zcmX@b@|Zc`o)F7a1|VPpVi_RT0b*7lwgF-g2moR^APxkv85tM~fV3hI9|W?22o6B{ OL11HZA>(8XCM5vXv Date: Sun, 17 Jun 2018 11:28:32 +0100 Subject: [PATCH 25/39] Don't put translations/ in git --- translations/en/LC_MESSAGES/plume.mo | Bin 567 -> 0 bytes translations/fr/LC_MESSAGES/plume.mo | Bin 586 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 translations/en/LC_MESSAGES/plume.mo delete mode 100644 translations/fr/LC_MESSAGES/plume.mo diff --git a/translations/en/LC_MESSAGES/plume.mo b/translations/en/LC_MESSAGES/plume.mo deleted file mode 100644 index cfc0f640a794367d1d99f94834ac6f63069f810a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 567 zcmbu6y-ve05Xa5el97o4p@RtqL&9g3DgzWMA+>5j0Y)&%5rUj^WjjEHy73A;0q@0I zuyX;4ZY-Silkfie>+WoSEY80PjyYzT*<}`(9@E4Pv&JZ9g?VMpW`ua>v(Y~}Z}g>E zAvpbxrWcn#F(8CHqqTWLD_&k8Gc|dbOnyZtu25&DLNEkuD9L$68D5iOZ88x(ynYxea#woXyplI tCNHUop>6Gy01Qy>@u7Ubl-q7;uwac?*j zU2D!U^>Vi-57D~ZPz(cI78vZ~z*sLkF3WqeRc1~mCWfH9m&i?v%Cl5%DUUHMg;8CG zt1?=FXf>|YWVjZFER_3rkyn=g>e|YAnOH?mD{pKJ8>Ke|`=?6lYsiq$@-e-jttcy1 zhB84_#6X7ds~1Dx2A$o`_V+8Ig)rDO`<;pXNU3>e4DLcZ@9@pUfY`OV?a#RDZ=~bB Date: Sun, 17 Jun 2018 11:33:50 +0100 Subject: [PATCH 26/39] Compile translations at run time --- .gitignore | 1 + build.rs | 61 ----------------------------------------------------- src/i18n.rs | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 60 insertions(+), 62 deletions(-) delete mode 100644 build.rs diff --git a/.gitignore b/.gitignore index e0ba536..32bc127 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ rls /target **/*.rs.bk rls +translations diff --git a/build.rs b/build.rs deleted file mode 100644 index 2e0afde..0000000 --- a/build.rs +++ /dev/null @@ -1,61 +0,0 @@ -use std::fs::{create_dir_all, File}; -use std::io::{BufReader, prelude::*}; -use std::path::Path; -use std::process::Command; - -fn main() { - update_po(); - compile_po(); -} - -fn update_po() { - let pot_path = Path::new("po").join("plume.pot"); - - 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() { - 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"); - create_dir_all(mo_dir.clone()).expect("Couldn't create MO directory"); - let mo_path = mo_dir.join("plume.mo"); - - 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 = 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() -} diff --git a/src/i18n.rs b/src/i18n.rs index caad569..c123092 100644 --- a/src/i18n.rs +++ b/src/i18n.rs @@ -4,7 +4,9 @@ use serde_json; use std::collections::HashMap; use std::env; use std::fs; -use std::path::PathBuf; +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"; @@ -30,6 +32,9 @@ impl Fairing for I18n { } fn on_attach(&self, rocket: Rocket) -> Result { + update_po(); + compile_po(); + bindtextdomain(self.domain, fs::canonicalize(&PathBuf::from("./translations/")).unwrap().to_str().unwrap()); textdomain(self.domain); Ok(rocket) @@ -53,6 +58,59 @@ impl Fairing for I18n { } } + +fn update_po() { + let pot_path = Path::new("po").join("plume.pot"); + + 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() { + 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("plume.mo"); + + 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("")))) From 23982d00fcec5128e07622b9506d8052756ec7b0 Mon Sep 17 00:00:00 2001 From: Bat Date: Sun, 17 Jun 2018 11:37:24 +0100 Subject: [PATCH 27/39] Use the choosen domain when compiling templates --- src/i18n.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/i18n.rs b/src/i18n.rs index c123092..e834783 100644 --- a/src/i18n.rs +++ b/src/i18n.rs @@ -32,8 +32,8 @@ impl Fairing for I18n { } fn on_attach(&self, rocket: Rocket) -> Result { - update_po(); - compile_po(); + update_po(self.domain); + compile_po(self.domain); bindtextdomain(self.domain, fs::canonicalize(&PathBuf::from("./translations/")).unwrap().to_str().unwrap()); textdomain(self.domain); @@ -58,9 +58,8 @@ impl Fairing for I18n { } } - -fn update_po() { - let pot_path = Path::new("po").join("plume.pot"); +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())); @@ -88,14 +87,14 @@ fn update_po() { } } -fn compile_po() { +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("plume.mo"); + let mo_path = mo_dir.join(format!("{}.mo", domain)); Command::new("msgfmt") .arg(format!("--output-file={}", mo_path.to_str().unwrap())) From ab5c992684a47cd707ddf143c00bd22ae11a387f Mon Sep 17 00:00:00 2001 From: Bat Date: Sun, 17 Jun 2018 11:53:11 +0100 Subject: [PATCH 28/39] Add translation instructions for developers --- DEVELOPMENT.md | 74 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 73 insertions(+), 1 deletion(-) diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index 171d1e7..0338800 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -1,65 +1,99 @@ # Development Guide + ## Running Plume locally + ### Mac OSX + All commands are run in the Mac Terminal or terminal emulator of your choice, such as iTerm2. First, you will need [Git](https://git-scm.com/download/mac), [Homebrew](https://brew.sh/), [Rust](https://www.rust-lang.org/en-US/), and [Postgres](https://www.postgresql.org/). Follow the instructions to install Homebrew before continuing if you don't already have it. + #### Download the Repository + Navigate to the directory on your machine where you would like to install the repository, such as in `~/dev` by running `cd dev`. Now, clone the remote repository by running `git clone https://github.com/Plume-org/Plume.git`. This will install the codebase to the `Plume` subdirectory. Navigate into that directory by running `cd Plume`. + #### Rust + If you think you might already have rust on your machine, you can check by running + ``` rustc --version # Should output something like # rustc 1.28.0-nightly (a805a2a5e 2018-06-10) ``` + If you don't already have Rust, install it by running + ``` curl https://sh.rustup.rs -sSf | sh ``` + In the interactive installation, choose the option of the nightly toolchain. Restart your console so that the `rustc` CLI tool is available. + #### Postgres + Now we will use Homebrew to install Postgres. If you think you might already have it, try running `brew info postgres`. If it is not available, continue to install Postgres by running the following: + ``` brew install postgres ``` + Now, you can use the following command to start Postgres on a one-time basis. + ``` pg_ctl -D /usr/local/var/postgres start ``` + After starting Postgres, we need to enter [PSQL](http://postgresguide.com/utilities/psql.html), the interactive terminal for running postgres queries. We'll be running this as the user `postgres` which is an admin-type postgres user. + ``` psql postgres ``` + Now that you are in psql, enter the following queries to prepare the database for Plume. + ``` CREATE DATABASE plume; CREATE USER plume WITH PASSWORD 'plume'; GRANT ALL PRIVILEGES ON DATABASE plume to plume; \q ``` + The final command `\q` lets us exit psql and returns us to the Terminal. Now, we will open psql again, this time as the `plume` user we just created. Then we'll give all privileges on all tables and sequences to our `plume` user. This is for local development use only and it's not recommend to give complete access to this user in a production environment. + ``` psql plume GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO plume; GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO plume; \q ``` + #### Database Migration -Now that the Postgres database is set up and the `plume` user has the privileges it needs, we can set up the database using the diesel CLI. If this was your time installing Rust, you will probably need to run that using `cargo`. `cargo` is installed with `rustc` so if you followed the earlier instructions it will already be available. + +Now that the Postgres database is set up and the `plume` user has the privileges it needs, we can set up the database using the diesel CLI. If this was your time installing Rust, you +will probably need to run that using `cargo`. `cargo` is installed with `rustc` so if you followed the earlier instructions it will already be available. + ``` cargo install diesel_cli ``` + The first time you run this, you can run setup. After that, every time you pull the repository you will want to run the migration command in case there were any migrations. Those commands are + ``` diesel setup --database-url='postgres://localhost/plume' diesel migration run --database-url='postgres://localhost/plume' ``` + #### Running Plume + To run Plume locally, make sure you are once again in the Plume directory, such as `~/dev/Plume`. Now you will be able to run the application using the command + ``` cargo run ``` + #### Configuration + Now Plume should be running on your machine at [http://localhost:8000](http://localhost:8000). The first time you run the application, you'll want to configure your blog name on the [http://localhost:8000/configuration](http://localhost:8000/configuration) page. You'll be able to change this name later. + #### Testing the federation To test the federation, you'll need to setup another database (see "Setup the database"), @@ -78,12 +112,50 @@ To run this other instance, you'll need to give two environment variables: ``` ROCKET_PORT=3033 DB_NAME=my_other_plume_db cargo run ``` + #### Making a Pull Request To create an upstream fork of the repository in GitHub, click "Fork" in the top right button on the main page of the [Plume repository](https://github.com/Plume-org/Plume). Now, in the command line, set another remote for the repository by running the following command, replacing `myname` with the name under which you forked the repo. You can use another name besides `upstream` if you prefer. Using [SSH](https://help.github.com/articles/connecting-to-github-with-ssh/) is recommended. + ``` git remote add upstream git@github.com/myname/Plume.git # Alt # git remote add upstream https://github.com/myname/Plume.git ``` + Now, make any changes to the code you want. After committing your changes, push to the upstream fork. Once your changes are made, visit the GitHub page for your fork and select "New pull request". Add descriptive text, any issue numbers using hashtags to reference the issue number, screenshots of your changes if relevant, a description of how you tested your changes, and any other information that will help the project maintainers be able to quickly accept your pull requests. The project maintainers may suggest further changes to improve the pull request even more. After implementing this locally, you can push to your upstream fork again and the changes will immediately show up in the pull request after pushing. Once all the suggested changes are made, the pull request may be accepted. Thanks for contributing. + +#### When working with Tera templates + +When working with the interface, or any message that will be displayed to the final user, keep in mind that Plume is an internationalized software. To make sure that the parts of the interface you are changing are translatable, you should: + +- Use the `_` and `_n` filters instead of directly writing strings in your HTML markup +- Add the strings to translate to the `po/plume.pot` file + +Here is an example: let's say we want to add two strings, a simple one and one that may deal with plurals. The first step is to add them to whatever template we want to display them in: + +```jinja +

{{ "Hello, world!" | _ }}

+ +

{{ "You have {{ count }} new notifications" | _n(singular="You have one new notification", count=n_notifications) }}

+``` + +As you can see, the `_` doesn't need any special argument to work, but `_n` requires `singular` (the singular form, in English) and `count` (the number of items, to determine which form to use) to be present. Note that any parameters given to these filters can be used as regular Tera variables inside of the translated strings, like we are doing with the `count` variable in the second string above. + +The second step is to add them to POT file. To add a simple message, just do: + +```po +msgid "Hello, world" # The string you used with your filter +msgstr "" # Always empty +``` + +For plural forms, the syntax is a bit different: + +```po +msgid "You have one new notification" # The singular form +msgid_plural "You have {{ count }} new notifications" # The plural one +msgstr[0] "" +msgstr[1] "" +``` + +And that's it! Once these new messages will have been translated, they will correctly be displayed in the requested locale! From fae6ecde6d6f44915e416ecaa3adf0ab21a9065f Mon Sep 17 00:00:00 2001 From: Bat Date: Sun, 17 Jun 2018 12:10:25 +0100 Subject: [PATCH 29/39] Add translation instructions for translators --- INTERNATIONALIZATION.md | 35 +++++++++++++++++++++++++++++++++++ README.md | 2 ++ 2 files changed, 37 insertions(+) create mode 100644 INTERNATIONALIZATION.md diff --git a/INTERNATIONALIZATION.md b/INTERNATIONALIZATION.md new file mode 100644 index 0000000..cbb0497 --- /dev/null +++ b/INTERNATIONALIZATION.md @@ -0,0 +1,35 @@ +# Making Plume available in your language + +*You will need to have basic git and GitHub knownledge to follow this guide. But we plan to setup a more user-friendly translation tool in the future.* + +To translate Plume in your language, you'll first need to make sure it is listed in the `po/LINGUAS` file. If it is not, you can ask anybody with a development environment to add it (or do it yourself if you have a development environment). Once it will be here, Plume must be launched once to generate all the needed files. + +Then you can start translating. Find the file corresponding to your locale, which is `po/YOUR_LOCALE.po`, and open it. Inside, you have a list of strings to translate. There are two kind of translatable strings. + +## Simple strings + +They look like this: + +```po +msgid "Hello, world" +msgstr "" +``` + +What is next to `msgid` is the string in English. To translate it, just fill the `msgstr` field with the translation. + +## Strings with plural forms + +Sometimes, strings may change depending on a number (for instance, a post counter). In the `.po` files, these strings look like this: + +``` +msgid "One post" +msgid_plural "{{ count }} posts" +msgstr[0] "" +msgstr[1] "" +``` + +Then you should fill the two `msgstr` field, one with the singular form, the second with the plural one. If your language as more than two forms, you can add another one by following the same pattern (`msgstr[n] ""`). + +## Interpolation + +Strings you translate may contain data from Plume (a username for instance). To tell Plume where to put these data, surround their identifier by `{{` and `}}`. The identifier is also present in this form in the English string to translate (this what you can see above, with the `{{ count }} posts` message). diff --git a/README.md b/README.md index e135789..70ac657 100644 --- a/README.md +++ b/README.md @@ -9,3 +9,5 @@ It is not yet ready for production use, but we have all the basic features (acco Feel free to join our Matrix room: `#plume:disroot.org` to discuss about the project! If you are interested in coding, check out the [development guide](https://github.com/Plume-org/Plume/blob/master/DEVELOPMENT.md). You can also help by reporting issues, suggesting features, or writing documentation for instance. + +If you would like to help by translating Plume, we also have [a guide for you](https://github.com/Plume-org/Plume/blob/master/INTERNATIONALIZATION.md)! From cafb0e2277eb7f2a6b1f608a8c13bba37926bc5f Mon Sep 17 00:00:00 2001 From: Bat Date: Sun, 17 Jun 2018 15:28:44 +0100 Subject: [PATCH 30/39] 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 099e504..c687510 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 7c5f9d9..b175393 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 e834783..0000000 --- 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 4545147..a1ffd40 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(); } From 3207aa0e22d35ec0827fd46840de226a04a01d49 Mon Sep 17 00:00:00 2001 From: Bat Date: Sun, 17 Jun 2018 16:26:15 +0100 Subject: [PATCH 31/39] Make the UI translatable --- po/en.po | 3 + po/en.po~ | 5 + po/fr.po | 3 + po/fr.po~ | 5 + po/plume.pot | 221 ++++++++++++++++++++++++ src/main.rs | 6 +- templates/base.html.tera | 18 +- templates/blogs/details.html.tera | 6 +- templates/blogs/new.html.tera | 10 +- templates/comments/new.html.tera | 8 +- templates/errors/500.html.tera | 4 +- templates/instance/configure.html.tera | 8 +- templates/instance/index.html.tera | 2 +- templates/notifications/index.html.tera | 4 +- templates/posts/details.html.tera | 22 +-- templates/posts/new.html.tera | 12 +- templates/session/login.html.tera | 10 +- templates/users/dashboard.tera | 10 +- templates/users/details.html.tera | 16 +- templates/users/edit.html.tera | 12 +- templates/users/followers.html.tera | 16 +- templates/users/new.html.tera | 14 +- 22 files changed, 326 insertions(+), 89 deletions(-) diff --git a/po/en.po b/po/en.po index bbe17a7..450ac62 100644 --- a/po/en.po +++ b/po/en.po @@ -12,6 +12,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" +msgid "Latest articles" +msgstr "" + msgid "Welcome on {{ instance_name }}" msgstr "Welcome on {{ instance_name }}" diff --git a/po/en.po~ b/po/en.po~ index 01a565e..bbe17a7 100644 --- a/po/en.po~ +++ b/po/en.po~ @@ -14,3 +14,8 @@ msgstr "" msgid "Welcome on {{ instance_name }}" msgstr "Welcome on {{ instance_name }}" + +msgid "One follower" +msgid_plural "{{ count }} followers" +msgstr[0] "One follower" +msgstr[1] "{{ count }} followers" diff --git a/po/fr.po b/po/fr.po index ad0a929..e621c36 100644 --- a/po/fr.po +++ b/po/fr.po @@ -12,6 +12,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" +msgid "Latest articles" +msgstr "Derniers articles" + msgid "Welcome on {{ instance_name }}" msgstr "Bienvenue sur {{ instance_name }}" diff --git a/po/fr.po~ b/po/fr.po~ index 2e3a767..ad0a929 100644 --- a/po/fr.po~ +++ b/po/fr.po~ @@ -14,3 +14,8 @@ msgstr "" msgid "Welcome on {{ instance_name }}" msgstr "Bienvenue sur {{ instance_name }}" + +msgid "One follower" +msgid_plural "{{ count }} followers" +msgstr[0] "{{ count }} abonné⋅e" +msgstr[1] "{{ count }} abonné⋅e⋅s" diff --git a/po/plume.pot b/po/plume.pot index e654621..30bad45 100644 --- a/po/plume.pot +++ b/po/plume.pot @@ -12,10 +12,231 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" +msgid "Latest articles" +msgstr "" + +msgid "No posts to see here yet." +msgstr "" + +msgid "New article" +msgstr "" + +msgid "New blog" +msgstr "" + +msgid "Create a blog" +msgstr "" + +msgid "Title" +msgstr "" + +msgid "Create blog" +msgstr "" + +msgid "Comment \"{{ post }}\"" +msgstr "" + +msgid "Content" +msgstr "" + +msgid "Submit comment" +msgstr "" + +msgid "Something broke on our side." +msgstr "" + +msgid "Sorry about that. If you think this is a bug, please report it." +msgstr "" + +msgid "Configuration" +msgstr "" + +msgid "Configure your instance" +msgstr "" + +msgid "Name" +msgstr "" + +msgid "Let's go!" +msgstr "" + msgid "Welcome on {{ instance_name }}" msgstr "" +msgid "Notifications" +msgstr "" + +msgid "Written by {{ link_start }}{{ name }}{{ link_end }}" +msgstr "" + +msgid "This article is under the {{ license }} license." +msgstr "" + +msgid "One like" +msgid_plural "{{ count }} likes" +msgstr[0] "" +msgstr[1] "" + +msgid "I don't like this anymore" +msgstr "" + +msgid "Add yours" +msgstr "" + +msgid "One reshare" +msgid_plural "{{ count }} reshares" +msgstr[0] "" +msgstr[1] "" + +msgid "I don't want to reshare this anymore" +msgstr "" + +msgid "Reshare" +msgstr "" + +msgid "Comments" +msgstr "" + +msgid "Respond" +msgstr "" + +msgid "Comment" +msgstr "" + +msgid "New post" +msgstr "" + +msgid "Create a post" +msgstr "" + +msgid "Title" +msgstr "" + +msgid "Content" +msgstr "" + +msgid "License" +msgstr "" + +msgid "Publish" +msgstr "" + +msgid "Login" +msgstr "" + +msgid "Username or email" +msgstr "" + +msgid "Password" +msgstr "" + +msgid "Dashboard" +msgstr "" + +msgid "Your Dashboard" +msgstr "" + +msgid "Your Blogs" +msgstr "" + +msgid "You don't have any blog yet. Create your own, or ask to join one." +msgstr "" + +msgid "Start a new blog" +msgstr "" + +msgid "Admin" +msgstr "" + +msgid "It is you" +msgstr "" + +msgid "Edit your profile" +msgstr "" + +msgid "Open on {{ instance_url }}" +msgstr "" + +msgid "Follow" +msgstr "" + +msgid "Unfollow" +msgstr "" + +msgid "Recently reshared" +msgstr "" + msgid "One follower" msgid_plural "{{ count }} followers" msgstr[0] "" msgstr[1] "" + +msgid "Edit your account" +msgstr "" + +msgid "Your Profile" +msgstr "" + +msgid "Display Name" +msgstr "" + +msgid "Email" +msgstr "" + +msgid "Summary" +msgstr "" + +msgid "Update account" +msgstr "" + +msgid "{{ name }}'s followers" +msgstr "" + +msgid "Followers" +msgstr "" + +msgid "New Account" +msgstr "" + +msgid "Create an account" +msgstr "" + +msgid "Username" +msgstr "" + +msgid "Email" +msgstr "" + +msgid "Password" +msgstr "" + +msgid "Password confirmation" +msgstr "" + +msgid "Create account" +msgstr "" + +msgid "Plume" +msgstr "" + +msgid "Menu" +msgstr "" + +msgid "Dashboard" +msgstr "" + +msgid "Notifications" +msgstr "" + +msgid "My account" +msgstr "" + +msgid "Log Out" +msgstr "" + +msgid "Log In" +msgstr "" + +msgid "Register" +msgstr "" + diff --git a/src/main.rs b/src/main.rs index a1ffd40..69df18e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -69,8 +69,8 @@ fn main() { rocket::ignite() .mount("/", routes![ routes::blogs::details, - routes::blogs::activity_details, - routes::blogs::outbox, + routes::blogs::activity_details, + routes::blogs::outbox, routes::blogs::new, routes::blogs::new_auth, routes::blogs::create, @@ -111,7 +111,7 @@ fn main() { routes::user::details, routes::user::dashboard, routes::user::dashboard_auth, - routes::user::followers, + routes::user::followers, routes::user::edit, routes::user::edit_auth, routes::user::update, diff --git a/templates/base.html.tera b/templates/base.html.tera index 491ff4b..bdb1121 100644 --- a/templates/base.html.tera +++ b/templates/base.html.tera @@ -2,27 +2,27 @@ - {% block title %}{% endblock title %} ⋅ Plume + {% block title %}{% endblock title %} ⋅ {{ "Plume" | _ }}
- +
diff --git a/templates/blogs/details.html.tera b/templates/blogs/details.html.tera index f976a61..ed9994a 100644 --- a/templates/blogs/details.html.tera +++ b/templates/blogs/details.html.tera @@ -10,12 +10,12 @@

{{ blog.summary }}

-

Latest articles

+

{{ "Latest articles" | _ }}

{% if recents | length < 1 %} -

No posts to see here yet.

+

{{ "No posts to see here yet." | _ }}

{% endif %} {% if is_author %} - New article + {{ "New article" | _ }} {% endif %}
{% for article in recents %} diff --git a/templates/blogs/new.html.tera b/templates/blogs/new.html.tera index 5f44f92..0f89bce 100644 --- a/templates/blogs/new.html.tera +++ b/templates/blogs/new.html.tera @@ -1,15 +1,15 @@ {% extends "base" %} {% block title %} -New blog +{{ "New blog" | _ }} {% endblock title %} {% block content %} -

Create a blog

+

{{ "Create a blog" | _ }}

- + - +
-{% endblock content %} + | _ {% endblock content %} diff --git a/templates/comments/new.html.tera b/templates/comments/new.html.tera index 2dc1448..847eb2a 100644 --- a/templates/comments/new.html.tera +++ b/templates/comments/new.html.tera @@ -1,15 +1,15 @@ {% extends "base" %} {% block title %} -Comment "{{ post.title }}" +{{ "Comment \"{{ post }}\"" | _(post=post.title) }} {% endblock title %} {% block content %} -

Comment "{{ post.title }}"

+

{{ "Comment \"{{ post }}\"" | _(post=post.title) }}

- + - +
{% endblock content %} diff --git a/templates/errors/500.html.tera b/templates/errors/500.html.tera index f72d88a..0999868 100644 --- a/templates/errors/500.html.tera +++ b/templates/errors/500.html.tera @@ -1,6 +1,6 @@ {% extends "errors/base" %} {% block error %} -

Something broke on our side.

-

Sorry about that. If you think this is a bug, please report it.

+

{{ "Something broke on our side." | _ }}

+

{{ "Sorry about that. If you think this is a bug, please report it." | _ }}

{% endblock error %} diff --git a/templates/instance/configure.html.tera b/templates/instance/configure.html.tera index 4fd83a0..d7b3bfd 100644 --- a/templates/instance/configure.html.tera +++ b/templates/instance/configure.html.tera @@ -1,15 +1,15 @@ {% extends "base" %} {% block title %} -Configuration +{{ "Configuration" | _ }} {% endblock title %} {% block content %} -

Configure your instance

+

{{ "Configure your instance" | _ }}

- + - +
{% endblock content %} diff --git a/templates/instance/index.html.tera b/templates/instance/index.html.tera index b859fc8..0bd0734 100644 --- a/templates/instance/index.html.tera +++ b/templates/instance/index.html.tera @@ -8,7 +8,7 @@ {% block content %}

{{ "Welcome on {{ instance_name }}" | _(instance_name=instance.name) }}

-

Latest articles

+

{{ "Latest articles" }}

{% for article in recents %} {{ macros::post_card(article=article) }} diff --git a/templates/notifications/index.html.tera b/templates/notifications/index.html.tera index d25dedb..bbe7961 100644 --- a/templates/notifications/index.html.tera +++ b/templates/notifications/index.html.tera @@ -1,11 +1,11 @@ {% extends "base" %} {% block title %} -Notifications +{{ "Notifications" | _ }} {% endblock title %} {% block content %} -

Notifications

+

{{ "Notifications" | _ }}

{% for notification in notifications %}
diff --git a/templates/posts/details.html.tera b/templates/posts/details.html.tera index 8b4043c..f4f0a69 100644 --- a/templates/posts/details.html.tera +++ b/templates/posts/details.html.tera @@ -16,7 +16,7 @@ {% endif %}

- Written by {{ name }} + {{ "Written by {{ link_start }}{{ name }}{{ link_end }}" | _(link_start="", name=name, link_end="")}}{{ date | date(format="%B %e, %Y") }}

@@ -26,33 +26,33 @@ {% endblock content %} diff --git a/templates/posts/new.html.tera b/templates/posts/new.html.tera index f6d8ae0..4608e9d 100644 --- a/templates/posts/new.html.tera +++ b/templates/posts/new.html.tera @@ -1,21 +1,21 @@ {% extends "base" %} {% block title %} -New post +{{ "New post" | _ }} {% endblock title %} {% block content %} -

Create a post

+

{{ "Create a post" | _ }}

- + - + - + - +
{% endblock content %} diff --git a/templates/session/login.html.tera b/templates/session/login.html.tera index 35da145..eee9b40 100644 --- a/templates/session/login.html.tera +++ b/templates/session/login.html.tera @@ -1,21 +1,21 @@ {% extends "base" %} {% block title %} -Login +{{ "Login" | _ }} {% endblock title %} {% block content %} -

Login

+

{{ "Login" | _ }}

{% if message %}

{{ message }}

{% endif %}
- + - + - +
{% endblock content %} diff --git a/templates/users/dashboard.tera b/templates/users/dashboard.tera index 763684c..72fc568 100644 --- a/templates/users/dashboard.tera +++ b/templates/users/dashboard.tera @@ -2,18 +2,18 @@ {% import "macros" as macros %} {% block title %} -Dashboard +{{ "Dashboard" | _ }} {% endblock title %} {% block content %} -

Your Dashboard

+

{{ "Your Dashboard" | _ }}

-

Your Blogs

+

{{ "Your Blogs" | _ }}

{% if blogs | length < 1 %} -

You don't have any blog yet. Create your own, or ask to join one.

+

{{ "You don't have any blog yet. Create your own, or ask to join one." | _ }}

{% endif %} - Start a new blog + {{ "Start a new blog" | _ }}
{% for blog in blogs %}
diff --git a/templates/users/details.html.tera b/templates/users/details.html.tera index 524754d..e34f8a7 100644 --- a/templates/users/details.html.tera +++ b/templates/users/details.html.tera @@ -16,27 +16,27 @@

{{ name }} {% if user.is_admin %} - Admin + {{ "Admin" | _ }} {% endif %} {% if is_self %} - It is you + {{ "It is you" | _ }} {% endif %}

{% if is_self %} - Edit your profile + {{ "Edit your profile" | _ }} {% endif %} {% if is_remote %} - Open on {{ instance_url }} + {{ "Open on {{ instance_url }}" | _(instance_url=instance_url) }} {% endif %} {% if not is_self and account %} {% if follows %} - Follow + {{ "Follow" | _ }} {% else %} - Unfollow + {{ "Unfollow" | _ }} {% endif %} {% endif %}
@@ -50,7 +50,7 @@
{% if recents | length != 0 %} -

Latest articles

+

{{ "Latest articles" | _ }}

{% for article in recents %} {{ macros::post_card(article=article) }} @@ -59,7 +59,7 @@ {% endif %} {% if reshares | length != 0 %} -

Recently reshared

+

{{ "Recently reshared" | _ }}

{% for article in reshares %} {{ macros::post_card(article=article) }} diff --git a/templates/users/edit.html.tera b/templates/users/edit.html.tera index d1bf95a..d7725ae 100644 --- a/templates/users/edit.html.tera +++ b/templates/users/edit.html.tera @@ -1,24 +1,24 @@ {% extends "base" %} {% block title %} -Edit your account +{{ "Edit your account" | _ }} {% endblock title %} {% block content %} -

Your Profile

+

{{ "Your Profile" | _ }}

- + - + - + - +
{% endblock content %} diff --git a/templates/users/followers.html.tera b/templates/users/followers.html.tera index 827813c..6ce08eb 100644 --- a/templates/users/followers.html.tera +++ b/templates/users/followers.html.tera @@ -7,7 +7,7 @@ {% set name = user.username %} {% endif %} -{{ name }}'s Followers +{{ "{{ name }}'s followers" | _(name=name) }} {% endblock title %} {% block content %} @@ -15,28 +15,28 @@

{{ name }} {% if user.is_admin %} - Admin + {{ "Admin" | _ }} {% endif %} {% if is_self %} - It is you + {{ "It is you" | _ }} {% endif %}

{% if is_remote %} - Open on {{ instance_url }} + {{ "Open on {{ instance_url }}" | _(instance_url=instance_url) }} {% endif %} - {% if not is_self and account %} + {% if (not is_self) and account %} {% if follows %} - Follow + {{ "Follow" | _ }} {% else %} - Unfollow + {{ "Unfollow" | _ }} {% endif %} {% endif %}
-

Followers

+

{{ "Followers" | _ }}

{% for follower in followers %} {% if follower.display_name %} diff --git a/templates/users/new.html.tera b/templates/users/new.html.tera index e1cd748..607306d 100644 --- a/templates/users/new.html.tera +++ b/templates/users/new.html.tera @@ -1,24 +1,24 @@ {% extends "base" %} {% block title %} -New Account +{{ "New Account" | _ }} {% endblock title %} {% block content %} -

Create an account

+

{{ "Create an account" | _ }}

- + - + - + - + - +
{% endblock content %} From aaf60502ed4b08c532945c8216f5040ba6f3f38f Mon Sep 17 00:00:00 2001 From: Bat Date: Sun, 17 Jun 2018 16:34:25 +0100 Subject: [PATCH 32/39] Fix translations Remove dulicated messages Fix quotes in templates --- po/en.po | 201 +++++++++++++++++++++++++++++ po/en.po~ | 3 + po/fr.po | 202 ++++++++++++++++++++++++++++++ po/fr.po~ | 3 + po/plume.pot | 21 ---- templates/comments/new.html.tera | 4 +- templates/posts/details.html.tera | 2 +- 7 files changed, 412 insertions(+), 24 deletions(-) diff --git a/po/en.po b/po/en.po index 450ac62..0a57a9b 100644 --- a/po/en.po +++ b/po/en.po @@ -15,10 +15,211 @@ msgstr "" msgid "Latest articles" msgstr "" +msgid "No posts to see here yet." +msgstr "" + +msgid "New article" +msgstr "" + +msgid "New blog" +msgstr "" + +msgid "Create a blog" +msgstr "" + +msgid "Title" +msgstr "" + +msgid "Create blog" +msgstr "" + +msgid "Comment \"{{ post }}\"" +msgstr "" + +msgid "Content" +msgstr "" + +msgid "Submit comment" +msgstr "" + +msgid "Something broke on our side." +msgstr "" + +msgid "Sorry about that. If you think this is a bug, please report it." +msgstr "" + +msgid "Configuration" +msgstr "" + +msgid "Configure your instance" +msgstr "" + +msgid "Name" +msgstr "" + +msgid "Let's go!" +msgstr "" + msgid "Welcome on {{ instance_name }}" msgstr "Welcome on {{ instance_name }}" +msgid "Notifications" +msgstr "" + +msgid "Written by {{ link_start }}{{ name }}{{ link_end }}" +msgstr "" + +msgid "This article is under the {{ license }} license." +msgstr "" + +#, fuzzy +msgid "One like" +msgid_plural "{{ count }} likes" +msgstr[0] "One follower" +msgstr[1] "{{ count }} followers" + +msgid "I don't like this anymore" +msgstr "" + +msgid "Add yours" +msgstr "" + +msgid "One reshare" +msgid_plural "{{ count }} reshares" +msgstr[0] "" +msgstr[1] "" + +msgid "I don't want to reshare this anymore" +msgstr "" + +msgid "Reshare" +msgstr "" + +msgid "Comments" +msgstr "" + +msgid "Respond" +msgstr "" + +msgid "Comment" +msgstr "" + +msgid "New post" +msgstr "" + +msgid "Create a post" +msgstr "" + +msgid "Publish" +msgstr "" + +msgid "Login" +msgstr "" + +msgid "Username or email" +msgstr "" + +msgid "Password" +msgstr "" + +msgid "Dashboard" +msgstr "" + +msgid "Your Dashboard" +msgstr "" + +msgid "Your Blogs" +msgstr "" + +msgid "You don't have any blog yet. Create your own, or ask to join one." +msgstr "" + +msgid "Start a new blog" +msgstr "" + +msgid "Admin" +msgstr "" + +msgid "It is you" +msgstr "" + +msgid "Edit your profile" +msgstr "" + +#, fuzzy +msgid "Open on {{ instance_url }}" +msgstr "Welcome on {{ instance_name }}" + +msgid "Follow" +msgstr "" + +#, fuzzy +msgid "Unfollow" +msgstr "One follower" + +msgid "Recently reshared" +msgstr "" + msgid "One follower" msgid_plural "{{ count }} followers" msgstr[0] "One follower" msgstr[1] "{{ count }} followers" + +msgid "Edit your account" +msgstr "" + +msgid "Your Profile" +msgstr "" + +msgid "Display Name" +msgstr "" + +msgid "Email" +msgstr "" + +msgid "Summary" +msgstr "" + +msgid "Update account" +msgstr "" + +#, fuzzy +msgid "{{ name }}'s followers" +msgstr "One follower" + +#, fuzzy +msgid "Followers" +msgstr "One follower" + +msgid "New Account" +msgstr "" + +msgid "Create an account" +msgstr "" + +msgid "Username" +msgstr "" + +msgid "Password confirmation" +msgstr "" + +msgid "Create account" +msgstr "" + +msgid "Plume" +msgstr "" + +msgid "Menu" +msgstr "" + +msgid "My account" +msgstr "" + +msgid "Log Out" +msgstr "" + +msgid "Log In" +msgstr "" + +msgid "Register" +msgstr "" diff --git a/po/en.po~ b/po/en.po~ index bbe17a7..450ac62 100644 --- a/po/en.po~ +++ b/po/en.po~ @@ -12,6 +12,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" +msgid "Latest articles" +msgstr "" + msgid "Welcome on {{ instance_name }}" msgstr "Welcome on {{ instance_name }}" diff --git a/po/fr.po b/po/fr.po index e621c36..672f163 100644 --- a/po/fr.po +++ b/po/fr.po @@ -15,10 +15,212 @@ msgstr "" msgid "Latest articles" msgstr "Derniers articles" +msgid "No posts to see here yet." +msgstr "" + +#, fuzzy +msgid "New article" +msgstr "Derniers articles" + +msgid "New blog" +msgstr "" + +msgid "Create a blog" +msgstr "" + +msgid "Title" +msgstr "" + +msgid "Create blog" +msgstr "" + +msgid "Comment \"{{ post }}\"" +msgstr "" + +msgid "Content" +msgstr "" + +msgid "Submit comment" +msgstr "" + +msgid "Something broke on our side." +msgstr "" + +msgid "Sorry about that. If you think this is a bug, please report it." +msgstr "" + +msgid "Configuration" +msgstr "" + +msgid "Configure your instance" +msgstr "" + +msgid "Name" +msgstr "" + +msgid "Let's go!" +msgstr "" + msgid "Welcome on {{ instance_name }}" msgstr "Bienvenue sur {{ instance_name }}" +msgid "Notifications" +msgstr "" + +msgid "Written by {{ link_start }}{{ name }}{{ link_end }}" +msgstr "" + +msgid "This article is under the {{ license }} license." +msgstr "" + +#, fuzzy +msgid "One like" +msgid_plural "{{ count }} likes" +msgstr[0] "{{ count }} abonné⋅e" +msgstr[1] "{{ count }} abonné⋅e⋅s" + +msgid "I don't like this anymore" +msgstr "" + +msgid "Add yours" +msgstr "" + +msgid "One reshare" +msgid_plural "{{ count }} reshares" +msgstr[0] "" +msgstr[1] "" + +msgid "I don't want to reshare this anymore" +msgstr "" + +msgid "Reshare" +msgstr "" + +msgid "Comments" +msgstr "" + +msgid "Respond" +msgstr "" + +msgid "Comment" +msgstr "" + +msgid "New post" +msgstr "" + +msgid "Create a post" +msgstr "" + +msgid "Publish" +msgstr "" + +msgid "Login" +msgstr "" + +msgid "Username or email" +msgstr "" + +msgid "Password" +msgstr "" + +msgid "Dashboard" +msgstr "" + +msgid "Your Dashboard" +msgstr "" + +msgid "Your Blogs" +msgstr "" + +msgid "You don't have any blog yet. Create your own, or ask to join one." +msgstr "" + +msgid "Start a new blog" +msgstr "" + +msgid "Admin" +msgstr "" + +msgid "It is you" +msgstr "" + +msgid "Edit your profile" +msgstr "" + +#, fuzzy +msgid "Open on {{ instance_url }}" +msgstr "Bienvenue sur {{ instance_name }}" + +msgid "Follow" +msgstr "" + +#, fuzzy +msgid "Unfollow" +msgstr "{{ count }} abonné⋅e" + +msgid "Recently reshared" +msgstr "" + msgid "One follower" msgid_plural "{{ count }} followers" msgstr[0] "{{ count }} abonné⋅e" msgstr[1] "{{ count }} abonné⋅e⋅s" + +msgid "Edit your account" +msgstr "" + +msgid "Your Profile" +msgstr "" + +msgid "Display Name" +msgstr "" + +msgid "Email" +msgstr "" + +msgid "Summary" +msgstr "" + +msgid "Update account" +msgstr "" + +#, fuzzy +msgid "{{ name }}'s followers" +msgstr "{{ count }} abonné⋅e" + +#, fuzzy +msgid "Followers" +msgstr "{{ count }} abonné⋅e" + +msgid "New Account" +msgstr "" + +msgid "Create an account" +msgstr "" + +msgid "Username" +msgstr "" + +msgid "Password confirmation" +msgstr "" + +msgid "Create account" +msgstr "" + +msgid "Plume" +msgstr "" + +msgid "Menu" +msgstr "" + +msgid "My account" +msgstr "" + +msgid "Log Out" +msgstr "" + +msgid "Log In" +msgstr "" + +msgid "Register" +msgstr "" diff --git a/po/fr.po~ b/po/fr.po~ index ad0a929..e621c36 100644 --- a/po/fr.po~ +++ b/po/fr.po~ @@ -12,6 +12,9 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" +msgid "Latest articles" +msgstr "Derniers articles" + msgid "Welcome on {{ instance_name }}" msgstr "Bienvenue sur {{ instance_name }}" diff --git a/po/plume.pot b/po/plume.pot index 30bad45..7a6f0aa 100644 --- a/po/plume.pot +++ b/po/plume.pot @@ -109,15 +109,6 @@ msgstr "" msgid "Create a post" msgstr "" -msgid "Title" -msgstr "" - -msgid "Content" -msgstr "" - -msgid "License" -msgstr "" - msgid "Publish" msgstr "" @@ -204,12 +195,6 @@ msgstr "" msgid "Username" msgstr "" -msgid "Email" -msgstr "" - -msgid "Password" -msgstr "" - msgid "Password confirmation" msgstr "" @@ -222,12 +207,6 @@ msgstr "" msgid "Menu" msgstr "" -msgid "Dashboard" -msgstr "" - -msgid "Notifications" -msgstr "" - msgid "My account" msgstr "" diff --git a/templates/comments/new.html.tera b/templates/comments/new.html.tera index 847eb2a..a2cc273 100644 --- a/templates/comments/new.html.tera +++ b/templates/comments/new.html.tera @@ -1,11 +1,11 @@ {% extends "base" %} {% block title %} -{{ "Comment \"{{ post }}\"" | _(post=post.title) }} +{{ 'Comment "{{ post }}"' | _(post=post.title) }} {% endblock title %} {% block content %} -

{{ "Comment \"{{ post }}\"" | _(post=post.title) }}

+

{{ 'Comment "{{ post }}"' | _(post=post.title) }}

diff --git a/templates/posts/details.html.tera b/templates/posts/details.html.tera index f4f0a69..54c8b12 100644 --- a/templates/posts/details.html.tera +++ b/templates/posts/details.html.tera @@ -16,7 +16,7 @@ {% endif %}

- {{ "Written by {{ link_start }}{{ name }}{{ link_end }}" | _(link_start="", name=name, link_end="")}} + {{ "Written by {{ link_start }}{{ name }}{{ link_end }}" | _(link_start='', name=name, link_end="")}}{{ date | date(format="%B %e, %Y") }}

From b3bbcb564a1a44439cffdf4bc873bf4e01c5399b Mon Sep 17 00:00:00 2001 From: Bat Date: Sun, 17 Jun 2018 16:37:47 +0100 Subject: [PATCH 33/39] Ignore .po~ files --- po/en.po~ | 24 ------------------------ po/fr.po~ | 24 ------------------------ 2 files changed, 48 deletions(-) delete mode 100644 po/en.po~ delete mode 100644 po/fr.po~ diff --git a/po/en.po~ b/po/en.po~ deleted file mode 100644 index 450ac62..0000000 --- a/po/en.po~ +++ /dev/null @@ -1,24 +0,0 @@ -msgid "" -msgstr "" -"Project-Id-Version: plume\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-06-15 16:33-0700\n" -"PO-Revision-Date: 2018-06-15 16:33-0700\n" -"Last-Translator: Automatically generated\n" -"Language-Team: none\n" -"Language: en\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -msgid "Latest articles" -msgstr "" - -msgid "Welcome on {{ instance_name }}" -msgstr "Welcome on {{ instance_name }}" - -msgid "One follower" -msgid_plural "{{ count }} followers" -msgstr[0] "One follower" -msgstr[1] "{{ count }} followers" diff --git a/po/fr.po~ b/po/fr.po~ deleted file mode 100644 index e621c36..0000000 --- a/po/fr.po~ +++ /dev/null @@ -1,24 +0,0 @@ -msgid "" -msgstr "" -"Project-Id-Version: plume\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-06-15 16:33-0700\n" -"PO-Revision-Date: 2018-06-15 16:33-0700\n" -"Last-Translator: Automatically generated\n" -"Language-Team: none\n" -"Language: fr\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n > 1);\n" - -msgid "Latest articles" -msgstr "Derniers articles" - -msgid "Welcome on {{ instance_name }}" -msgstr "Bienvenue sur {{ instance_name }}" - -msgid "One follower" -msgid_plural "{{ count }} followers" -msgstr[0] "{{ count }} abonné⋅e" -msgstr[1] "{{ count }} abonné⋅e⋅s" From b950d8f60b76531a364bc24686c4e52400dc8fcc Mon Sep 17 00:00:00 2001 From: Bat Date: Sun, 17 Jun 2018 16:45:38 +0100 Subject: [PATCH 34/39] Translate to French --- po/fr.po | 126 ++++++++++++++++++++++++++----------------------------- 1 file changed, 60 insertions(+), 66 deletions(-) diff --git a/po/fr.po b/po/fr.po index 672f163..c24f4e0 100644 --- a/po/fr.po +++ b/po/fr.po @@ -16,150 +16,146 @@ msgid "Latest articles" msgstr "Derniers articles" msgid "No posts to see here yet." -msgstr "" +msgstr "Aucun article pour le moment" -#, fuzzy msgid "New article" msgstr "Derniers articles" msgid "New blog" -msgstr "" +msgstr "Nouveau blog" msgid "Create a blog" -msgstr "" +msgstr "Créer un blog" msgid "Title" -msgstr "" +msgstr "Titre" msgid "Create blog" -msgstr "" +msgstr "Créer le blog" msgid "Comment \"{{ post }}\"" -msgstr "" +msgstr "Commenter « {{ post }} »" msgid "Content" -msgstr "" +msgstr "Contenu" msgid "Submit comment" -msgstr "" +msgstr "Envoyer le commentaire" msgid "Something broke on our side." -msgstr "" +msgstr "Nous avons cassé quelque chose" msgid "Sorry about that. If you think this is a bug, please report it." -msgstr "" +msgstr "Nous sommes désolé⋅e⋅s. Si vous pensez que c'est un bogue, merci de le rapporter." msgid "Configuration" -msgstr "" +msgstr "Configuration" msgid "Configure your instance" -msgstr "" +msgstr "Configurez votre instance" msgid "Name" -msgstr "" +msgstr "Nom" msgid "Let's go!" -msgstr "" +msgstr "C'est parti !" msgid "Welcome on {{ instance_name }}" msgstr "Bienvenue sur {{ instance_name }}" msgid "Notifications" -msgstr "" +msgstr "Notifications" msgid "Written by {{ link_start }}{{ name }}{{ link_end }}" -msgstr "" +msgstr "Écrit par {{ link_start}}{{ name }}{{ link_end }}" msgid "This article is under the {{ license }} license." -msgstr "" +msgstr "Cet article est placé sous la licence {{ license }}" -#, fuzzy msgid "One like" msgid_plural "{{ count }} likes" msgstr[0] "{{ count }} abonné⋅e" msgstr[1] "{{ count }} abonné⋅e⋅s" msgid "I don't like this anymore" -msgstr "" +msgstr "Je n'aime plus" msgid "Add yours" -msgstr "" +msgstr "Ajoutez le votre" msgid "One reshare" msgid_plural "{{ count }} reshares" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "{{ count }} repartage" +msgstr[1] "{{ count }} repartages" msgid "I don't want to reshare this anymore" -msgstr "" +msgstr "Je ne veux plus repartager" msgid "Reshare" -msgstr "" +msgstr "Repartagez" msgid "Comments" -msgstr "" +msgstr "Commentaires" msgid "Respond" -msgstr "" +msgstr "Répondre" msgid "Comment" -msgstr "" +msgstr "Commentez" msgid "New post" -msgstr "" +msgstr "Nouvel article" msgid "Create a post" -msgstr "" +msgstr "Créer un article" msgid "Publish" -msgstr "" +msgstr "Publier" msgid "Login" -msgstr "" +msgstr "Se connecter" msgid "Username or email" -msgstr "" +msgstr "Nom d'utilisateur ou email" msgid "Password" -msgstr "" +msgstr "Mot de passe" msgid "Dashboard" -msgstr "" +msgstr "Tableau de bord" msgid "Your Dashboard" -msgstr "" +msgstr "Votre tableau de bord" msgid "Your Blogs" -msgstr "" +msgstr "Vos blogs" msgid "You don't have any blog yet. Create your own, or ask to join one." -msgstr "" +msgstr "Vous n'avez pas encore de blog. Créez le votre, ou demandez à en rejoindre un." msgid "Start a new blog" -msgstr "" +msgstr "Commencez un nouveau blog" msgid "Admin" -msgstr "" +msgstr "Administrateur" msgid "It is you" -msgstr "" +msgstr "C'est vous" msgid "Edit your profile" -msgstr "" +msgstr "Éditez votre profil" -#, fuzzy msgid "Open on {{ instance_url }}" msgstr "Bienvenue sur {{ instance_name }}" msgid "Follow" -msgstr "" +msgstr "S'abonner" -#, fuzzy msgid "Unfollow" -msgstr "{{ count }} abonné⋅e" +msgstr "Se désabonner" msgid "Recently reshared" -msgstr "" +msgstr "Récemment repartagés" msgid "One follower" msgid_plural "{{ count }} followers" @@ -167,60 +163,58 @@ msgstr[0] "{{ count }} abonné⋅e" msgstr[1] "{{ count }} abonné⋅e⋅s" msgid "Edit your account" -msgstr "" +msgstr "Éditer votre compte" msgid "Your Profile" -msgstr "" +msgstr "Votre profil" msgid "Display Name" -msgstr "" +msgstr "Nom affiché" msgid "Email" -msgstr "" +msgstr "Email" msgid "Summary" -msgstr "" +msgstr "Description" msgid "Update account" -msgstr "" +msgstr "Mettre à jour mes informations" -#, fuzzy msgid "{{ name }}'s followers" msgstr "{{ count }} abonné⋅e" -#, fuzzy msgid "Followers" msgstr "{{ count }} abonné⋅e" msgid "New Account" -msgstr "" +msgstr "Nouveau compte" msgid "Create an account" -msgstr "" +msgstr "Créer un compte" msgid "Username" -msgstr "" +msgstr "Nom d'utilisateur" msgid "Password confirmation" -msgstr "" +msgstr "Confirmation du mot de passe" msgid "Create account" -msgstr "" +msgstr "Créer mon compte" msgid "Plume" -msgstr "" +msgstr "Plume" msgid "Menu" -msgstr "" +msgstr "Menu" msgid "My account" -msgstr "" +msgstr "Mon compte" msgid "Log Out" -msgstr "" +msgstr "Se déconnecter" msgid "Log In" -msgstr "" +msgstr "Se connecter" msgid "Register" -msgstr "" +msgstr "S'inscrire" From ab841f826dba145d440123e9a99ab16576d49f5d Mon Sep 17 00:00:00 2001 From: Bat Date: Sun, 17 Jun 2018 16:46:53 +0100 Subject: [PATCH 35/39] Forgot to make a string translatable on the homepage --- templates/instance/index.html.tera | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/instance/index.html.tera b/templates/instance/index.html.tera index 0bd0734..49b0958 100644 --- a/templates/instance/index.html.tera +++ b/templates/instance/index.html.tera @@ -8,7 +8,7 @@ {% block content %}

{{ "Welcome on {{ instance_name }}" | _(instance_name=instance.name) }}

-

{{ "Latest articles" }}

+

{{ "Latest articles" | _ }}

{% for article in recents %} {{ macros::post_card(article=article) }} From 152eafc06fd6210ae9916b272cc4edfc264a38e7 Mon Sep 17 00:00:00 2001 From: Bat Date: Sun, 17 Jun 2018 17:06:47 +0100 Subject: [PATCH 36/39] Translate Rust strings --- .gitignore | 1 + po/en.po | 30 ++++++++++++++++++++++++++++++ po/fr.po | 38 ++++++++++++++++++++++++++++++++++++-- po/plume.pot | 30 ++++++++++++++++++++++++++++++ src/routes/instance.rs | 3 ++- src/routes/session.rs | 5 +++-- src/utils.rs | 3 ++- 7 files changed, 104 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 32bc127..a4c7fe2 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ rls **/*.rs.bk rls translations +po/*.po~ diff --git a/po/en.po b/po/en.po index 0a57a9b..d65de4b 100644 --- a/po/en.po +++ b/po/en.po @@ -223,3 +223,33 @@ msgstr "" msgid "Register" msgstr "" + +msgid "You need to be logged in order to create a new blog" +msgstr "" + +msgid "You need to be logged in order to post a comment" +msgstr "" + +msgid "You need to be logged in order to like a post" +msgstr "" + +msgid "You need to be logged in order to see your notifications" +msgstr "" + +msgid "You need to be logged in order to write a new post" +msgstr "" + +msgid "You need to be logged in order to reshare a post" +msgstr "" + +msgid "Invalid username or password" +msgstr "" + +msgid "You need to be logged in order to access your dashboard" +msgstr "" + +msgid "You need to be logged in order to follow someone" +msgstr "" + +msgid "You need to be logged in order to edit your profile" +msgstr "" diff --git a/po/fr.po b/po/fr.po index c24f4e0..a4e6d81 100644 --- a/po/fr.po +++ b/po/fr.po @@ -46,7 +46,9 @@ msgid "Something broke on our side." msgstr "Nous avons cassé quelque chose" msgid "Sorry about that. If you think this is a bug, please report it." -msgstr "Nous sommes désolé⋅e⋅s. Si vous pensez que c'est un bogue, merci de le rapporter." +msgstr "" +"Nous sommes désolé⋅e⋅s. Si vous pensez que c'est un bogue, merci de le " +"rapporter." msgid "Configuration" msgstr "Configuration" @@ -131,7 +133,9 @@ msgid "Your Blogs" msgstr "Vos blogs" msgid "You don't have any blog yet. Create your own, or ask to join one." -msgstr "Vous n'avez pas encore de blog. Créez le votre, ou demandez à en rejoindre un." +msgstr "" +"Vous n'avez pas encore de blog. Créez le votre, ou demandez à en rejoindre " +"un." msgid "Start a new blog" msgstr "Commencez un nouveau blog" @@ -218,3 +222,33 @@ msgstr "Se connecter" msgid "Register" msgstr "S'inscrire" + +msgid "You need to be logged in order to create a new blog" +msgstr "" + +msgid "You need to be logged in order to post a comment" +msgstr "" + +msgid "You need to be logged in order to like a post" +msgstr "" + +msgid "You need to be logged in order to see your notifications" +msgstr "" + +msgid "You need to be logged in order to write a new post" +msgstr "" + +msgid "You need to be logged in order to reshare a post" +msgstr "" + +msgid "Invalid username or password" +msgstr "" + +msgid "You need to be logged in order to access your dashboard" +msgstr "" + +msgid "You need to be logged in order to follow someone" +msgstr "" + +msgid "You need to be logged in order to edit your profile" +msgstr "" diff --git a/po/plume.pot b/po/plume.pot index 7a6f0aa..7fc8caf 100644 --- a/po/plume.pot +++ b/po/plume.pot @@ -219,3 +219,33 @@ msgstr "" msgid "Register" msgstr "" +msgid "You need to be logged in order to create a new blog" +msgstr "" + +msgid "You need to be logged in order to post a comment" +msgstr "" + +msgid "You need to be logged in order to like a post" +msgstr "" + +msgid "You need to be logged in order to see your notifications" +msgstr "" + +msgid "You need to be logged in order to write a new post" +msgstr "" + +msgid "You need to be logged in order to reshare a post" +msgstr "" + +msgid "Invalid username or password" +msgstr "" + +msgid "You need to be logged in order to access your dashboard" +msgstr "" + +msgid "You need to be logged in order to follow someone" +msgstr "" + +msgid "You need to be logged in order to edit your profile" +msgstr "" + diff --git a/src/routes/instance.rs b/src/routes/instance.rs index e8fa9c5..f366a39 100644 --- a/src/routes/instance.rs +++ b/src/routes/instance.rs @@ -1,3 +1,4 @@ +use gettextrs::gettext; use rocket::{request::Form, response::Redirect}; use rocket_contrib::{Json, Template}; use serde_json; @@ -38,7 +39,7 @@ fn index(conn: DbConn, user: Option) -> Template { } None => { Template::render("errors/500", json!({ - "error_message": "You need to configure your instance before using it." + "error_message": gettext("You need to configure your instance before using it.".to_string()) })) } } diff --git a/src/routes/session.rs b/src/routes/session.rs index 2b72879..057e63b 100644 --- a/src/routes/session.rs +++ b/src/routes/session.rs @@ -1,3 +1,4 @@ +use gettextrs::gettext; use rocket::{ http::{Cookie, Cookies, uri::Uri}, response::{Redirect, status::NotFound}, @@ -42,7 +43,7 @@ fn create(conn: DbConn, data: Form, flash: Option, mut Some(usr) => Ok(usr), None => match User::find_local(&*conn, form.email_or_name.to_string()) { Some(usr) => Ok(usr), - None => Err("Invalid username or password") + None => Err(gettext("Invalid username or password")) } }; match user { @@ -54,7 +55,7 @@ fn create(conn: DbConn, data: Form, flash: Option, mut .unwrap_or("/".to_owned())) )) } else { - Err(NotFound(String::from("Invalid username or password"))) + Err(NotFound(gettext("Invalid username or password"))) } }, Err(e) => Err(NotFound(String::from(e))) diff --git a/src/utils.rs b/src/utils.rs index 5adac6d..e9463e1 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,3 +1,4 @@ +use gettextrs::gettext; use heck::CamelCase; use rocket::{ http::uri::Uri, @@ -15,5 +16,5 @@ pub fn make_actor_id(name: String) -> String { } pub fn requires_login(message: &str, url: &str) -> Flash { - Flash::new(Redirect::to(Uri::new(format!("/login?m={}", message))), "callback", url) + Flash::new(Redirect::to(Uri::new(format!("/login?m={}", gettext(message.to_string())))), "callback", url) } From e8225cb0bea79fc6ef408fa290ffd03fc0def8e4 Mon Sep 17 00:00:00 2001 From: Bat Date: Sun, 17 Jun 2018 17:09:28 +0100 Subject: [PATCH 37/39] Update french translation --- po/fr.po | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/po/fr.po b/po/fr.po index a4e6d81..9d3c480 100644 --- a/po/fr.po +++ b/po/fr.po @@ -224,31 +224,31 @@ msgid "Register" msgstr "S'inscrire" msgid "You need to be logged in order to create a new blog" -msgstr "" +msgstr "Vous devez vous connecter pour créer un nouveau blog" msgid "You need to be logged in order to post a comment" -msgstr "" +msgstr "Vous devez vous connecter pour commenter" msgid "You need to be logged in order to like a post" -msgstr "" +msgstr "Vous devez vous connecter pour aimer un article" msgid "You need to be logged in order to see your notifications" -msgstr "" +msgstr "Vous devez vous connecter pour voir vos notifications" msgid "You need to be logged in order to write a new post" -msgstr "" +msgstr "Vous devez vous connecter pour écrire un article" msgid "You need to be logged in order to reshare a post" -msgstr "" +msgstr "Vous devez vous connecter pour repartager un article" msgid "Invalid username or password" -msgstr "" +msgstr "Nom d'utilisateur ou mot de passe invalide" msgid "You need to be logged in order to access your dashboard" -msgstr "" +msgstr "Vous devez vous connecter pour accéder à votre tableau de bord" msgid "You need to be logged in order to follow someone" -msgstr "" +msgstr "Vous devez vous connecter pour suivre quelqu'un" msgid "You need to be logged in order to edit your profile" -msgstr "" +msgstr "Vous devez vous connecter pour modifier votre profil" From aa0ce32ec1450b32c5875bce0b74378dcd27094d Mon Sep 17 00:00:00 2001 From: Bat Date: Sun, 17 Jun 2018 17:19:39 +0100 Subject: [PATCH 38/39] Fix a few problemns with translations --- po/en.po | 2 +- po/fr.po | 12 ++++++------ po/plume.pot | 2 +- templates/posts/details.html.tera | 9 ++++++++- 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/po/en.po b/po/en.po index d65de4b..2634ce4 100644 --- a/po/en.po +++ b/po/en.po @@ -66,7 +66,7 @@ msgstr "Welcome on {{ instance_name }}" msgid "Notifications" msgstr "" -msgid "Written by {{ link_start }}{{ name }}{{ link_end }}" +msgid "Written by {{ link_1 }}{{ url }}{{ link_2 }}{{ name }}{{ link_3 }}" msgstr "" msgid "This article is under the {{ license }} license." diff --git a/po/fr.po b/po/fr.po index 9d3c480..55a2a72 100644 --- a/po/fr.po +++ b/po/fr.po @@ -68,22 +68,22 @@ msgstr "Bienvenue sur {{ instance_name }}" msgid "Notifications" msgstr "Notifications" -msgid "Written by {{ link_start }}{{ name }}{{ link_end }}" -msgstr "Écrit par {{ link_start}}{{ name }}{{ link_end }}" +msgid "Written by {{ link_1 }}{{ url }}{{ link_2 }}{{ name }}{{ link_3 }}" +msgstr "Écrit par {{ link_1 }}{{ url }}{{ link_2 }}{{ name }}{{ link_3 }}" msgid "This article is under the {{ license }} license." msgstr "Cet article est placé sous la licence {{ license }}" msgid "One like" msgid_plural "{{ count }} likes" -msgstr[0] "{{ count }} abonné⋅e" -msgstr[1] "{{ count }} abonné⋅e⋅s" +msgstr[0] "{{ count }} personne aime cet article" +msgstr[1] "{{ count }} personnes aiment cet article" msgid "I don't like this anymore" msgstr "Je n'aime plus" msgid "Add yours" -msgstr "Ajoutez le votre" +msgstr "J'aime" msgid "One reshare" msgid_plural "{{ count }} reshares" @@ -159,7 +159,7 @@ msgid "Unfollow" msgstr "Se désabonner" msgid "Recently reshared" -msgstr "Récemment repartagés" +msgstr "Récemment repartagé" msgid "One follower" msgid_plural "{{ count }} followers" diff --git a/po/plume.pot b/po/plume.pot index 7fc8caf..7d698ed 100644 --- a/po/plume.pot +++ b/po/plume.pot @@ -66,7 +66,7 @@ msgstr "" msgid "Notifications" msgstr "" -msgid "Written by {{ link_start }}{{ name }}{{ link_end }}" +msgid "Written by {{ link_1 }}{{ url }}{{ link_2 }}{{ name }}{{ link_3 }}" msgstr "" msgid "This article is under the {{ license }} license." diff --git a/templates/posts/details.html.tera b/templates/posts/details.html.tera index 54c8b12..ae173b9 100644 --- a/templates/posts/details.html.tera +++ b/templates/posts/details.html.tera @@ -16,7 +16,14 @@ {% endif %}

- {{ "Written by {{ link_start }}{{ name }}{{ link_end }}" | _(link_start='', name=name, link_end="")}} + {{ "Written by {{ link_1 }}{{ url }}{{ link_2 }}{{ name }}{{ link_3 }}" | _( + link_1='', + name=name, + link_3="" + ) + }}{{ date | date(format="%B %e, %Y") }}

From 0b9515645c714f90da0494130e37410cdd8b3626 Mon Sep 17 00:00:00 2001 From: Bat Date: Sun, 17 Jun 2018 18:48:22 +0100 Subject: [PATCH 39/39] De-duplicate some parts of the users templates --- src/routes/user.rs | 3 ++- templates/users/details.html.tera | 33 +---------------------------- templates/users/followers.html.tera | 25 +--------------------- templates/users/header.tera | 32 ++++++++++++++++++++++++++++ 4 files changed, 36 insertions(+), 57 deletions(-) create mode 100644 templates/users/header.tera diff --git a/src/routes/user.rs b/src/routes/user.rs index 8e6e5cd..2bc25ec 100644 --- a/src/routes/user.rs +++ b/src/routes/user.rs @@ -129,7 +129,8 @@ fn followers(name: String, conn: DbConn, account: Option) -> Template { json }).collect::>(), "account": account, - "is_self": account.map(|a| a.id == user_id).unwrap_or(false) + "is_self": account.map(|a| a.id == user_id).unwrap_or(false), + "n_followers": user.get_followers(&*conn).len() })) } diff --git a/templates/users/details.html.tera b/templates/users/details.html.tera index e34f8a7..f129135 100644 --- a/templates/users/details.html.tera +++ b/templates/users/details.html.tera @@ -12,38 +12,7 @@ {% endblock title %} {% block content %} -
-

- {{ name }} - {% if user.is_admin %} - {{ "Admin" | _ }} - {% endif %} - - {% if is_self %} - {{ "It is you" | _ }} - {% endif %} -

- - {% if is_self %} - {{ "Edit your profile" | _ }} - {% endif %} - - {% if is_remote %} - {{ "Open on {{ instance_url }}" | _(instance_url=instance_url) }} - {% endif %} - - {% if not is_self and account %} - {% if follows %} - {{ "Follow" | _ }} - {% else %} - {{ "Unfollow" | _ }} - {% endif %} - {% endif %} -
- - + {% include "users/header" %}
{{ user.summary | safe }} diff --git a/templates/users/followers.html.tera b/templates/users/followers.html.tera index 6ce08eb..2b025b3 100644 --- a/templates/users/followers.html.tera +++ b/templates/users/followers.html.tera @@ -11,30 +11,7 @@ {% endblock title %} {% block content %} -
-

- {{ name }} - {% if user.is_admin %} - {{ "Admin" | _ }} - {% endif %} - - {% if is_self %} - {{ "It is you" | _ }} - {% endif %} -

- - {% if is_remote %} - {{ "Open on {{ instance_url }}" | _(instance_url=instance_url) }} - {% endif %} - - {% if (not is_self) and account %} - {% if follows %} - {{ "Follow" | _ }} - {% else %} - {{ "Unfollow" | _ }} - {% endif %} - {% endif %} -
+ {% include "users/header" %}

{{ "Followers" | _ }}

diff --git a/templates/users/header.tera b/templates/users/header.tera new file mode 100644 index 0000000..dc69599 --- /dev/null +++ b/templates/users/header.tera @@ -0,0 +1,32 @@ +
+

+ {{ name }} + {% if user.is_admin %} + {{ "Admin" | _ }} + {% endif %} + + {% if is_self %} + {{ "It is you" | _ }} + {% endif %} +

+ + {% if is_self %} + {{ "Edit your profile" | _ }} + {% endif %} + + {% if is_remote %} + {{ "Open on {{ instance_url }}" | _(instance_url=instance_url) }} + {% endif %} + + {% if not is_self and account %} + {% if follows %} + {{ "Follow" | _ }} + {% else %} + {{ "Unfollow" | _ }} + {% endif %} + {% endif %} +
+ +