1
0
Fork 0

Add i18n to state

This commit is contained in:
Alex Kotov 2020-10-21 09:05:54 +05:00
parent bcd5c65a12
commit e8593b5f5a
Signed by: kotovalexarian
GPG Key ID: 553C0EBBEB5D5F08
9 changed files with 208 additions and 1 deletions

121
Cargo.lock generated
View File

@ -308,6 +308,7 @@ dependencies = [
"bcrypt",
"diesel",
"dotenv",
"fluent-bundle",
"r2d2",
"regex",
"rocket",
@ -316,6 +317,7 @@ dependencies = [
"serde",
"serde_derive",
"serde_json",
"unic-langid",
"validator",
]
@ -331,6 +333,36 @@ dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "fluent-bundle"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a79916560098f0a57215a489e37b7fc83088949eab7f7977dcc329b254d50c17"
dependencies = [
"fluent-langneg",
"fluent-syntax",
"intl-memoizer",
"intl_pluralrules",
"rental",
"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.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9389354f858e38f37d9a249133611a1fcaec469f44773b04ddbd82f4f08d49eb"
[[package]]
name = "fsevent"
version = "0.4.0"
@ -366,6 +398,15 @@ version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
[[package]]
name = "fxhash"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
dependencies = [
"byteorder",
]
[[package]]
name = "generic-array"
version = "0.12.3"
@ -555,6 +596,26 @@ dependencies = [
"cfg-if",
]
[[package]]
name = "intl-memoizer"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a0ed58ba6089d49f8a9a7d5e16fc9b9e2019cdf40ef270f3d465fa244d9630b"
dependencies = [
"type-map",
"unic-langid",
]
[[package]]
name = "intl_pluralrules"
version = "7.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c271cdb1f12a9feb3a017619c3ee681f971f270f6757341d6abe1f9f7a98bc3"
dependencies = [
"tinystr",
"unic-langid",
]
[[package]]
name = "iovec"
version = "0.1.4"
@ -1022,6 +1083,27 @@ version = "0.6.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8cab7a364d15cde1e505267766a2d3c4e22a843e1a601f0fa7564c0f82ced11c"
[[package]]
name = "rental"
version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8545debe98b2b139fb04cad8618b530e9b07c152d99a5de83c860b877d67847f"
dependencies = [
"rental-impl",
"stable_deref_trait",
]
[[package]]
name = "rental-impl"
version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "475e68978dc5b743f2f40d8e0a8fdc83f1c5e78cbf4b8fa5e74e73beebc340de"
dependencies = [
"proc-macro2 1.0.24",
"quote 1.0.7",
"syn 1.0.44",
]
[[package]]
name = "rocket"
version = "0.4.5"
@ -1214,6 +1296,12 @@ version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbee7696b84bbf3d89a1c2eccff0850e3047ed46bfcd2e92c29a2d074d57e252"
[[package]]
name = "stable_deref_trait"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]]
name = "state"
version = "0.4.1"
@ -1274,6 +1362,12 @@ dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "tinystr"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29738eedb4388d9ea620eeab9384884fc3f06f586a2eddb56bedc5885126c7c1"
[[package]]
name = "tinyvec"
version = "0.3.4"
@ -1295,6 +1389,15 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079"
[[package]]
name = "type-map"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d2741b1474c327d95c1f1e3b0a2c3977c8e128409c572a33af2914e7d636717"
dependencies = [
"fxhash",
]
[[package]]
name = "typeable"
version = "0.1.2"
@ -1313,6 +1416,24 @@ version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
[[package]]
name = "unic-langid"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73328fcd730a030bdb19ddf23e192187a6b01cd98be6d3140622a89129459ce5"
dependencies = [
"unic-langid-impl",
]
[[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 = "unicase"
version = "1.4.2"

View File

@ -15,12 +15,14 @@ publish = true
[dependencies]
bcrypt = "0.8.2"
dotenv = "0.15.0"
fluent-bundle = "0.13.1"
r2d2 = "0.8.9"
regex = "1.4.1"
rocket_csrf = { path = "/home/kotovalexarian/repos/github/kotovalexarian/rocket_csrf" }
serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"
unic-langid = "0.9.0"
[dependencies.diesel]
version = "1.4.5"

View File

@ -128,6 +128,19 @@ impl Config {
Ok(result_str.to_string())
}
pub fn locales_path(&self) -> Result<String, ()> {
let mut result_path_buf = std::path::PathBuf::new();
result_path_buf.push(self.root.to_string());
result_path_buf.push("locales");
let result_str = match result_path_buf.to_str() {
None => return Err(()),
Some(value) => value,
};
Ok(result_str.to_string())
}
pub fn use_env_for_root(&mut self) {
self.root = match std::env::var("ROOT") {
Err(_) => return,

53
src/i18n.rs Normal file
View File

@ -0,0 +1,53 @@
use std::collections::HashMap;
use fluent_bundle::FluentResource;
use fluent_bundle::concurrent::FluentBundle;
use unic_langid::LanguageIdentifier;
pub struct I18n(HashMap<String, FluentBundle<FluentResource>>);
impl I18n {
pub fn new(path: &str, locales: &[&str]) -> Result<Self, ()> {
let lang_ids: Vec<Result<LanguageIdentifier, _>> =
locales.iter().map(|locale| {
locale.parse::<LanguageIdentifier>()
}).collect();
if let Some(_) = lang_ids.iter().find(|lang_id| lang_id.is_err()) {
return Err(());
}
let lang_ids: Vec<&LanguageIdentifier> =
lang_ids.iter().map(|lang_id| lang_id.as_ref().unwrap()).collect();
let mut hash_map = HashMap::new();
for lang_id in lang_ids {
let locale = lang_id.to_string();
let mut path_buf = std::path::PathBuf::from(path);
path_buf.push(&locale);
path_buf.set_extension("ftl");
let data = match std::fs::read_to_string(path_buf) {
Ok(data) => data,
Err(_) => return Err(()),
};
let resource = match FluentResource::try_new(data) {
Ok(resource) => resource,
Err(_) => return Err(()),
};
let mut bundle = FluentBundle::default();
if let Err(_) = bundle.add_resource(resource) {
return Err(());
};
hash_map.insert(locale, bundle);
}
Ok(Self(hash_map))
}
}

View File

@ -5,6 +5,7 @@
mod config;
mod database;
mod forms;
mod i18n;
mod models;
mod responses;
mod routes;

View File

@ -1,13 +1,16 @@
use crate::states;
use crate::views;
use crate::i18n::I18n;
use crate::responses::CommonResponse;
use rocket::State;
use rocket_contrib::templates::Template;
use rocket_csrf::CsrfToken;
#[get("/")]
pub fn index(
_i18n: State<I18n>,
csrf_token: CsrfToken,
current_user: states::MaybeCurrentUser,
) -> Result<Template, CommonResponse> {

View File

@ -4,8 +4,10 @@ use crate::views;
use crate::models;
use crate::forms;
use crate::i18n::I18n;
use crate::responses::CommonResponse;
use rocket::State;
use rocket::http::{Cookie, Cookies};
use rocket::response::Redirect;
use rocket::request::Form;
@ -14,6 +16,7 @@ use rocket_csrf::CsrfToken;
#[get("/sign_in")]
pub fn new(
_i18n: State<I18n>,
csrf_token: CsrfToken,
current_user: states::MaybeCurrentUser,
) -> Result<Template, CommonResponse> {
@ -40,6 +43,7 @@ pub fn new(
#[post("/sign_in", data = "<form>")]
pub fn create(
_i18n: State<I18n>,
csrf_token: CsrfToken,
db_conn: database::DbConn,
current_user: states::MaybeCurrentUser,
@ -76,6 +80,7 @@ pub fn create(
#[delete("/sign_out", data = "<form>")]
pub fn delete(
_i18n: State<I18n>,
csrf_token: CsrfToken,
current_user: states::MaybeCurrentUser,
form: Form<forms::UserSignOut>,

View File

@ -4,8 +4,10 @@ use crate::views;
use crate::models;
use crate::forms;
use crate::i18n::I18n;
use crate::responses::CommonResponse;
use rocket::State;
use rocket::http::{Cookie, Cookies};
use rocket::response::Redirect;
use rocket::request::Form;
@ -14,6 +16,7 @@ use rocket_csrf::CsrfToken;
#[get("/sign_up")]
pub fn new(
_i18n: State<I18n>,
csrf_token: CsrfToken,
current_user: states::MaybeCurrentUser,
) -> Result<Template, CommonResponse> {
@ -40,6 +43,7 @@ pub fn new(
#[post("/sign_up", data = "<form>")]
pub fn create(
_i18n: State<I18n>,
csrf_token: CsrfToken,
db_conn: database::DbConn,
current_user: states::MaybeCurrentUser,

View File

@ -1,5 +1,6 @@
use crate::config;
use crate::database;
use crate::i18n::I18n;
use crate::routes;
use rocket_contrib::serve::{Options as ServeOptions, StaticFiles};
@ -8,9 +9,13 @@ use rocket_contrib::templates::Template;
pub fn rocket(config: &config::Config) -> Result<rocket::Rocket, ()> {
let rocket_config = config.to_rocket_config()?;
let public_path = config.public_path()?;
let public_path = config.public_path()?;
let locales_path = config.locales_path()?;
let i18n = I18n::new(&locales_path, &["en", "ru"])?;
let result = rocket::custom(rocket_config)
.manage(i18n)
.manage(database::create_db_pool(config))
.attach(rocket_csrf::Fairing::new())
.attach(Template::fairing())