/* This Source Code Form is subject to the terms of the Mozilla Public *License,v.2.0.IfacopyoftheMPLwasnotdistributedwiththis
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use fluent_ffi::{adapt_bundle_for_gecko, FluentBundleRc}; use nsstring::{nsACString, nsCString}; use std::mem; use std::rc::Rc; use thin_vec::ThinVec;
usecrate::{env::GeckoEnvironment, fetcher::GeckoFileFetcher, xpcom_utils::is_parent_process}; use fluent_fallback::{generator::BundleGenerator, types::ResourceType}; use futures_channel::mpsc::{unbounded, UnboundedSender}; pubuse l10nregistry::{
errors::L10nRegistrySetupError,
registry::{BundleAdapter, GenerateBundles, GenerateBundlesSync, L10nRegistry},
source::{FileSource, ResourceId, ToResourceId},
}; use unic_langid::LanguageIdentifier; use xpcom::RefPtr;
thread_local!(static L10N_REGISTRY: Rc<GeckoL10nRegistry> = { let sources = if is_parent_process() { let packaged_locales = get_packaged_locales(); let entries = get_l10n_registry_category_entries();
pubfn set_l10n_registry(new_sources: &ThinVec<L10nFileSourceDescriptor>) {
L10N_REGISTRY.with(|reg| { let new_source_names: Vec<_> = new_sources
.iter()
.map(|d| d.name.to_utf8().to_string())
.collect(); let old_sources = reg.get_source_names().unwrap();
letmut sources_to_be_removed = vec![]; for name in &old_sources { if !new_source_names.contains(&name) {
sources_to_be_removed.push(name);
}
}
reg.remove_sources(sources_to_be_removed).unwrap();
letmut add_sources = vec![]; for desc in new_sources { if !old_sources.contains(&desc.name.to_string()) {
add_sources.push(FileSource::new(
desc.name.to_string(),
Some(desc.metasource.to_string()),
desc.locales
.iter()
.map(|s| s.to_utf8().parse().unwrap())
.collect(),
desc.pre_path.to_string(),
Default::default(),
GeckoFileFetcher,
));
}
}
reg.register_sources(add_sources).unwrap();
});
}
#[no_mangle] pubunsafeextern"C"fn l10nregistry_get_parent_process_sources(
sources: &mut ThinVec<L10nFileSourceDescriptor>,
) {
debug_assert!(
is_parent_process(), "This should be called only in parent process."
);
// If at the point when the first content process is being initialized, the parent // process `L10nRegistryService` has not been initialized yet, this will trigger it. // // This is architecturally imperfect, but acceptable for simplicity reasons because // `L10nRegistry` instance is cheap and mainly servers as a store of state. let reg = get_l10n_registry(); for name in reg.get_source_names().unwrap() { let source = reg.file_source_by_name(&name).unwrap().unwrap(); let descriptor = L10nFileSourceDescriptor {
name: source.name.as_str().into(),
metasource: source.metasource.as_str().into(),
locales: source
.locales()
.iter()
.map(|l| l.to_string().into())
.collect(),
pre_path: source.pre_path.as_str().into(),
index: source
.get_index()
.map(|index| index.into_iter().map(|s| s.into()).collect())
.unwrap_or_default(),
};
sources.push(descriptor);
}
}
#[no_mangle] pubunsafeextern"C"fn l10nregistry_register_parent_process_sources(
sources: &ThinVec<L10nFileSourceDescriptor>,
) {
debug_assert!(
!is_parent_process(), "This should be called only in content process."
);
set_l10n_registry(sources);
}
#[no_mangle] pubunsafeextern"C"fn l10nregistry_addref(reg: *const GeckoL10nRegistry) { let raw = Rc::from_raw(reg);
mem::forget(Rc::clone(&raw));
mem::forget(raw);
}
match locales {
Ok(locales) => {
*status = L10nRegistryStatus::None; letmut iter = reg.bundles_stream(locales.into_iter(), res_ids);
// Immediately spawn the task which will handle the async calls, and use an `UnboundedSender` // to send callbacks for specific `next()` calls to it. let (sender, mut receiver) = unbounded::<NextRequest>();
moz_task::spawn_local("l10nregistry_generate_bundles", asyncmove { use futures::StreamExt; whilelet Some(req) = receiver.next().await { let result = match iter.next().await {
Some(Ok(result)) => Box::into_raw(Box::new(result)),
_ => std::ptr::null_mut(),
};
(req.callback)(&req.promise, result);
}
})
.detach(); let iter = GeckoFluentBundleAsyncIteratorWrapper(sender); Box::into_raw(Box::new(iter))
}
Err(_) => {
*status = L10nRegistryStatus::InvalidLocaleCode;
std::ptr::null_mut()
}
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.