initial translatability

This commit is contained in:
Dietrich 2021-03-30 13:18:13 +02:00
parent 7fd29d4903
commit 218840432f
Signed by: dietrich
GPG Key ID: 9F3C20C0F85DF67C
12 changed files with 345 additions and 7 deletions

2
.gitignore vendored
View File

@ -1,6 +1,6 @@
/target
.env
links.db
links.db*
launch.json
settings.json
links.session.sql

295
Cargo.lock generated
View File

@ -1,5 +1,15 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "Inflector"
version = "0.11.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3"
dependencies = [
"lazy_static",
"regex",
]
[[package]]
name = "actix-codec"
version = "0.3.0"
@ -412,6 +422,12 @@ dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "arc-swap"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4d7d63395147b81a9e570bcc6243aaf71c017bd666d4909cfef0085bdda8d73"
[[package]]
name = "argonautica"
version = "0.2.0"
@ -1037,6 +1053,12 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0"
[[package]]
name = "doc-comment"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
[[package]]
name = "dotenv"
version = "0.15.0"
@ -1126,6 +1148,99 @@ dependencies = [
"miniz_oxide 0.4.3",
]
[[package]]
name = "fluent"
version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "960ac6317b829b94c67f9a774e8b56db388405e174855a5a84d4b461ff85b281"
dependencies = [
"fluent-bundle",
"unic-langid",
]
[[package]]
name = "fluent-bundle"
version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba3cc2d1c59a0daaa93bb346db97e1ebad1067c5ffedc1af8b937a9d8caa6a77"
dependencies = [
"fluent-langneg",
"fluent-syntax",
"intl-memoizer",
"intl_pluralrules",
"ouroboros",
"rustc-hash",
"smallvec",
"unic-langid",
]
[[package]]
name = "fluent-langneg"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c4ad0989667548f06ccd0e306ed56b61bd4d35458d54df5ec7587c0e8ed5e94"
dependencies = [
"unic-langid",
]
[[package]]
name = "fluent-syntax"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "784f660373ea898f712a7e67b43f35bf79608d46112747c29767d087611d716b"
[[package]]
name = "fluent-template-macros"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3051f88dd918b30a994177acc8f3b8b0b399c98ca5aa2ab985e79070a8841592"
dependencies = [
"flume",
"ignore",
"once_cell",
"proc-macro2 1.0.24",
"quote 1.0.8",
"syn",
"unic-langid",
]
[[package]]
name = "fluent-templates"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fa6b2186b959236019d67fb839f036c83a799edd4389c505678ca1b8d41e9ed"
dependencies = [
"arc-swap",
"fluent",
"fluent-bundle",
"fluent-langneg",
"fluent-syntax",
"fluent-template-macros",
"flume",
"heck",
"ignore",
"lazy_static",
"log",
"once_cell",
"serde_json",
"snafu",
"tera",
"unic-langid",
]
[[package]]
name = "flume"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "531a685ab99b8f60a271b44d5dd1a76e55124a8c9fa0407b7a8e9cd172d5b588"
dependencies = [
"futures-core",
"futures-sink",
"nanorand",
"pin-project 1.0.4",
"spinning_top",
]
[[package]]
name = "fnv"
version = "1.0.7"
@ -1327,8 +1442,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8"
dependencies = [
"cfg-if 1.0.0",
"js-sys",
"libc",
"wasi 0.10.2+wasi-snapshot-preview1",
"wasm-bindgen",
]
[[package]]
@ -1589,6 +1706,26 @@ dependencies = [
"cfg-if 1.0.0",
]
[[package]]
name = "intl-memoizer"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c310433e4a310918d6ed9243542a6b83ec1183df95dff8f23f87bb88a264a66f"
dependencies = [
"type-map",
"unic-langid",
]
[[package]]
name = "intl_pluralrules"
version = "7.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b18f988384267d7066cc2be425e6faf352900652c046b6971d2e228d3b1c5ecf"
dependencies = [
"tinystr",
"unic-langid",
]
[[package]]
name = "iovec"
version = "0.1.4"
@ -1848,6 +1985,15 @@ dependencies = [
"ws2_32-sys",
]
[[package]]
name = "nanorand"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac1378b66f7c93a1c0f8464a19bf47df8795083842e5090f4b7305973d5a22d0"
dependencies = [
"getrandom 0.2.2",
]
[[package]]
name = "net2"
version = "0.2.37"
@ -1957,6 +2103,29 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
[[package]]
name = "ouroboros"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f6d5c203fe8d786d9d7bec8203cbbff3eb2cf8410c0d70cfd05b3d5f5d545da"
dependencies = [
"ouroboros_macro",
"stable_deref_trait",
]
[[package]]
name = "ouroboros_macro"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "129943a960e6a08c7e70ca5a09f113c273fe7f10ae8420992c78293e3dffdf65"
dependencies = [
"Inflector",
"proc-macro-error",
"proc-macro2 1.0.24",
"quote 1.0.8",
"syn",
]
[[package]]
name = "parking_lot"
version = "0.11.1"
@ -2145,6 +2314,30 @@ version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
[[package]]
name = "proc-macro-error"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
"proc-macro-error-attr",
"proc-macro2 1.0.24",
"quote 1.0.8",
"syn",
"version_check 0.9.2",
]
[[package]]
name = "proc-macro-error-attr"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
"proc-macro2 1.0.24",
"quote 1.0.8",
"version_check 0.9.2",
]
[[package]]
name = "proc-macro-hack"
version = "0.5.19"
@ -2187,6 +2380,8 @@ dependencies = [
"chrono",
"clap",
"dotenv",
"fluent-langneg",
"fluent-templates",
"image",
"qrcode",
"rand 0.8.3",
@ -2566,6 +2761,12 @@ version = "0.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e3bad0ee36814ca07d7968269dd4b7ec89ec2da10c4bb613928d3077083c232"
[[package]]
name = "rustc-hash"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "rustc_version"
version = "0.2.3"
@ -2820,6 +3021,27 @@ version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e"
[[package]]
name = "snafu"
version = "0.6.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eab12d3c261b2308b0d80c26fffb58d17eba81a4be97890101f416b478c79ca7"
dependencies = [
"doc-comment",
"snafu-derive",
]
[[package]]
name = "snafu-derive"
version = "0.6.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1508efa03c362e23817f96cde18abed596a25219a8b2c66e8db33c03543d315b"
dependencies = [
"proc-macro2 1.0.24",
"quote 1.0.8",
"syn",
]
[[package]]
name = "socket2"
version = "0.3.19"
@ -2837,6 +3059,15 @@ version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
[[package]]
name = "spinning_top"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e529d73e80d64b5f2631f9035113347c578a1c9c7774b83a2b880788459ab36"
dependencies = [
"lock_api",
]
[[package]]
name = "sqlformat"
version = "0.1.6"
@ -2941,6 +3172,12 @@ dependencies = [
"tokio-rustls",
]
[[package]]
name = "stable_deref_trait"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]]
name = "standback"
version = "0.2.14"
@ -3220,6 +3457,12 @@ dependencies = [
"syn",
]
[[package]]
name = "tinystr"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29738eedb4388d9ea620eeab9384884fc3f06f586a2eddb56bedc5885126c7c1"
[[package]]
name = "tinyvec"
version = "1.1.1"
@ -3365,6 +3608,15 @@ dependencies = [
"trust-dns-proto",
]
[[package]]
name = "type-map"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6d3364c5e96cb2ad1603037ab253ddd34d7fb72a58bdddf4b7350760fc69a46"
dependencies = [
"rustc-hash",
]
[[package]]
name = "typenum"
version = "1.12.0"
@ -3398,6 +3650,49 @@ version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80d7ff825a6a654ee85a63e80f92f054f904f21e7d12da4e22f9834a4aaa35bc"
[[package]]
name = "unic-langid"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73328fcd730a030bdb19ddf23e192187a6b01cd98be6d3140622a89129459ce5"
dependencies = [
"unic-langid-impl",
"unic-langid-macros",
]
[[package]]
name = "unic-langid-impl"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a4a8eeaf0494862c1404c95ec2f4c33a2acff5076f64314b465e3ddae1b934d"
dependencies = [
"tinystr",
]
[[package]]
name = "unic-langid-macros"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18f980d6d87e8805f2836d64b4138cc95aa7986fa63b1f51f67d5fbff64dd6e5"
dependencies = [
"proc-macro-hack",
"tinystr",
"unic-langid-impl",
"unic-langid-macros-impl",
]
[[package]]
name = "unic-langid-macros-impl"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29396ffd97e27574c3e01368b1a64267d3064969e4848e2e130ff668be9daa9f"
dependencies = [
"proc-macro-hack",
"quote 1.0.8",
"syn",
"unic-langid-impl",
]
[[package]]
name = "unic-segment"
version = "0.9.0"

View File

@ -33,6 +33,8 @@ image = "0.23"
rand="0.8"
rpassword = "5.0"
clap = "2.33"
fluent-templates = { version = "0.6", features = ["tera"] }
fluent-langneg ="0.13"
[build-dependencies]
actix-web-static-files = "3.0"

6
locales/core.ftl Normal file
View File

@ -0,0 +1,6 @@
list-links = List of existing links
add-link = Add a new link
invite-user = Invite a new user
list-users = List of existing users
welcome-user = Wellcome {$username}
logout = Logout

6
locales/de/main.ftl Normal file
View File

@ -0,0 +1,6 @@
list-links = Link Liste
add-link = Link hinzufügen
invite-user = Benutzer einladen
list-users = Liste der Benutzer
welcome-user = Herzlich willkommen {$username}
logout = Abmelden

6
locales/en/main.ftl Normal file
View File

@ -0,0 +1,6 @@
list-links = List of existing links
add-link = Add a new link
invite-user = Invite a new user
list-users = List of existing users
welcome-user = Wellcome {$username}
logout = Logout

View File

@ -0,0 +1,4 @@
-- Add migration script here
ALTER TABLE users
ADD COLUMN language Text NOT NULL DEFAULT "en";

View File

@ -25,6 +25,7 @@ use std::{fmt::Display, path::PathBuf, str::FromStr};
use actix_identity::{CookieIdentityPolicy, IdentityService};
use actix_web::{web, App, HttpResponse, HttpServer};
use fluent_templates::{static_loader, FluentLoader};
use qrcode::types::QrError;
use sqlx::{Pool, Sqlite};
use tera::Tera;
@ -188,9 +189,20 @@ impl ServerConfig {
}
include!(concat!(env!("OUT_DIR"), "/generated.rs"));
static_loader! {
static LOCALES = {
locales: "./locales",
fallback_language: "en",
};
}
fn build_tera() -> Tera {
let mut tera = Tera::default();
// Add translation support
tera.register_function("fluent", FluentLoader::new(&*LOCALES));
tera.add_raw_templates(vec![
("admin.html", include_str!("../templates/admin.html")),
("base.html", include_str!("../templates/base.html")),

View File

@ -11,6 +11,7 @@ pub struct User {
pub email: String,
pub password: String,
pub role: i64,
pub language: String,
}
impl User {

View File

@ -81,6 +81,7 @@ pub(crate) async fn list_all_allowed(
users.username as usern,
users.email as uemail,
users.role as urole,
users.language as ulang,
count(clicks.id) as counter
from
links
@ -107,6 +108,7 @@ pub(crate) async fn list_all_allowed(
email: v.get("uemail"),
password: "invalid".to_owned(),
role: v.get("urole"),
language: v.get("ulang"),
},
clicks: Count {
number: v.get("counter"), /* count is never None */
@ -244,6 +246,7 @@ pub(crate) async fn update_user(
email: data.email.clone(),
password,
role: unmodified_user.role,
language: unmodified_user.language,
};
new_user.update_user(server_config).await?;
let changed_user = User::get_user(uid, server_config).await?;

View File

@ -11,13 +11,16 @@
<div class="admin">
<nav>
<ol>
<li><a href="/admin/index/">Link Liste</a></li>
<li><a href="/admin/submit/">Link Hinzufügen</a></li>
{% if user.role == 2 %}<li><a href="/admin/signup/">Einladen</a></li>
<li><a href="/admin/view/users/">Benutzer</a></li>{% endif %}
<li style="float:right"><a href="/admin/logout/">Abmelden</a></li>
<li><a href="/admin/index/">{{ fluent(key="list-links", lang=user.language) }}</a>
</li>
<li><a href="/admin/submit/">{{ fluent(key="add-link", lang=user.language) }}</a></li>
{% if user.role == 2 %}<li><a href="/admin/signup/">{{ fluent(key="invite-user", lang=user.language) }}</a>
</li>
<li><a href="/admin/view/users/">{{ fluent(key="list-users", lang=user.language) }}</a></li>{% endif %}
<li style="float:right"><a href="/admin/logout/">{{ fluent(key="logout", lang=user.language) }}</a></li>
<li style="float:right">
<div class="willkommen">Herzlich willkommen {{ user.username }}</div>
<div class="willkommen">{{ fluent(key="welcome-user", lang=user.language, username=user.username) }}
</div>
</li>
</ol>
</nav>