aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar cel 🌸 <cel@blos.sm>2024-02-10 06:54:25 +0000
committerLibravatar cel 🌸 <cel@blos.sm>2024-02-10 06:54:25 +0000
commit88fa09755ff31b39b0454f0da58bc41a90263e89 (patch)
tree31e91e27324366bbea20b4af2a17ec10f73322e9
parent205a71efa9f60938c86d57bba07f6d33b21790a2 (diff)
downloadblossom-88fa09755ff31b39b0454f0da58bc41a90263e89.tar.gz
blossom-88fa09755ff31b39b0454f0da58bc41a90263e89.tar.bz2
blossom-88fa09755ff31b39b0454f0da58bc41a90263e89.zip
add initial localisation
-rw-r--r--Cargo.lock36
-rw-r--r--Cargo.toml2
-rw-r--r--resources/en/base.ftl9
-rw-r--r--resources/en/contact.ftl9
-rw-r--r--resources/en/home.ftl13
-rw-r--r--src/error.rs1
-rw-r--r--src/main.rs54
-rw-r--r--src/templates.rs22
-rw-r--r--templates/base.html2
-rw-r--r--templates/blogpost-panel.html5
-rw-r--r--templates/contact.html21
-rw-r--r--templates/filtertags.html2
-rw-r--r--templates/home.html17
-rw-r--r--templates/latestposts.html7
-rw-r--r--templates/poem-panel.html5
-rw-r--r--templates/random-poem.html5
16 files changed, 163 insertions, 47 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 3fff1c8..2c56a4a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1455,6 +1455,9 @@ checksum = "38a712ff53e257d60d3d22936c51cafa606552129d55539c8a400de44eff676d"
dependencies = [
"async-trait",
"bytes",
+ "fluent",
+ "fluent-langneg",
+ "fluent-syntax",
"futures-util",
"headers",
"hex",
@@ -1462,6 +1465,7 @@ dependencies = [
"http-body-util",
"hyper 1.1.0",
"hyper-util",
+ "intl-memoizer",
"mime",
"mime_guess",
"nix",
@@ -1481,6 +1485,7 @@ dependencies = [
"tokio",
"tokio-util",
"tracing",
+ "unic-langid",
"wildmatch",
]
@@ -1519,6 +1524,12 @@ dependencies = [
]
[[package]]
+name = "proc-macro-hack"
+version = "0.5.20+deprecated"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
+
+[[package]]
name = "proc-macro2"
version = "1.0.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2438,6 +2449,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "238722e6d794ed130f91f4ea33e01fcff4f188d92337a21297892521c72df516"
dependencies = [
"unic-langid-impl",
+ "unic-langid-macros",
]
[[package]]
@@ -2450,6 +2462,30 @@ dependencies = [
]
[[package]]
+name = "unic-langid-macros"
+version = "0.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c854cefb82ff2816410ce606acbad1b3af065140907b29be9229040752b83ec"
+dependencies = [
+ "proc-macro-hack",
+ "tinystr",
+ "unic-langid-impl",
+ "unic-langid-macros-impl",
+]
+
+[[package]]
+name = "unic-langid-macros-impl"
+version = "0.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fea2a4c80deb4fb3ca51f66b5e2dd91e3642bbce52234bcf22e41668281208e4"
+dependencies = [
+ "proc-macro-hack",
+ "quote 1.0.35",
+ "syn 2.0.48",
+ "unic-langid-impl",
+]
+
+[[package]]
name = "unicase"
version = "2.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index 3147ef5..7be8c9d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -22,7 +22,7 @@ toml = "0.7.4"
tokio-stream = { version = "0.1.14", features = ["fs"] }
atom_syndication = "0.12.1"
fluent = "0.16.0"
-poem = { version = "2.0.0", features = ["embed"] }
+poem = { version = "2.0.0", features = ["embed", "i18n"] }
askama = { git = "https://bunny.garden/forks/askama.git", features = ["with-poem"] }
askama_poem = { git = "https://bunny.garden/forks/askama.git" }
rust-embed = "8.2.0"
diff --git a/resources/en/base.ftl b/resources/en/base.ftl
new file mode 100644
index 0000000..9285cd2
--- /dev/null
+++ b/resources/en/base.ftl
@@ -0,0 +1,9 @@
+title = celeste's hard drive
+title-blog = celeste's blog
+title-poetry = celeste's poetry
+branch = cherry blossom branch
+latest-blogposts = latest blogposts
+random-poem = random poem
+filter-by-tags = filter by tags
+permalink = permalink
+untitled = untitled
diff --git a/resources/en/contact.ftl b/resources/en/contact.ftl
new file mode 100644
index 0000000..4b9f2d2
--- /dev/null
+++ b/resources/en/contact.ftl
@@ -0,0 +1,9 @@
+title-contact = celeste's contact details
+name = celeste 🌸
+pronouns = pronouns: <span class="p-x-pronoun-nominative">she</span>/<span class="p-x-pronoun-accusative">her</span>
+email = email
+jabber = jabber
+scrobbles = scrobbles
+bandcamp-fan = bandcamp fan
+languages = languages (in rough skill order): english, portuguese, french, japanese, german, chinese, latin, toki pona, korean
+programming = programming: rust, erlang, go, haskell, webdev, lisp
diff --git a/resources/en/home.ftl b/resources/en/home.ftl
new file mode 100644
index 0000000..24702ee
--- /dev/null
+++ b/resources/en/home.ftl
@@ -0,0 +1,13 @@
+latest-update = latest update: added poetry!
+now-playing = now playing
+
+# welcome panel
+welcome =
+ <h2>hallo i am celeste welcome 2 my site 🌟</h2>
+ <p>this is where i do the posting</p>
+ <p>i wish u a wonderful day</p>
+ <br>
+ <img src="/static/quinntyping.png">
+ <p>perpetually under construction</p>
+ <img style="border: 0;" src="/static/barraconstruction.gif">
+
diff --git a/src/error.rs b/src/error.rs
index 611ce79..adaf77f 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -56,6 +56,7 @@ impl ResponseError for BlossomError {
Self: std::error::Error + Send + Sync + 'static,
{
templates::Error {
+ title: self.to_string(),
status: self.status(),
message: self.to_string(),
}
diff --git a/src/main.rs b/src/main.rs
index 2f1a00b..de7bc73 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -15,6 +15,7 @@ mod utils;
use std::{collections::HashSet, time::Duration};
use poem::http::StatusCode;
+use poem::i18n::{I18NResources, Locale};
use poem::{
endpoint::EmbeddedFilesEndpoint,
get, handler,
@@ -44,7 +45,7 @@ type Result<T> = std::result::Result<T, BlossomError>;
struct Static;
#[handler]
-async fn home(Data(reqwest): Data<&reqwest::Client>) -> templates::Home {
+async fn home(Data(reqwest): Data<&reqwest::Client>, locale: Locale) -> templates::Home {
let listenbrainz_client = listenbrainz::raw::Client::new();
let (live, listenbrainz, blogposts, poems) = tokio::join!(
live::get_live_status(reqwest),
@@ -59,20 +60,27 @@ async fn home(Data(reqwest): Data<&reqwest::Client>) -> templates::Home {
let poems = poems.unwrap_or_default();
let poem = poems.choose(&mut rand::thread_rng()).cloned();
templates::Home {
+ title: locale.text("title").unwrap(),
is_live,
listenbrainz,
blogposts,
poem,
+ locale,
}
}
// #[get("/blog/<blogpost>")]
#[handler]
-async fn blogpost(Path(blogpost): Path<String>) -> Result<templates::Blogpost> {
+async fn blogpost(Path(blogpost): Path<String>, locale: Locale) -> Result<templates::Blogpost> {
let blogpost = Blogpost::get_article(&blogpost).await?;
Ok(templates::Blogpost {
+ title: blogpost
+ .subject()
+ .unwrap_or(locale.text("untitled").unwrap().as_str())
+ .to_owned(),
blogpost,
filter_tags: HashSet::new(),
+ locale,
})
}
@@ -83,7 +91,10 @@ struct FilterTags {
// #[get("/blog?<filter>")]
#[handler]
-async fn get_blog(filter_tags: Option<Query<FilterTags>>) -> Result<templates::Blog> {
+async fn get_blog(
+ filter_tags: Option<Query<FilterTags>>,
+ locale: Locale,
+) -> Result<templates::Blog> {
let mut blogposts = Blogpost::get_articles().await?;
let tags: Vec<String> = posts::Post::get_tags(&blogposts)
.into_iter()
@@ -95,12 +106,15 @@ async fn get_blog(filter_tags: Option<Query<FilterTags>>) -> Result<templates::B
blogposts = posts::Post::filter_by_tags(blogposts, &filter_hashset);
}
Ok(templates::Blog {
+ title: locale.text("title-blog").unwrap(),
blogposts,
tags,
filter_tags: filter_hashset,
+ locale,
})
}
+// TODO: localize feed
#[handler]
async fn feed() -> Result<Response> {
let blogposts: Vec<Box<dyn Post + Send + Sync>> = Blogpost::get_articles()
@@ -132,8 +146,11 @@ async fn feed() -> Result<Response> {
}
#[handler]
-async fn contact() -> templates::Contact {
- templates::Contact
+async fn contact(locale: Locale) -> templates::Contact {
+ templates::Contact {
+ title: locale.text("title-contact").unwrap(),
+ locale,
+ }
}
#[handler]
@@ -142,21 +159,34 @@ async fn plants() -> Result<()> {
}
#[handler]
-async fn get_poem(Path(poem): Path<String>) -> Result<templates::Poem> {
+async fn get_poem(Path(poem): Path<String>, locale: Locale) -> Result<templates::Poem> {
let poem = Poem::get_article(&poem).await?;
- Ok(templates::Poem { poem, jiggle: 4 })
+ Ok(templates::Poem {
+ title: (&poem.title)
+ .clone()
+ .unwrap_or(locale.text("untitled").unwrap()),
+ poem,
+ jiggle: 4,
+ locale,
+ })
}
#[handler]
-async fn get_poetry() -> Result<templates::Poetry> {
+async fn get_poetry(locale: Locale) -> Result<templates::Poetry> {
let mut poems = Poem::get_articles().await?;
poems.sort_by_key(|poem| poem.created_at);
poems.reverse();
- Ok(templates::Poetry { poems, jiggle: 16 })
+ Ok(templates::Poetry {
+ title: locale.text("title-poetry").unwrap(),
+ poems,
+ jiggle: 16,
+ locale,
+ })
}
async fn custom_error(err: poem::Error) -> impl IntoResponse {
templates::Error {
+ title: err.to_string(),
status: err.status(),
message: err.to_string(),
}
@@ -171,6 +201,11 @@ async fn main() -> std::result::Result<(), std::io::Error> {
// let mut skinny_data = mastodon_async::Data::default();
// skinny_data.base = Cow::from("https://skinnyver.se");
+ let resources = I18NResources::builder()
+ .add_path("./resources")
+ .build()
+ .unwrap();
+
let blossom = Route::new()
.at("/", get(home))
.at("/blog", get(get_blog))
@@ -182,6 +217,7 @@ async fn main() -> std::result::Result<(), std::io::Error> {
.at("/plants", get(plants))
.nest("/static/", EmbeddedFilesEndpoint::<Static>::new())
.catch_all_error(custom_error)
+ .data(resources)
.with(Tracing)
.with(AddData::new(
reqwest::Client::builder()
diff --git a/src/templates.rs b/src/templates.rs
index 4bcb64b..2ab9c41 100644
--- a/src/templates.rs
+++ b/src/templates.rs
@@ -2,6 +2,7 @@ use std::collections::HashSet;
use askama::Template;
use poem::http::StatusCode;
+use poem::i18n::Locale;
use rand::{thread_rng, Rng};
use crate::poetry;
@@ -17,55 +18,66 @@ mod filters {
}
#[derive(Template)]
-#[template(path = "base.html")]
-struct Base;
-
-#[derive(Template)]
#[template(path = "home.html")]
pub struct Home {
+ pub title: String,
pub is_live: bool,
pub listenbrainz: NowPlayingData,
pub blogposts: Vec<blog::Blogpost>,
pub poem: Option<poetry::Poem>,
+ pub locale: Locale,
}
#[derive(Template)]
#[template(path = "blogpost.html")]
pub struct Blogpost {
+ pub title: String,
pub blogpost: blog::Blogpost,
pub filter_tags: HashSet<String>,
+ pub locale: Locale,
}
// filtertags, blogpost-panel
#[derive(Template)]
#[template(path = "blog.html")]
pub struct Blog {
+ pub title: String,
pub blogposts: Vec<blog::Blogpost>,
pub tags: Vec<String>,
pub filter_tags: HashSet<String>,
+ pub locale: Locale,
}
#[derive(Template)]
#[template(path = "poem.html")]
pub struct Poem {
+ pub title: String,
pub poem: poetry::Poem,
pub jiggle: isize,
+ pub locale: Locale,
}
#[derive(Template)]
#[template(path = "poetry.html")]
pub struct Poetry {
+ pub title: String,
pub poems: Vec<poetry::Poem>,
pub jiggle: isize,
+ pub locale: Locale,
}
#[derive(Template)]
#[template(path = "contact.html")]
-pub struct Contact;
+pub struct Contact {
+ pub title: String,
+ pub locale: Locale,
+}
#[derive(Template)]
#[template(path = "error.html")]
pub struct Error {
+ pub title: String,
pub status: StatusCode,
pub message: String,
+ // TODO: localize error page
}
diff --git a/templates/base.html b/templates/base.html
index c1dbfad..428ce40 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -7,7 +7,7 @@
<link rel="stylesheet" href="/static/style.css">
<link rel="stylesheet" href="/static/fonts.css">
<link rel="icon" type="image/png" href="/static/favicon.png" />
- <title>celeste's hard drive</title>
+ <title>{{ title }}</title>
</head>
<body>
diff --git a/templates/blogpost-panel.html b/templates/blogpost-panel.html
index 45117b6..2871407 100644
--- a/templates/blogpost-panel.html
+++ b/templates/blogpost-panel.html
@@ -1,6 +1,7 @@
<div class="panel content blogpost">
- <h1 class="title">{{ blogpost.subject().unwrap_or("untitled") }}</h1>
- <h2 class="created-at">{{ blogpost.published_at() }} <a href="/blog/{{ blogpost.file_name() }}">permalink</a></h2>
+ <h1 class="title">{{ blogpost.subject().unwrap_or(locale.text("untitled").unwrap().as_str()) }}</h1>
+ <h2 class="created-at">{{ blogpost.published_at() }} <a href="/blog/{{ blogpost.file_name() }}">{{
+ locale.text("permalink").unwrap() }}</a></h2>
<div class="tags">{% for tag in blogpost.tags() %}{% let tag = tag.to_string() %}<a
class="tag {% if filter_tags.contains(tag) %}active{% endif %}" href="/blog?filter={{ tag }}">{{ tag
}}</a>{%
diff --git a/templates/contact.html b/templates/contact.html
index 4302e88..d6534fd 100644
--- a/templates/contact.html
+++ b/templates/contact.html
@@ -6,7 +6,7 @@
<header>
<div class="panel" id="title">
- <h1>celeste 🌸</h1>
+ <h1>{{ locale.text("name").unwrap() }}</h1>
</div>
</header>
@@ -15,21 +15,22 @@
{% block content %}
<div class="content panel h-card" rel="author">
- <h1 class="p-name">cel</h1>
+ <h1 class="p-name">{{ locale.text("name").unwrap() }}</h1>
<ul>
<li>
- <h3>pronouns: <span class="p-x-pronoun-nominative">she</span>/<span class="p-x-pronoun-accusative">her</span></h3>
+ <h3>{{ locale.text("pronouns").unwrap()|safe }}</h3>
</li>
- <li>email: <a class="u-email" href="mailto:cel@blos.sm">cel@blos.sm</a></li>
- <li>jabber: <a class="u-impp" href="xmpp:cel@blos.sm?message">cel@blos.sm</a></li>
- <li>scrobbles: <a class="u-url" href="https://listenbrainz.org/user/celblossom">listenbrainz/celblossom</a></li>
- <li>bandcamp fan: <a class="u-url" href="https://bandcamp.com/celblossom">bandcamp/celblossom</a></li>
+ <li>{{ locale.text("email").unwrap() }}: <a class="u-email" href="mailto:cel@blos.sm">cel@blos.sm</a></li>
+ <li>{{ locale.text("jabber").unwrap() }}: <a class="u-impp" href="xmpp:cel@blos.sm?message">cel@blos.sm</a></li>
+ <li>{{ locale.text("scrobbles").unwrap() }}: <a class="u-url"
+ href="https://listenbrainz.org/user/celblossom">listenbrainz/celblossom</a></li>
+ <li>{{ locale.text("bandcamp-fan").unwrap() }}: <a class="u-url"
+ href="https://bandcamp.com/celblossom">bandcamp/celblossom</a></li>
<br>
- <li><span class="p-note">languages (in rough skill order): english, portuguese, french, japanese, german, chinese,
- latin, toki pona, korean</span></li>
+ <li><span class="p-note">{{ locale.text("languages").unwrap() }}</span></li>
</li>
- <li><span class="p-note">programming: rust, erlang, go, haskell, webdev, lisp</span></li>
+ <li><span class="p-note">{{ locale.text("programming").unwrap() }}</span></li>
</ul>
</div>
diff --git a/templates/filtertags.html b/templates/filtertags.html
index 55c802f..4902dd4 100644
--- a/templates/filtertags.html
+++ b/templates/filtertags.html
@@ -1,5 +1,5 @@
<div class="panel" id="filter-tags">
- <h2>filter by tags</h2>
+ <h2>{{ locale.text("filter-by-tags").unwrap() }}</h2>
<div class="tags">
{% for tag in tags.clone() %}{% let contains_tag = filter_tags.contains(tag) %}<a
class="{% if contains_tag %}active{% endif %}"
diff --git a/templates/home.html b/templates/home.html
index 7bbed9e..3e34cae 100644
--- a/templates/home.html
+++ b/templates/home.html
@@ -6,7 +6,7 @@
<header>
<div class="panel" id="title">
- <h1>celeste 🌸</h1>
+ <h1>{{ locale.text("name").unwrap() }}</h1>
</div>
{% if is_live %}
@@ -16,7 +16,8 @@
{% endif %}
{% if listenbrainz.is_scrobbling %}
- <a href="https://listenbrainz.org/user/celblossom" class="panel" id="scrobble">now playing: {{
+ <a href="https://listenbrainz.org/user/celblossom" class="panel" id="scrobble">{{ locale.text("now-playing").unwrap()
+ }}: {{
listenbrainz.song.clone().unwrap_or_default() }} -
{{ listenbrainz.artist.clone().unwrap_or_default() }}</a>
{% endif %}
@@ -28,13 +29,7 @@
{% block content %}
<div class="panel content">
- <h2>hallo i am celeste welcome 2 my site 🌟</h2>
- <p>this is where i do the posting</p>
- <p>i wish u a wonderful day</p>
- <br>
- <img src="/static/quinntyping.png">
- <p>perpetually under construction</p>
- <img style="border: 0;" src="/static/barraconstruction.gif">
+ {{ locale.text("welcome").unwrap()|safe }}
</div>
{% endblock content %}
@@ -44,10 +39,10 @@
<aside>
<div class="panel" style="background-color: #b52f6a; z-index: -1; font-family: 'Terminal Grotesque'; font-size: 2em">
- latest update: added poetry!</div>
+ {{ locale.text("latest-update").unwrap() }}</div>
{% include "latestposts.html" %}
{% include "random-poem.html" %}
</aside>
-{% endblock aside %} \ No newline at end of file
+{% endblock aside %}
diff --git a/templates/latestposts.html b/templates/latestposts.html
index e2dfa9f..b2ed2c5 100644
--- a/templates/latestposts.html
+++ b/templates/latestposts.html
@@ -1,10 +1,11 @@
<div class="panel" id="posts">
- <h2>latest posts <a class="small-badge" href="/feed"><img class="small-badge" src="/static/atombadge.png"
- alt="atom newsfeed"></a></h2>
+ <h2>{{ locale.text("latest-blogposts").unwrap() }} <a class="small-badge" href="/feed"><img class="small-badge"
+ src="/static/atombadge.png" alt="atom newsfeed"></a></h2>
<table id="post-list">
{% for blogpost in blogposts %}
<tr>
- <td><a class="post-entry" href="/blog/{{ blogpost.file_name() }}">{{ blogpost.subject().unwrap_or("untitled")
+ <td><a class="post-entry" href="/blog/{{ blogpost.file_name() }}">{{
+ blogpost.subject().unwrap_or(locale.text("untitled").unwrap().as_str())
}}<span class="post-date">{{
blogpost.published_at()|mytruncate(10) }}</span></a></td>
</tr>
diff --git a/templates/poem-panel.html b/templates/poem-panel.html
index 3359578..e1fb016 100644
--- a/templates/poem-panel.html
+++ b/templates/poem-panel.html
@@ -2,9 +2,10 @@
style="top: {{ self::thread_rng().gen_range(-jiggle..=jiggle) }}vw; left: {{ self::thread_rng().gen_range(-4..=4) }}vw"
class="panel content poem">
{% if let Some(title) = poem.title %}<h1 class="title">{{ title }}</h1>{% endif %}
- <h2 class="created-at">{{ poem.created_at.date_naive() }} <a href="/poetry/{{ poem.file_name }}">permalink</a>
+ <h2 class="created-at">{{ poem.created_at.date_naive() }} <a href="/poetry/{{ poem.file_name }}">{{
+ locale.text("permalink").unwrap() }}</a>
</h2>
<div class="poem-content">
{{ poem.content|safe }}
</div>
-</div>
+</div> \ No newline at end of file
diff --git a/templates/random-poem.html b/templates/random-poem.html
index bdfbaff..f3531d8 100644
--- a/templates/random-poem.html
+++ b/templates/random-poem.html
@@ -1,8 +1,9 @@
{% if let Some(poem) = poem %}
<div class="panel" id="random-poem">
- <h2>random poem</h2>
+ <h2>{{ locale.text("random-poem").unwrap() }}</h2>
<a href="/poetry/{{ poem.file_name }}">
- <h3>{% if let Some(title) = poem.title %}{{ title }}{% else %}permalink{% endif %}</h3>
+ <h3>{% if let Some(title) = poem.title %}{{ title }}{% else %}{{ locale.text("permalink").unwrap() }}{% endif %}
+ </h3>
</a>
<div class="poem-content">
{{ poem.content|safe }}