Hello,
I'm trying to utilize the example provided as a part of fluent-template crate for my app localization...
Example shows how one can define constant "language id's, and use them to translate message into specific language. So far, everything is clear and example makes sense.
Then, rust beginner (me) comes in, wants to add global static variable, to allow runtime-change-able target language selection for the translation of UI...
`std::cell::RefCell<lang::SupportedLanguage>` cannot be shared between threads safely
the trait `std::marker::Sync` is not implemented for `std::cell::RefCell<lang::SupportedLanguage>`
shared static variables must have a type that implements `Sync`rustc(E0277)
What threads?!? I mean, nowhere I even realize I could be doing stuff even remotely related to threading... I do not think i need (not sure if correctly, or i misunderstand some basic rust concepts) multiple ownership either, thus Arc/Rc seem not to be needed/related to my use-case?
The code, that is basically crate example, extended with my enum SupportedLanguages
, and static "CURRENT_LANGUAGE" to keep track of user-selected language for translations...
use fluent_templates::{Loader, static_loader};
use unic_langid::{LanguageIdentifier, langid};
use std::cell::RefCell;
pub enum SupportedLanguage {
EnglishUs,
Czech,
Russian,
}
static LI_ENGLISH: LanguageIdentifier = langid!("en-US");
static LI_CZECH: LanguageIdentifier = langid!("cz");
static LI_RUSSIAN: LanguageIdentifier = langid!("ru");
impl SupportedLanguage {
fn as_li_ptr(&self) -> &'static LanguageIdentifier {
match self {
SupportedLanguage::EnglishUs => LI_ENGLISH.as_ref(),
SupportedLanguage::Czech => LI_CZECH.as_ref(),
SupportedLanguage::Russian => LI_RUSSIAN.as_ref(),
}
}
}
static_loader! {
static LOCALES = {
locales: "./locales",
fallback_language: "en-US",
};
}
static CURRENT_LANGUAGE: RefCell<SupportedLanguage> = RefCell::new(SupportedLanguage::EnglishUs);
pub fn set_current_lang(lang: SupportedLanguage) {
CURRENT_LANGUAGE.replace(lang);
}
fn current_lang() -> SupportedLanguage {
*CURRENT_LANGUAGE.borrow()
}
pub fn translate(message: &str) -> String {
let lang_id = current_lang();
let translated = &*LOCALES.lookup(&lang_id.as_li_ptr(), message);
translated.to_string()
}
When I try to create function returning langid!()
with parametrized arg., I fail again , because macros do not work C-like apparently, and return type of this langid!() macro changes from LanguageIdentifier (as in original example) to TokenStream for some dark magic reason... (my head explodes)
Why do i get threading related error with simple enum & refcell that is supposed to work with single-threaded apps?
Why does langid!() macro seem to have LanguageIdentifier return type when used for assignment to const variable, but different return type when used as return value of function?
Did i choose the wrong approach to a static variable to keep track of target language of running app, and/or can the langid!() macro be forced somehow to return/cast into proper LaguageIdentifier that i could use to translate to specific language at runtime?
thanks a lot for guidelines...