translations #1

This commit is contained in:
Ondrej Vlach 2023-11-26 23:53:31 +01:00
parent 5fa660037e
commit 07c02052fd
9 changed files with 288 additions and 22 deletions

198
Cargo.lock generated
View File

@ -222,6 +222,12 @@ dependencies = [
"phf_codegen", "phf_codegen",
] ]
[[package]]
name = "chunky-vec"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb7bdea464ae038f09197b82430b921c53619fc8d2bcaf7b151013b3ca008017"
[[package]] [[package]]
name = "cookie" name = "cookie"
version = "0.18.0" version = "0.18.0"
@ -369,12 +375,32 @@ dependencies = [
"crypto-common", "crypto-common",
] ]
[[package]]
name = "displaydoc"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "either" name = "either"
version = "1.9.0" version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
[[package]]
name = "elsa"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "714f766f3556b44e7e4776ad133fcc3445a489517c25c704ace411bb14790194"
dependencies = [
"stable_deref_trait",
]
[[package]] [[package]]
name = "encoding_rs" name = "encoding_rs"
version = "0.8.33" version = "0.8.33"
@ -441,6 +467,69 @@ dependencies = [
"windows-sys", "windows-sys",
] ]
[[package]]
name = "fluent-bundle"
version = "0.15.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e242c601dec9711505f6d5bbff5bedd4b61b2469f2e8bb8e57ee7c9747a87ffd"
dependencies = [
"fluent-langneg",
"fluent-syntax",
"intl-memoizer",
"intl_pluralrules",
"rustc-hash",
"self_cell 0.10.3",
"smallvec",
"unic-langid",
]
[[package]]
name = "fluent-fallback"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08fdcccdeb6c01cb085f2bb3420506e6c67f025cee5db047529838c673a7d82b"
dependencies = [
"async-trait",
"chunky-vec",
"fluent-bundle",
"futures",
"once_cell",
"rustc-hash",
"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-resmgr"
version = "0.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7144b87452708dd3217fdb41aefb74cf261fde09cd055ee2e1f4634b5beb380"
dependencies = [
"elsa",
"fluent-bundle",
"fluent-fallback",
"futures",
"rustc-hash",
"unic-langid",
]
[[package]]
name = "fluent-syntax"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0abed97648395c902868fee9026de96483933faa54ea3b40d652f7dfe61ca78"
dependencies = [
"thiserror",
]
[[package]] [[package]]
name = "fnv" name = "fnv"
version = "1.0.7" version = "1.0.7"
@ -488,6 +577,7 @@ checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335"
dependencies = [ dependencies = [
"futures-channel", "futures-channel",
"futures-core", "futures-core",
"futures-executor",
"futures-io", "futures-io",
"futures-sink", "futures-sink",
"futures-task", "futures-task",
@ -510,12 +600,34 @@ version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c"
[[package]]
name = "futures-executor"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc"
dependencies = [
"futures-core",
"futures-task",
"futures-util",
]
[[package]] [[package]]
name = "futures-io" name = "futures-io"
version = "0.3.29" version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa"
[[package]]
name = "futures-macro"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "futures-sink" name = "futures-sink"
version = "0.3.29" version = "0.3.29"
@ -537,6 +649,7 @@ dependencies = [
"futures-channel", "futures-channel",
"futures-core", "futures-core",
"futures-io", "futures-io",
"futures-macro",
"futures-sink", "futures-sink",
"futures-task", "futures-task",
"memchr", "memchr",
@ -818,6 +931,25 @@ dependencies = [
"libc", "libc",
] ]
[[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.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "078ea7b7c29a2b4df841a7f6ac8775ff6074020c6776d48491ce2268e068f972"
dependencies = [
"unic-langid",
]
[[package]] [[package]]
name = "ipnet" name = "ipnet"
version = "2.9.0" version = "2.9.0"
@ -1152,6 +1284,8 @@ version = "0.1.0"
dependencies = [ dependencies = [
"chrono", "chrono",
"fern", "fern",
"fluent-bundle",
"fluent-resmgr",
"log", "log",
"ovlach_data", "ovlach_data",
"reqwest", "reqwest",
@ -1161,6 +1295,7 @@ dependencies = [
"serde_yaml", "serde_yaml",
"sha256", "sha256",
"tokio", "tokio",
"unic-langid",
] ]
[[package]] [[package]]
@ -1619,6 +1754,12 @@ version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
[[package]]
name = "rustc-hash"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]] [[package]]
name = "rustix" name = "rustix"
version = "0.38.25" version = "0.38.25"
@ -1697,6 +1838,21 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "self_cell"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e14e4d63b804dc0c7ec4a1e52bcb63f02c7ac94476755aa579edac21e01f915d"
dependencies = [
"self_cell 1.0.2",
]
[[package]]
name = "self_cell"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e388332cd64eb80cd595a00941baf513caffae8dce9cfd0467fc9c66397dade6"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.193" version = "1.0.193"
@ -1870,6 +2026,12 @@ dependencies = [
"memchr", "memchr",
] ]
[[package]]
name = "stable_deref_trait"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]] [[package]]
name = "state" name = "state"
version = "0.6.0" version = "0.6.0"
@ -2005,6 +2167,15 @@ dependencies = [
"time-core", "time-core",
] ]
[[package]]
name = "tinystr"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "83c02bf3c538ab32ba913408224323915f4ef9a6d61c0e85d493f355921c0ece"
dependencies = [
"displaydoc",
]
[[package]] [[package]]
name = "tinyvec" name = "tinyvec"
version = "1.6.0" version = "1.6.0"
@ -2192,6 +2363,15 @@ version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
[[package]]
name = "type-map"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6d3364c5e96cb2ad1603037ab253ddd34d7fb72a58bdddf4b7350760fc69a46"
dependencies = [
"rustc-hash",
]
[[package]] [[package]]
name = "typenum" name = "typenum"
version = "1.17.0" version = "1.17.0"
@ -2244,6 +2424,24 @@ version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80d7ff825a6a654ee85a63e80f92f054f904f21e7d12da4e22f9834a4aaa35bc" checksum = "80d7ff825a6a654ee85a63e80f92f054f904f21e7d12da4e22f9834a4aaa35bc"
[[package]]
name = "unic-langid"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "398f9ad7239db44fd0f80fe068d12ff22d78354080332a5077dc6f52f14dcf2f"
dependencies = [
"unic-langid-impl",
]
[[package]]
name = "unic-langid-impl"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e35bfd2f2b8796545b55d7d3fd3e89a0613f68a0d1c8bc28cb7ff96b411a35ff"
dependencies = [
"tinystr",
]
[[package]] [[package]]
name = "unic-segment" name = "unic-segment"
version = "0.9.0" version = "0.9.0"

View File

@ -17,3 +17,6 @@ tokio = { version = "1", features = ["full"] }
ovlach_data = { git = "https://glpat-Ju_qUN9Yh8qa5rEnd6T7:glpat-Ju_qUN9Yh8qa5rEnd6T7@gitlab.nanobyte.cz/ondrej/ov-site-api-data.git", branch = "add_missing_fields"} ovlach_data = { git = "https://glpat-Ju_qUN9Yh8qa5rEnd6T7:glpat-Ju_qUN9Yh8qa5rEnd6T7@gitlab.nanobyte.cz/ondrej/ov-site-api-data.git", branch = "add_missing_fields"}
chrono = "0.4.31" chrono = "0.4.31"
sha256 = "1.4.0" sha256 = "1.4.0"
fluent-bundle = "0.15.2"
fluent-resmgr = "0.0.6"
unic-langid = "0.9.1"

View File

@ -0,0 +1,17 @@
devops-enginner-web-developer = DevOPS engineer/Backend web developer(TODO do API)
download-cv = Stáhnout životopis
hire-me = Kontakt
about-me = O mě
professional-skills = Jazyky a technologie
work-experience = Zaměstnání
contact = Kontakt
bio = Základní udaje
education = Vzdělání
title-about = O mě
title-skills = Technologie
title-experience = Zaměstnání
title-education = Vzdělání
title-contact = Kontakt
age = Věk
email = E-mail
phone = Telefon

View File

@ -0,0 +1,17 @@
devops-enginner-web-developer = DevOPS engineer/Backend web developer
download-cv = Download CV
hire-me = Hire me
about-me = About me
professional-skills = Professional Skills
education = Education
work-experience = Work experience
contact = Contact
bio = Bio
title-about = About
title-skills = Skills
title-experience = Experience
title-education = Education
title-contact = Contact
age = Age
email = Email
phone = Phone

View File

@ -22,12 +22,13 @@ pub struct CVBackendConfig {
cv_backend_path: String, cv_backend_path: String,
} }
pub fn rocket_builder() -> Rocket<Build> { pub fn rocket_builder() -> Rocket<Build> {
let rocket = rocket::build(); let rocket = rocket::build();
//let figment = rocket.figment(); //let figment = rocket.figment();
// extract the entire config any `Deserialize` value // extract the entire config any `Deserialize` value
//let config: PresentationConfig = figment.extract().expect("config"); //let config: PresentationConfig = figment.extract().expect("config");
rocket.attach( rocket.attach(
Template::try_custom(|engines| { Template::try_custom(|engines| {
engines.tera.register_filter("static", static_filter); engines.tera.register_filter("static", static_filter);

View File

@ -11,7 +11,7 @@ struct RootPage {
static_host: String, static_host: String,
cv: CV, cv: CV,
download_cv_url: String, download_cv_url: String,
lang: I18n, lang: String,
} }
#[get("/")] #[get("/")]
@ -21,6 +21,7 @@ pub async fn index(presentation_config: &State<PresentationConfig>, cv_config: &
static_host: presentation_config.static_route.clone(), static_host: presentation_config.static_route.clone(),
cv, cv,
download_cv_url: "FIXME!".to_string(), download_cv_url: "FIXME!".to_string(),
lang: "en".to_string(),
}, },
Err(e) => { Err(e) => {
error!("Can't fetch CV data from backend {:?}", e); error!("Can't fetch CV data from backend {:?}", e);

View File

@ -1,10 +1,13 @@
use std::collections::HashMap; use std::{collections::HashMap, str::FromStr};
use chrono::{Utc, Datelike}; use chrono::{Utc, Datelike};
use log::error; use log::error;
use rocket_dyn_templates::tera::{Value, Error}; use rocket_dyn_templates::tera::{Value, Error};
use ovlach_data::cv::chrono::from_string; use ovlach_data::cv::chrono::from_string;
use sha256::{digest, try_digest}; use sha256::{digest, try_digest};
use fluent_resmgr::resource_manager::ResourceManager;
use tokio::sync::broadcast::error;
use unic_langid::LanguageIdentifier;
// TODO: tenhle modul je trochu prasacky.. // TODO: tenhle modul je trochu prasacky..
@ -20,7 +23,33 @@ pub fn translate_filter(
value: &Value, value: &Value,
args: &HashMap<String, rocket_dyn_templates::tera::Value> args: &HashMap<String, rocket_dyn_templates::tera::Value>
) -> Result<Value, Error> { ) -> Result<Value, Error> {
return Ok(rocket_dyn_templates::tera::Value::String(format!("{}", value.as_str().unwrap()))); // TODO: fix-me here! let mgr = ResourceManager::new("./resources/{locale}/{res_id}".into());
let locales = vec![LanguageIdentifier::from_str("en-US").unwrap()];
let val_id = vec![value.as_str().unwrap().to_string()];
let val = value.as_str().unwrap().to_string();
let bundle = mgr.get_bundle(locales, vec!["ovlach_frontend".to_string()]);
let mut errors = vec![];
match bundle.get_message(&val) {
Some(msg) => {
match msg.value() {
Some(pattern) => {
let output = bundle.format_pattern(pattern, None, &mut errors);
return Ok(rocket_dyn_templates::tera::Value::String(output.clone().to_string()))
},
None => {
error!("Can't translate message: {}", val);
return Ok(rocket_dyn_templates::tera::Value::String(format!("{}", val)));
},
}
},
None => {
error!("Can't translate message: {}", val);
return Ok(rocket_dyn_templates::tera::Value::String(format!("{}", val)));
},
};
} }
pub fn lang_entity( pub fn lang_entity(

View File

@ -32,15 +32,15 @@
<div class="site-nav"> <div class="site-nav">
<nav role="navigation"> <nav role="navigation">
<ul class="nav justify-content-center"> <ul class="nav justify-content-center">
<li class="nav-item"><a class="nav-link" href="#about" title="About"><span class="menu-title">About</span></a> <li class="nav-item"><a class="nav-link" href="#about" title="About"><span class="menu-title">{{ "title-about" | translate(lang=lang) }}</span></a>
</li> </li>
<li class="nav-item"><a class="nav-link" href="#skills" title="Skills"><span class="menu-title">Skills</span></a> <li class="nav-item"><a class="nav-link" href="#skills" title="Skills"><span class="menu-title">{{ "title-skills" | translate(lang=lang) }}</span></a>
</li> </li>
<li class="nav-item"><a class="nav-link" href="#experience" title="Experience"><span class="menu-title">Experience</span></a> <li class="nav-item"><a class="nav-link" href="#experience" title="Experience"><span class="menu-title">{{ "title-experience" | translate(lang=lang) }}</span></a>
</li> </li>
<li class="nav-item"><a class="nav-link" href="#education" title="Education"><span class="menu-title">Education</span></a> <li class="nav-item"><a class="nav-link" href="#education" title="Education"><span class="menu-title">{{ "title-education" | translate(lang=lang) }}</span></a>
</li> </li>
<li class="nav-item"><a class="nav-link" href="#contact" title="Contact"><span class="menu-title">Contact</span></a> <li class="nav-item"><a class="nav-link" href="#contact" title="Contact"><span class="menu-title">{{ "title-contact" | translate(lang=lang) }}</span></a>
</li> </li>
</ul> </ul>
</nav> </nav>

View File

@ -14,7 +14,7 @@
<div class="header-bio mt-3"> <div class="header-bio mt-3">
<div data-aos="zoom-in" data-aos-delay="0"> <div data-aos="zoom-in" data-aos-delay="0">
<h2 class="h1"> {{ cv.person.name }} {{ cv.person.surname }} </h2> <h2 class="h1"> {{ cv.person.name }} {{ cv.person.surname }} </h2>
<p>{{ "DevOPS engineer/backend web developer" | translate(lang=lang) }}</p> <p>{{ "devops-enginner-web-developer" | translate(lang=lang) }}</p>
</div> </div>
<div class="header-social mb-3 d-print-none" data-aos="zoom-in" data-aos-delay="200"> <div class="header-social mb-3 d-print-none" data-aos="zoom-in" data-aos-delay="200">
<nav role="navigation"> <nav role="navigation">
@ -50,8 +50,8 @@
</nav> </nav>
</div> </div>
<div class="d-print-none"> <div class="d-print-none">
<a class="btn btn-outline-light btn-lg shadow-sm mt-1 me-3" href="{{ download_cv_url }}" data-aos="fade-right" data-aos-delay="700">{{ "Download CV" | translate(lang=lang) }}</a> <a class="btn btn-outline-light btn-lg shadow-sm mt-1 me-3" href="{{ download_cv_url }}" data-aos="fade-right" data-aos-delay="700">{{ "download-cv" | translate(lang=lang) }}</a>
<a class="btn btn-info btn-lg shadow-sm mt-1" href="#contact" data-aos="fade-left" data-aos-delay="700"> {{ "Hire me" | translate(lang=lang) }} </a></div> <a class="btn btn-info btn-lg shadow-sm mt-1" href="#contact" data-aos="fade-left" data-aos-delay="700"> {{ "hire-me" | translate(lang=lang) }} </a></div>
</div> </div>
</div> </div>
</div> </div>
@ -62,33 +62,33 @@
<div class="about-section"> <div class="about-section">
<div class="row"> <div class="row">
<div class="col-md-6"> <div class="col-md-6">
<h2 class="h2 fw-light mb-4">{{ "About Me" | translate(lang=lang) }} </h2> <h2 class="h2 fw-light mb-4">{{ "about-me" | translate(lang=lang) }} </h2>
<p>{{ cv.person.about | lang_entity }}</p> <p>{{ cv.person.about | lang_entity }}</p>
</div> </div>
<div class="col-md-5 offset-lg-1"> <div class="col-md-5 offset-lg-1">
<div class="row mt-2"> <div class="row mt-2">
<h2 class="h2 fw-light mb-4">Bio</h2> <h2 class="h2 fw-light mb-4">{{ "bio" | translate(lang=lang) }}</h2>
<div class="col-sm-5"> <div class="col-sm-5">
<div class="pb-2 fw-bolder"><i class="far fa-calendar-alt pe-2 text-muted" style="width:24px;opacity:0.85;"></i> Age</div> <div class="pb-2 fw-bolder"><i class="far fa-calendar-alt pe-2 text-muted" style="width:24px;opacity:0.85;"></i> {{ "age" | translate(lang=lang) }}</div>
</div> </div>
<div class="col-sm-7"> <div class="col-sm-7">
<div class="pb-2">{{ cv.person.birthday | calculate_age }}</div> <div class="pb-2">{{ cv.person.birthday | calculate_age }}</div>
</div> </div>
<div class="col-sm-5"> <div class="col-sm-5">
<div class="pb-2 fw-bolder"><i class="far fa-envelope pe-2 text-muted" style="width:24px;opacity:0.85;"></i> Email</div> <div class="pb-2 fw-bolder"><i class="far fa-envelope pe-2 text-muted" style="width:24px;opacity:0.85;"></i> {{"email" | translate(lang=lang) }}</div>
</div> </div>
<div class="col-sm-7"> <div class="col-sm-7">
<div class="pb-2"> {{ cv.person.email }} </div> <div class="pb-2"> {{ cv.person.email }} </div>
</div> </div>
<div class="col-sm-5"> <div class="col-sm-5">
<div class="pb-2 fw-bolder"><i class="fas fa-phone pe-2 text-muted" style="width:24px;opacity:0.85;"></i> Phone</div> <div class="pb-2 fw-bolder"><i class="fas fa-phone pe-2 text-muted" style="width:24px;opacity:0.85;"></i> {{ "phone" | translate(lang=lang) }}</div>
</div> </div>
<div class="col-sm-7"> <div class="col-sm-7">
<div class="pb-2">+ {{cv.person.phone | insert_space_every(times=3) }}</div> <div class="pb-2">+ {{cv.person.phone | insert_space_every(times=3) }}</div>
</div> </div>
{% if cv.person.address %} {% if cv.person.address %}
<div class="col-sm-5"> <div class="col-sm-5">
<div class="pb-2 fw-bolder"><i class="fas fa-map-marker-alt pe-2 text-muted" style="width:24px;opacity:0.85;"></i> Address</div> <div class="pb-2 fw-bolder"><i class="fas fa-map-marker-alt pe-2 text-muted" style="width:24px;opacity:0.85;"></i> {{"address" | translate(lang=lang) }}</div>
</div> </div>
<div class="col-sm-7"> <div class="col-sm-7">
<div class="pb-2">{{ cv.person.address }} </div> <div class="pb-2">{{ cv.person.address }} </div>
@ -101,7 +101,7 @@
</div> </div>
<div class="shadow-1-strong bg-white my-5 p-5" id="skills"> <div class="shadow-1-strong bg-white my-5 p-5" id="skills">
<div class="skills-section"> <div class="skills-section">
<h2 class="h2 fw-light mb-4">{{ "Professional Skills" | translate(lang=lang) }}</h2> <h2 class="h2 fw-light mb-4">{{ "professional-skills" | translate(lang=lang) }}</h2>
<div class="row"> <div class="row">
<div class="col-md-6"> <div class="col-md-6">
{% set arr_cnt = cv.skills | length %} {% set arr_cnt = cv.skills | length %}
@ -139,7 +139,7 @@
<div class="shadow-1-strong bg-white my-5 p-5" id="experience"> <div class="shadow-1-strong bg-white my-5 p-5" id="experience">
<div class="work-experience-section"> <div class="work-experience-section">
<h2 class="h2 fw-light mb-4">{{ "Professional Skills" | translate(lang=lang) }}</h2> <h2 class="h2 fw-light mb-4">{{ "work-experience" | translate(lang=lang) }}</h2>
<div class="timeline"> <div class="timeline">
{% for job in cv.jobs %} {% for job in cv.jobs %}
<div class="timeline-card timeline-card-info" data-aos="fade-in" data-aos-delay="{{ loop.index * 100 }}"> <div class="timeline-card timeline-card-info" data-aos="fade-in" data-aos-delay="{{ loop.index * 100 }}">
@ -157,7 +157,7 @@
</div> </div>
<div class="shadow-1-strong bg-white my-5 p-5" id="education"> <div class="shadow-1-strong bg-white my-5 p-5" id="education">
<div class="education-section"> <div class="education-section">
<h2 class="h2 fw-light mb-4">{{ "Education " | translate(lang=lang) }}</h2> <h2 class="h2 fw-light mb-4">{{ "education" | translate(lang=lang) }}</h2>
<div class="timeline"> <div class="timeline">
{% for education in cv.education %} {% for education in cv.education %}
<div class="timeline-card timeline-card-success" data-aos="fade-in" data-aos-delay="0"> <div class="timeline-card timeline-card-success" data-aos="fade-in" data-aos-delay="0">
@ -184,7 +184,7 @@
</div> </div>
<div class="shadow-1-strong bg-white my-5 p-5" id="contact"> <div class="shadow-1-strong bg-white my-5 p-5" id="contact">
<div class="contant-section"> <div class="contant-section">
<h2 class="h2 fw-light text mb-4">Contact</h2> <h2 class="h2 fw-light text mb-4">{{ "contact" | translate(lang=lang) }}</h2>
<div class="row mb-4"> <div class="row mb-4">
<div class="col-md-5" data-aos="fade-left" data-aos-delay="200"> <div class="col-md-5" data-aos="fade-left" data-aos-delay="200">
<div class="d-print-none"> <div class="d-print-none">