view_engine.rs
1 use async_trait::async_trait; 2 use axum::{Extension, Router as AxumRouter}; 3 use fluent_templates::{ArcLoader, FluentLoader}; 4 use loco_rs::{ 5 app::{AppContext, Initializer}, 6 controller::views::{engines, ViewEngine}, 7 Error, Result, 8 }; 9 use tracing::info; 10 11 const I18N_DIR: &str = "assets/i18n"; 12 const I18N_SHARED: &str = "assets/i18n/shared.ftl"; 13 #[allow(clippy::module_name_repetitions)] 14 pub struct ViewEngineInitializer; 15 16 #[async_trait] 17 impl Initializer for ViewEngineInitializer { 18 fn name(&self) -> String { 19 "view-engine".to_string() 20 } 21 22 async fn after_routes(&self, router: AxumRouter, _ctx: &AppContext) -> Result<AxumRouter> { 23 #[allow(unused_mut)] 24 let mut tera_engine = engines::TeraView::build()?; 25 if std::path::Path::new(I18N_DIR).exists() { 26 let arc = ArcLoader::builder(&I18N_DIR, unic_langid::langid!("en-US")) 27 .shared_resources(Some(&[I18N_SHARED.into()])) 28 .customize(|bundle| bundle.set_use_isolating(false)) 29 .build() 30 .map_err(|e| Error::string(&e.to_string()))?; 31 #[cfg(debug_assertions)] 32 tera_engine 33 .tera 34 .lock() 35 .expect("lock") 36 .engine.register_function("t", FluentLoader::new(arc)); 37 38 #[cfg(not(debug_assertions))] 39 tera_engine 40 .tera 41 .register_function("t", FluentLoader::new(arc)); 42 info!("locales loaded"); 43 } 44 45 Ok(router.layer(Extension(ViewEngine::from(tera_engine)))) 46 } 47 }