Improve built-in services
This commit is contained in:
parent
b7ed5d1e1c
commit
ed5f96361b
9 changed files with 276 additions and 51 deletions
|
@ -1,5 +1,5 @@
|
||||||
mod registry;
|
mod registry;
|
||||||
pub use registry::{ServiceRegistry, StaticServiceRegistry};
|
pub use registry::{/*ServiceRegistry, */StaticServiceRegistry};
|
||||||
|
|
||||||
mod websocket_stream;
|
mod websocket_stream;
|
||||||
pub use websocket_stream::ws_stream;
|
pub use websocket_stream::ws_stream;
|
||||||
|
|
|
@ -37,7 +37,7 @@ impl<'a> ServiceRegistry<'a> {
|
||||||
pub fn with_builtins() -> Self {
|
pub fn with_builtins() -> Self {
|
||||||
let mut reg = Self::default();
|
let mut reg = Self::default();
|
||||||
reg.register(crate::services::usdpl::DevToolsServer::new(crate::services_impl::DevTools{}))
|
reg.register(crate::services::usdpl::DevToolsServer::new(crate::services_impl::DevTools{}))
|
||||||
.register(crate::services::usdpl::TranslationsServer::new(crate::services_impl::Translations{}));
|
.register(crate::services::usdpl::TranslationsServer::new(crate::services_impl::Translations::new()));
|
||||||
reg
|
reg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,20 @@ impl<'a> generated::IDevTools<'a> for DevTools {
|
||||||
lvl if lvl == generated::LogLevel::Error as _ => log::error!("{}", input.msg),
|
lvl if lvl == generated::LogLevel::Error as _ => log::error!("{}", input.msg),
|
||||||
lvl => return Err(Box::<dyn std::error::Error + Send + Sync>::from(format!("Unexpected input log level {}", lvl)))
|
lvl => return Err(Box::<dyn std::error::Error + Send + Sync>::from(format!("Unexpected input log level {}", lvl)))
|
||||||
}
|
}
|
||||||
Ok(generated::Empty{ ok: true })
|
Ok(generated::Empty{})
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn echo(
|
||||||
|
&mut self,
|
||||||
|
input: generated::Ok,
|
||||||
|
) -> Result<generated::Ok, Box<dyn std::error::Error + Send>> {
|
||||||
|
Ok(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn version(
|
||||||
|
&mut self,
|
||||||
|
_: generated::Empty
|
||||||
|
) -> Result<generated::VersionString, Box<dyn std::error::Error + Send>> {
|
||||||
|
Ok(generated::VersionString { version: env!("CARGO_PKG_VERSION").to_owned() })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,30 @@
|
||||||
use crate::services::usdpl as generated;
|
use crate::services::usdpl as generated;
|
||||||
|
|
||||||
/// Built-in translation service implementation
|
/// Built-in translation service implementation
|
||||||
pub(crate) struct Translations {}
|
pub(crate) struct Translations {
|
||||||
|
catalogs: async_lock::RwLock<std::collections::HashMap<String, gettext_ng::Catalog>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Translations {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
catalogs: async_lock::RwLock::new(std::collections::HashMap::new()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_catalog(&self, lang: &str) -> Result<gettext_ng::Catalog, gettext_ng::Error> {
|
||||||
|
let catalogs_rlock = self.catalogs.read().await;
|
||||||
|
if let Some(catalog) = catalogs_rlock.get(lang) {
|
||||||
|
Ok(catalog.to_owned())
|
||||||
|
} else {
|
||||||
|
drop(catalogs_rlock);
|
||||||
|
let catalog = load_locale(lang)?;
|
||||||
|
let mut catalogs_wlock = self.catalogs.write().await;
|
||||||
|
catalogs_wlock.insert(lang.to_owned(), catalog.clone());
|
||||||
|
Ok(catalog)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl<'a> generated::ITranslations<'a> for Translations {
|
impl<'a> generated::ITranslations<'a> for Translations {
|
||||||
|
@ -9,12 +32,12 @@ impl<'a> generated::ITranslations<'a> for Translations {
|
||||||
&mut self,
|
&mut self,
|
||||||
input: generated::LanguageRequest,
|
input: generated::LanguageRequest,
|
||||||
) -> Result<generated::TranslationsReply, Box<dyn std::error::Error + Send>> {
|
) -> Result<generated::TranslationsReply, Box<dyn std::error::Error + Send>> {
|
||||||
let catalog = load_locale(&input.lang).map_err(|e| Box::new(e) as _)?;
|
let catalog = self.get_catalog(&input.lang).await.map_err(|e| Box::new(e) as _)?;
|
||||||
let catalog_map = catalog.nalltext();
|
let catalog_map = catalog.nalltext();
|
||||||
let mut map = std::collections::HashMap::with_capacity(catalog_map.len());
|
let mut map = std::collections::HashMap::with_capacity(catalog_map.len());
|
||||||
for (key, val) in catalog_map.into_iter() {
|
for (key, val) in catalog_map.into_iter() {
|
||||||
if val.len() > 1 {
|
if val.len() > 1 {
|
||||||
log::warn!("Translations key {} for language {} has plural entries which aren't currently supported", key, input.lang);
|
log::warn!("Translations key {} for language {} has plural entries which aren't supported by Translations::get_language(...)", key, input.lang);
|
||||||
}
|
}
|
||||||
if let Some(val_0) = val.get(0) {
|
if let Some(val_0) = val.get(0) {
|
||||||
map.insert(key.to_owned(), val_0.to_owned());
|
map.insert(key.to_owned(), val_0.to_owned());
|
||||||
|
@ -22,6 +45,20 @@ impl<'a> generated::ITranslations<'a> for Translations {
|
||||||
}
|
}
|
||||||
Ok(generated::TranslationsReply { translations: map })
|
Ok(generated::TranslationsReply { translations: map })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn get_translation(
|
||||||
|
&mut self,
|
||||||
|
input: generated::TranslationRequest,
|
||||||
|
) -> Result<generated::TranslatedString, Box<dyn std::error::Error + Send>> {
|
||||||
|
let catalog = self.get_catalog(&input.lang).await.map_err(|e| Box::new(e) as _)?;
|
||||||
|
let translated = if input.count == 0 {
|
||||||
|
catalog.gettext(&input.msg_id)
|
||||||
|
} else {
|
||||||
|
catalog.ngettext(&input.msg_id, &input.msg_id, input.count)
|
||||||
|
}.to_owned();
|
||||||
|
let is_default = translated == input.msg_id;
|
||||||
|
Ok(generated::TranslatedString { translated, is_default, uuid: input.uuid })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_locale(lang: &str) -> Result<gettext_ng::Catalog, gettext_ng::Error> {
|
fn load_locale(lang: &str) -> Result<gettext_ng::Catalog, gettext_ng::Error> {
|
||||||
|
|
|
@ -2,10 +2,16 @@ syntax = "proto3";
|
||||||
|
|
||||||
package usdpl;
|
package usdpl;
|
||||||
|
|
||||||
// The translation service
|
// The tools service
|
||||||
service DevTools {
|
service DevTools {
|
||||||
// Retrieves all translations for the provided 4-letter code
|
// Write a message to the back-end log
|
||||||
rpc Log (LogMessage) returns (Empty);
|
rpc Log (LogMessage) returns (Empty);
|
||||||
|
|
||||||
|
// Echo a message through the back-end
|
||||||
|
rpc Echo (Ok) returns (Ok);
|
||||||
|
|
||||||
|
// Retrieve the USDPL version
|
||||||
|
rpc Version (Empty) returns (VersionString);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum LogLevel {
|
enum LogLevel {
|
||||||
|
@ -22,6 +28,12 @@ message LogMessage {
|
||||||
string msg = 2;
|
string msg = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
message Empty {
|
message Empty {}
|
||||||
|
|
||||||
|
message Ok {
|
||||||
bool ok = 1;
|
bool ok = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message VersionString {
|
||||||
|
string version = 1;
|
||||||
|
}
|
||||||
|
|
|
@ -5,7 +5,9 @@ package usdpl;
|
||||||
// The translation service
|
// The translation service
|
||||||
service Translations {
|
service Translations {
|
||||||
// Retrieves all translations for the provided 4-letter code
|
// Retrieves all translations for the provided 4-letter code
|
||||||
rpc GetLanguage (LanguageRequest) returns (TranslationsReply) {}
|
rpc GetLanguage (LanguageRequest) returns (TranslationsReply);
|
||||||
|
/// Retrieve a specific translation
|
||||||
|
rpc GetTranslation(TranslationRequest) returns (TranslatedString);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The request message containing the language code
|
// The request message containing the language code
|
||||||
|
@ -17,3 +19,17 @@ message LanguageRequest {
|
||||||
message TranslationsReply {
|
message TranslationsReply {
|
||||||
map<string, string> translations = 1;
|
map<string, string> translations = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The request message for a specific translated string
|
||||||
|
message TranslationRequest {
|
||||||
|
string lang = 1;
|
||||||
|
string msg_id = 2;
|
||||||
|
uint64 count = 3;
|
||||||
|
uint64 uuid = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message TranslatedString {
|
||||||
|
string translated = 1;
|
||||||
|
bool is_default = 2;
|
||||||
|
uint64 uuid = 3;
|
||||||
|
}
|
||||||
|
|
|
@ -93,8 +93,36 @@ fn generate_service_methods(
|
||||||
Some(x2.into_wasm())
|
Some(x2.into_wasm())
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
// log error
|
if let Some(e_handler) = &self.error_handler {
|
||||||
log::error!("service:{}|method:{}|error:{}", self.service.descriptor(), #method_name_str, e);
|
let error_info = js_sys::Object::new();
|
||||||
|
js_sys::Reflect::set(
|
||||||
|
&error_info,
|
||||||
|
&JsValue::from("service"),
|
||||||
|
&JsValue::from(self.service.descriptor())
|
||||||
|
).unwrap();
|
||||||
|
js_sys::Reflect::set(
|
||||||
|
&error_info,
|
||||||
|
&JsValue::from("method"),
|
||||||
|
&JsValue::from(#method_name_str)
|
||||||
|
).unwrap();
|
||||||
|
js_sys::Reflect::set(
|
||||||
|
&error_info,
|
||||||
|
&JsValue::from("error"),
|
||||||
|
&JsValue::from("todo"/*TODO*/)
|
||||||
|
).unwrap();
|
||||||
|
if let Err(call_e) = e_handler.call1(&JsValue::UNDEFINED, &error_info) {
|
||||||
|
// log error
|
||||||
|
log::error!("service:{}|method:{}|error:{}|js error:{}", self.service.descriptor(), #method_name_str, e,
|
||||||
|
if let Some(s) = call_e.as_string() {
|
||||||
|
s
|
||||||
|
} else {
|
||||||
|
format!("{:?}", call_e)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// log error
|
||||||
|
log::error!("service:{}|method:{}|error:{}", self.service.descriptor(), #method_name_str, e);
|
||||||
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,8 +144,36 @@ fn generate_service_methods(
|
||||||
Some(x2.into_wasm())
|
Some(x2.into_wasm())
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
// log error
|
if let Some(e_handler) = &self.error_handler {
|
||||||
log::error!("service:{}|method:{}|error:{}", self.service.descriptor(), #method_name_str, e);
|
let error_info = js_sys::Object::new();
|
||||||
|
js_sys::Reflect::set(
|
||||||
|
&error_info,
|
||||||
|
&JsValue::from("service"),
|
||||||
|
&JsValue::from(self.service.descriptor())
|
||||||
|
).unwrap();
|
||||||
|
js_sys::Reflect::set(
|
||||||
|
&error_info,
|
||||||
|
&JsValue::from("method"),
|
||||||
|
&JsValue::from(#method_name_str)
|
||||||
|
).unwrap();
|
||||||
|
js_sys::Reflect::set(
|
||||||
|
&error_info,
|
||||||
|
&JsValue::from("error"),
|
||||||
|
&JsValue::from("todo"/*TODO*/)
|
||||||
|
).unwrap();
|
||||||
|
if let Err(call_e) = e_handler.call1(&JsValue::UNDEFINED, &error_info) {
|
||||||
|
// log error
|
||||||
|
log::error!("service:{}|method:{}|error:{}|js error:{}", self.service.descriptor(), #method_name_str, e,
|
||||||
|
if let Some(s) = call_e.as_string() {
|
||||||
|
s
|
||||||
|
} else {
|
||||||
|
format!("{:?}", call_e)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// log error
|
||||||
|
log::error!("service:{}|method:{}|error:{}", self.service.descriptor(), #method_name_str, e);
|
||||||
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -179,7 +235,35 @@ fn generate_service_methods(
|
||||||
while let Some(next_result) = x.next().await {
|
while let Some(next_result) = x.next().await {
|
||||||
match next_result {
|
match next_result {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::error!("service:{}|method:{}|error:{}", self.service.descriptor(), #method_name_str, e);
|
if let Some(e_handler) = &self.error_handler {
|
||||||
|
let error_info = js_sys::Object::new();
|
||||||
|
js_sys::Reflect::set(
|
||||||
|
&error_info,
|
||||||
|
&JsValue::from("service"),
|
||||||
|
&JsValue::from(self.service.descriptor())
|
||||||
|
).unwrap();
|
||||||
|
js_sys::Reflect::set(
|
||||||
|
&error_info,
|
||||||
|
&JsValue::from("method"),
|
||||||
|
&JsValue::from(#method_name_str)
|
||||||
|
).unwrap();
|
||||||
|
js_sys::Reflect::set(
|
||||||
|
&error_info,
|
||||||
|
&JsValue::from("error"),
|
||||||
|
&JsValue::from("todo"/*TODO*/)
|
||||||
|
).unwrap();
|
||||||
|
if let Err(call_e) = e_handler.call1(&JsValue::UNDEFINED, &error_info) {
|
||||||
|
// log error
|
||||||
|
log::error!("service:{}|method:{}|error:{}|js error:{}", self.service.descriptor(), #method_name_str, e,
|
||||||
|
if let Some(s) = call_e.as_string() {
|
||||||
|
s
|
||||||
|
} else {
|
||||||
|
format!("{:?}", call_e)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log::error!("service:{}|method:{}|error:{}", self.service.descriptor(), #method_name_str, e);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
Ok(item) => {
|
Ok(item) => {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
@ -208,8 +292,36 @@ fn generate_service_methods(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
// log error
|
if let Some(e_handler) = &self.error_handler {
|
||||||
log::error!("service:{}|method:{}|error:{}", self.service.descriptor(), #method_name_str, e);
|
let error_info = js_sys::Object::new();
|
||||||
|
js_sys::Reflect::set(
|
||||||
|
&error_info,
|
||||||
|
&JsValue::from("service"),
|
||||||
|
&JsValue::from(self.service.descriptor())
|
||||||
|
).unwrap();
|
||||||
|
js_sys::Reflect::set(
|
||||||
|
&error_info,
|
||||||
|
&JsValue::from("method"),
|
||||||
|
&JsValue::from(#method_name_str)
|
||||||
|
).unwrap();
|
||||||
|
js_sys::Reflect::set(
|
||||||
|
&error_info,
|
||||||
|
&JsValue::from("error"),
|
||||||
|
&JsValue::from("todo"/*TODO*/)
|
||||||
|
).unwrap();
|
||||||
|
if let Err(call_e) = e_handler.call1(&JsValue::UNDEFINED, &error_info) {
|
||||||
|
// log error
|
||||||
|
log::error!("service:{}|method:{}|error:{}|js error:{}", self.service.descriptor(), #method_name_str, e,
|
||||||
|
if let Some(s) = call_e.as_string() {
|
||||||
|
s
|
||||||
|
} else {
|
||||||
|
format!("{:?}", call_e)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// log error
|
||||||
|
log::error!("service:{}|method:{}|error:{}", self.service.descriptor(), #method_name_str, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -229,7 +341,35 @@ fn generate_service_methods(
|
||||||
while let Some(next_result) = x.next().await {
|
while let Some(next_result) = x.next().await {
|
||||||
match next_result {
|
match next_result {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::error!("service:{}|method:{}|error:{}", self.service.descriptor(), #method_name_str, e);
|
if let Some(e_handler) = &self.error_handler {
|
||||||
|
let error_info = js_sys::Object::new();
|
||||||
|
js_sys::Reflect::set(
|
||||||
|
&error_info,
|
||||||
|
&JsValue::from("service"),
|
||||||
|
&JsValue::from(self.service.descriptor())
|
||||||
|
).unwrap();
|
||||||
|
js_sys::Reflect::set(
|
||||||
|
&error_info,
|
||||||
|
&JsValue::from("method"),
|
||||||
|
&JsValue::from(#method_name_str)
|
||||||
|
).unwrap();
|
||||||
|
js_sys::Reflect::set(
|
||||||
|
&error_info,
|
||||||
|
&JsValue::from("error"),
|
||||||
|
&JsValue::from("todo"/*TODO*/)
|
||||||
|
).unwrap();
|
||||||
|
if let Err(call_e) = e_handler.call1(&JsValue::UNDEFINED, &error_info) {
|
||||||
|
// log error
|
||||||
|
log::error!("service:{}|method:{}|error:{}|js error:{}", self.service.descriptor(), #method_name_str, e,
|
||||||
|
if let Some(s) = call_e.as_string() {
|
||||||
|
s
|
||||||
|
} else {
|
||||||
|
format!("{:?}", call_e)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log::error!("service:{}|method:{}|error:{}", self.service.descriptor(), #method_name_str, e);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
Ok(item) => {
|
Ok(item) => {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
@ -258,8 +398,36 @@ fn generate_service_methods(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
// log error
|
if let Some(e_handler) = &self.error_handler {
|
||||||
log::error!("service:{}|method:{}|error:{}", self.service.descriptor(), #method_name_str, e);
|
let error_info = js_sys::Object::new();
|
||||||
|
js_sys::Reflect::set(
|
||||||
|
&error_info,
|
||||||
|
&JsValue::from("service"),
|
||||||
|
&JsValue::from(self.service.descriptor())
|
||||||
|
).unwrap();
|
||||||
|
js_sys::Reflect::set(
|
||||||
|
&error_info,
|
||||||
|
&JsValue::from("method"),
|
||||||
|
&JsValue::from(#method_name_str)
|
||||||
|
).unwrap();
|
||||||
|
js_sys::Reflect::set(
|
||||||
|
&error_info,
|
||||||
|
&JsValue::from("error"),
|
||||||
|
&JsValue::from("todo"/*TODO*/)
|
||||||
|
).unwrap();
|
||||||
|
if let Err(call_e) = e_handler.call1(&JsValue::UNDEFINED, &error_info) {
|
||||||
|
// log error
|
||||||
|
log::error!("service:{}|method:{}|error:{}|js error:{}", self.service.descriptor(), #method_name_str, e,
|
||||||
|
if let Some(s) = call_e.as_string() {
|
||||||
|
s
|
||||||
|
} else {
|
||||||
|
format!("{:?}", call_e)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// log error
|
||||||
|
log::error!("service:{}|method:{}|error:{}", self.service.descriptor(), #method_name_str, e);
|
||||||
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1088,11 +1256,12 @@ impl IServiceGenerator for WasmServiceGenerator {
|
||||||
|
|
||||||
#service_types
|
#service_types
|
||||||
|
|
||||||
/// WASM/JS-compatible wrapper of the Rust nRPC service
|
/// WASM/JS-compatible wrapper of a Rust nRPC service
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
pub struct #service_js_name {
|
pub struct #service_js_name {
|
||||||
//#[wasm_bindgen(skip)]
|
//#[wasm_bindgen(skip)]
|
||||||
service: super::#service_struct_name<'static, WebSocketHandler>,
|
service: super::#service_struct_name<'static, WebSocketHandler>,
|
||||||
|
error_handler: Option<js_sys::Function>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
|
@ -1106,9 +1275,15 @@ impl IServiceGenerator for WasmServiceGenerator {
|
||||||
log::info!("Initialized ws service {} on port {}", #service_str_name, port);
|
log::info!("Initialized ws service {} on port {}", #service_str_name, port);
|
||||||
Self {
|
Self {
|
||||||
service: implementation,
|
service: implementation,
|
||||||
|
error_handler: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn on_error(&mut self, handler: Option<js_sys::Function>) {
|
||||||
|
self.error_handler = handler;
|
||||||
|
}
|
||||||
|
|
||||||
#service_methods
|
#service_methods
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ mod api_decky;
|
||||||
/// This contains functionality used in both the back-end and front-end.
|
/// This contains functionality used in both the back-end and front-end.
|
||||||
pub mod api {
|
pub mod api {
|
||||||
#[cfg(not(any(feature = "decky")))]
|
#[cfg(not(any(feature = "decky")))]
|
||||||
|
#[allow(unused_imports)]
|
||||||
pub use super::api_any::*;
|
pub use super::api_any::*;
|
||||||
pub use super::api_common::*;
|
pub use super::api_common::*;
|
||||||
#[cfg(all(feature = "decky", not(any(feature = "any"))))]
|
#[cfg(all(feature = "decky", not(any(feature = "any"))))]
|
||||||
|
|
|
@ -32,8 +32,6 @@ const DEFAULT_LOGGER: console_logs::BuiltInLogger = console_logs::BuiltInLogger:
|
||||||
|
|
||||||
static mut CACHE: Option<std::collections::HashMap<String, JsValue>> = None;
|
static mut CACHE: Option<std::collections::HashMap<String, JsValue>> = None;
|
||||||
|
|
||||||
static mut TRANSLATIONS: Option<std::collections::HashMap<String, Vec<String>>> = None;
|
|
||||||
|
|
||||||
#[cfg(feature = "encrypt")]
|
#[cfg(feature = "encrypt")]
|
||||||
fn encryption_key() -> Vec<u8> {
|
fn encryption_key() -> Vec<u8> {
|
||||||
hex::decode(obfstr::obfstr!(env!("USDPL_ENCRYPTION_KEY"))).unwrap()
|
hex::decode(obfstr::obfstr!(env!("USDPL_ENCRYPTION_KEY"))).unwrap()
|
||||||
|
@ -111,31 +109,3 @@ pub fn get_value(key: String) -> JsValue {
|
||||||
.unwrap_or(JsValue::UNDEFINED)
|
.unwrap_or(JsValue::UNDEFINED)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Translate a phrase, equivalent to tr_n(msg_id, 0)
|
|
||||||
#[wasm_bindgen]
|
|
||||||
pub fn tr(msg_id: String) -> String {
|
|
||||||
if let Some(translations) = unsafe { TRANSLATIONS.as_ref().unwrap().get(&msg_id) } {
|
|
||||||
if let Some(translated) = translations.get(0) {
|
|
||||||
translated.to_owned()
|
|
||||||
} else {
|
|
||||||
msg_id
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
msg_id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Translate a phrase, retrieving the plural form for `n` items
|
|
||||||
#[wasm_bindgen]
|
|
||||||
pub fn tr_n(msg_id: String, n: usize) -> String {
|
|
||||||
if let Some(translations) = unsafe { TRANSLATIONS.as_ref().unwrap().get(&msg_id) } {
|
|
||||||
if let Some(translated) = translations.get(n) {
|
|
||||||
translated.to_owned()
|
|
||||||
} else {
|
|
||||||
msg_id
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
msg_id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue