зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1613705 - [localization] part7: Re-enable custom locales argument to Localization. r=nika,emilio
Depends on D113570 Differential Revision: https://phabricator.services.mozilla.com/D113571
This commit is contained in:
Родитель
e27c29555a
Коммит
791fb0ec84
|
@ -2823,7 +2823,6 @@ dependencies = [
|
|||
"futures-channel",
|
||||
"l10nregistry",
|
||||
"l10nregistry-ffi",
|
||||
"libc",
|
||||
"moz_task",
|
||||
"nserror",
|
||||
"nsstring",
|
||||
|
|
|
@ -87,14 +87,14 @@ interface Localization {
|
|||
* - aSync - Specifies if the initial state of the Localization API is synchronous.
|
||||
* This enables a number of synchronous methods on the
|
||||
* Localization API.
|
||||
* - aBundleGenerator - an object with two methods - `generateBundles` and
|
||||
* `generateBundlesSync` allowing consumers to overload the
|
||||
* default generators provided by Gecko.
|
||||
* - aRegistry - optional custom L10nRegistry to be used by this Localization instance.
|
||||
* - aLocales - custom set of locales to be used for this Localization.
|
||||
*/
|
||||
[Throws]
|
||||
constructor(sequence<UTF8String> aResourceIds,
|
||||
optional boolean aSync = false,
|
||||
optional L10nRegistry aRegistry);
|
||||
optional L10nRegistry aRegistry,
|
||||
optional sequence<UTF8String> aLocales);
|
||||
|
||||
/**
|
||||
* A method for adding resources to the localization context.
|
||||
|
|
|
@ -142,53 +142,64 @@ already_AddRefed<Localization> Localization::Create(
|
|||
|
||||
Localization::Localization(const nsTArray<nsCString>& aResIds, bool aIsSync)
|
||||
: mIsSync(aIsSync) {
|
||||
ffi::localization_new(&aResIds, mIsSync, getter_AddRefs(mRaw));
|
||||
ffi::localization_new(&aResIds, mIsSync, nullptr, getter_AddRefs(mRaw));
|
||||
|
||||
RegisterObservers();
|
||||
}
|
||||
|
||||
Localization::Localization(nsIGlobalObject* aGlobal,
|
||||
const nsTArray<nsCString>& aResIds, bool aIsSync)
|
||||
: mGlobal(aGlobal), mIsSync(aIsSync) {
|
||||
ffi::localization_new(&aResIds, mIsSync, getter_AddRefs(mRaw));
|
||||
RegisterObservers();
|
||||
}
|
||||
ffi::localization_new(&aResIds, mIsSync, nullptr, getter_AddRefs(mRaw));
|
||||
|
||||
Localization::Localization(nsIGlobalObject* aGlobal,
|
||||
const nsTArray<nsCString>& aResIds, bool aIsSync,
|
||||
const L10nRegistry& aRegistry)
|
||||
: mGlobal(aGlobal), mIsSync(aIsSync) {
|
||||
ffi::localization_new_with_reg(&aResIds, mIsSync, aRegistry.Raw(),
|
||||
getter_AddRefs(mRaw));
|
||||
RegisterObservers();
|
||||
}
|
||||
|
||||
Localization::Localization(nsIGlobalObject* aGlobal, bool aIsSync)
|
||||
: mGlobal(aGlobal), mIsSync(aIsSync) {
|
||||
nsTArray<nsCString> resIds;
|
||||
ffi::localization_new(&resIds, mIsSync, getter_AddRefs(mRaw));
|
||||
ffi::localization_new(&resIds, mIsSync, nullptr, getter_AddRefs(mRaw));
|
||||
|
||||
RegisterObservers();
|
||||
}
|
||||
|
||||
Localization::Localization(nsIGlobalObject* aGlobal)
|
||||
: mGlobal(aGlobal), mIsSync(false) {
|
||||
nsTArray<nsCString> resIds;
|
||||
ffi::localization_new(&resIds, mIsSync, getter_AddRefs(mRaw));
|
||||
Localization::Localization(nsIGlobalObject* aGlobal, bool aIsSync,
|
||||
const ffi::LocalizationRc* aRaw)
|
||||
: mGlobal(aGlobal), mRaw(aRaw), mIsSync(aIsSync) {
|
||||
RegisterObservers();
|
||||
}
|
||||
|
||||
already_AddRefed<Localization> Localization::Constructor(
|
||||
const GlobalObject& aGlobal, const Sequence<nsCString>& aResourceIds,
|
||||
bool aIsSync, const Optional<NonNull<L10nRegistry>>& aRegistry,
|
||||
ErrorResult& aRv) {
|
||||
const Optional<Sequence<nsCString>>& aLocales, ErrorResult& aRv) {
|
||||
nsTArray<nsCString> resIds = ToTArray<nsTArray<nsCString>>(aResourceIds);
|
||||
Maybe<nsTArray<nsCString>> locales;
|
||||
|
||||
if (aLocales.WasPassed()) {
|
||||
locales.emplace();
|
||||
locales->SetCapacity(aLocales.Value().Length());
|
||||
for (const auto& locale : aLocales.Value()) {
|
||||
locales->AppendElement(locale);
|
||||
}
|
||||
}
|
||||
|
||||
RefPtr<const ffi::LocalizationRc> raw;
|
||||
|
||||
bool result = ffi::localization_new_with_locales(
|
||||
&resIds, aIsSync,
|
||||
aRegistry.WasPassed() ? aRegistry.Value().Raw() : nullptr,
|
||||
locales.ptrOr(nullptr), getter_AddRefs(raw));
|
||||
|
||||
if (!result) {
|
||||
aRv.ThrowInvalidStateError(
|
||||
"Failed to create the Localization. Check the locales arguments.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
|
||||
|
||||
if (aRegistry.WasPassed()) {
|
||||
return do_AddRef(
|
||||
new Localization(global, resIds, aIsSync, aRegistry.Value()));
|
||||
} else {
|
||||
return do_AddRef(new Localization(global, resIds, aIsSync));
|
||||
}
|
||||
return do_AddRef(new Localization(global, aIsSync, raw));
|
||||
}
|
||||
|
||||
JSObject* Localization::WrapObject(JSContext* aCx,
|
||||
|
|
|
@ -38,6 +38,7 @@ class Localization : public nsIObserver,
|
|||
const dom::GlobalObject& aGlobal,
|
||||
const dom::Sequence<nsCString>& aResourceIds, bool aIsSync,
|
||||
const dom::Optional<dom::NonNull<L10nRegistry>>& aRegistry,
|
||||
const dom::Optional<dom::Sequence<nsCString>>& aLocales,
|
||||
ErrorResult& aRv);
|
||||
static already_AddRefed<Localization> Create(
|
||||
const nsTArray<nsCString>& aResourceIds, bool aIsSync);
|
||||
|
@ -79,12 +80,14 @@ class Localization : public nsIObserver,
|
|||
|
||||
protected:
|
||||
Localization(const nsTArray<nsCString>& aResIds, bool aIsSync);
|
||||
Localization(nsIGlobalObject* aGlobal, bool aIsSync);
|
||||
|
||||
Localization(nsIGlobalObject* aGlobal, const nsTArray<nsCString>& aResIds,
|
||||
bool aIsSync);
|
||||
Localization(nsIGlobalObject* aGlobal, const nsTArray<nsCString>& aResIds,
|
||||
bool aIsSync, const L10nRegistry& aRegistry);
|
||||
explicit Localization(nsIGlobalObject* aGlobal);
|
||||
Localization(nsIGlobalObject* aGlobal, bool aIsSync);
|
||||
|
||||
Localization(nsIGlobalObject* aGlobal, bool aIsSync,
|
||||
const ffi::LocalizationRc* aRaw);
|
||||
|
||||
virtual ~Localization();
|
||||
|
||||
void RegisterObservers();
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use crate::xpcom_utils::get_app_locales;
|
||||
use cstr::cstr;
|
||||
use fluent_fallback::env::LocalesProvider;
|
||||
use l10nregistry::{
|
||||
|
@ -15,12 +16,19 @@ use std::{
|
|||
ffi::CStr,
|
||||
fmt::{self, Write},
|
||||
};
|
||||
use unic_langid::LanguageIdentifier;
|
||||
use xpcom::interfaces;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct GeckoEnvironment;
|
||||
pub struct GeckoEnvironment {
|
||||
custom_locales: Option<Vec<LanguageIdentifier>>,
|
||||
}
|
||||
|
||||
impl GeckoEnvironment {
|
||||
pub fn new(custom_locales: Option<Vec<LanguageIdentifier>>) -> Self {
|
||||
Self { custom_locales }
|
||||
}
|
||||
|
||||
pub fn report_l10nregistry_setup_error(error: &L10nRegistrySetupError) {
|
||||
warn!("L10nRegistry setup error: {}", error);
|
||||
let result = log_simple_console_error(
|
||||
|
@ -72,7 +80,16 @@ impl ErrorReporter for GeckoEnvironment {
|
|||
impl LocalesProvider for GeckoEnvironment {
|
||||
type Iter = std::vec::IntoIter<unic_langid::LanguageIdentifier>;
|
||||
fn locales(&self) -> Self::Iter {
|
||||
vec!["en-US".parse().unwrap()].into_iter()
|
||||
if let Some(custom_locales) = &self.custom_locales {
|
||||
custom_locales.clone().into_iter()
|
||||
} else {
|
||||
let result = get_app_locales()
|
||||
.expect("Failed to retrieve app locales")
|
||||
.into_iter()
|
||||
.map(|s| LanguageIdentifier::from_bytes(&s).expect("Failed to parse a locale"))
|
||||
.collect::<Vec<_>>();
|
||||
result.into_iter()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -105,7 +105,7 @@ fn get_packaged_locales() -> Vec<LanguageIdentifier> {
|
|||
}
|
||||
|
||||
fn create_l10n_registry(sources: Option<Vec<FileSource>>) -> Rc<GeckoL10nRegistry> {
|
||||
let env = GeckoEnvironment;
|
||||
let env = GeckoEnvironment::new(None);
|
||||
let mut reg = L10nRegistry::with_provider(env);
|
||||
|
||||
reg.set_adapt_bundle(GeckoBundleAdapter::default())
|
||||
|
@ -166,7 +166,7 @@ pub enum L10nRegistryStatus {
|
|||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn l10nregistry_new(use_isolating: bool) -> *const GeckoL10nRegistry {
|
||||
let env = GeckoEnvironment;
|
||||
let env = GeckoEnvironment::new(None);
|
||||
let mut reg = L10nRegistry::with_provider(env);
|
||||
let _ = reg
|
||||
.set_adapt_bundle(GeckoBundleAdapter { use_isolating })
|
||||
|
|
|
@ -59,7 +59,7 @@ pub extern "C" fn l10nfilesource_new(
|
|||
FileSourceOptions { allow_override },
|
||||
GeckoFileFetcher,
|
||||
);
|
||||
source.set_reporter(GeckoEnvironment);
|
||||
source.set_reporter(GeckoEnvironment::new(None));
|
||||
|
||||
*status = L10nFileSourceStatus::None;
|
||||
Rc::into_raw(Rc::new(source))
|
||||
|
@ -113,7 +113,7 @@ pub unsafe extern "C" fn l10nfilesource_new_with_index(
|
|||
GeckoFileFetcher,
|
||||
index,
|
||||
);
|
||||
source.set_reporter(GeckoEnvironment);
|
||||
source.set_reporter(GeckoEnvironment::new(None));
|
||||
|
||||
*status = L10nFileSourceStatus::None;
|
||||
Rc::into_raw(Rc::new(source))
|
||||
|
@ -165,7 +165,7 @@ pub extern "C" fn l10nfilesource_new_mock(
|
|||
Default::default(),
|
||||
fetcher,
|
||||
);
|
||||
source.set_reporter(GeckoEnvironment);
|
||||
source.set_reporter(GeckoEnvironment::new(None));
|
||||
|
||||
*status = L10nFileSourceStatus::None;
|
||||
Rc::into_raw(Rc::new(source))
|
||||
|
|
|
@ -76,6 +76,19 @@ pub fn get_packaged_locales() -> Option<ThinVec<nsCString>> {
|
|||
Some(locales)
|
||||
}
|
||||
|
||||
pub fn get_app_locales() -> Option<ThinVec<nsCString>> {
|
||||
let locale_service =
|
||||
get_service::<mozILocaleService>(cstr!("@mozilla.org/intl/localeservice;1"))?;
|
||||
let mut locales = ThinVec::new();
|
||||
unsafe {
|
||||
locale_service
|
||||
.GetAppLocalesAsBCP47(&mut locales)
|
||||
.to_result()
|
||||
.ok()?;
|
||||
}
|
||||
Some(locales)
|
||||
}
|
||||
|
||||
pub fn set_available_locales(locales: &ThinVec<nsCString>) {
|
||||
let locale_service =
|
||||
get_service::<mozILocaleService>(cstr!("@mozilla.org/intl/localeservice;1"))
|
||||
|
|
|
@ -7,7 +7,6 @@ edition = "2018"
|
|||
[dependencies]
|
||||
futures-channel = "0.3"
|
||||
futures = "0.3"
|
||||
libc = "0.2"
|
||||
nserror = { path = "../../../../xpcom/rust/nserror" }
|
||||
nsstring = { path = "../../../../xpcom/rust/nsstring" }
|
||||
l10nregistry = { git = "https://github.com/zbraniecki/l10nregistry-rs", rev = "92d8fbfbbbdffa2047ce01a935a389eb11031f69" }
|
||||
|
|
|
@ -15,10 +15,11 @@ use l10nregistry_ffi::{
|
|||
env::GeckoEnvironment,
|
||||
registry::{get_l10n_registry, GeckoL10nRegistry},
|
||||
};
|
||||
use nserror::{nsresult, NS_OK};
|
||||
use nsstring::{nsACString, nsCString};
|
||||
use std::os::raw::c_void;
|
||||
use std::{borrow::Cow, cell::RefCell};
|
||||
use thin_vec::ThinVec;
|
||||
use unic_langid::LanguageIdentifier;
|
||||
use xpcom::{interfaces::nsrefcnt, RefCounted, RefPtr, Refcnt};
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -127,8 +128,19 @@ unsafe impl RefCounted for LocalizationRc {
|
|||
}
|
||||
|
||||
impl LocalizationRc {
|
||||
pub fn new(reg: &GeckoL10nRegistry, res_ids: Vec<String>, is_sync: bool) -> RefPtr<Self> {
|
||||
let inner = Localization::with_env(res_ids, is_sync, GeckoEnvironment, reg.clone());
|
||||
pub fn new(
|
||||
res_ids: Vec<String>,
|
||||
is_sync: bool,
|
||||
registry: Option<&GeckoL10nRegistry>,
|
||||
locales: Option<Vec<LanguageIdentifier>>,
|
||||
) -> RefPtr<Self> {
|
||||
let env = GeckoEnvironment::new(locales);
|
||||
let inner = if let Some(reg) = registry {
|
||||
Localization::with_env(res_ids, is_sync, env, reg.clone())
|
||||
} else {
|
||||
let reg = (*get_l10n_registry()).clone();
|
||||
Localization::with_env(res_ids, is_sync, env, reg)
|
||||
};
|
||||
|
||||
let loc = Box::new(LocalizationRc {
|
||||
inner: RefCell::new(inner),
|
||||
|
@ -393,30 +405,50 @@ impl LocalizationRc {
|
|||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn localization_new(
|
||||
res_ids: &ThinVec<nsCString>,
|
||||
is_sync: bool,
|
||||
result: &mut *const LocalizationRc,
|
||||
) -> nsresult {
|
||||
*result = std::ptr::null();
|
||||
|
||||
let reg = get_l10n_registry();
|
||||
let res_ids: Vec<String> = res_ids.iter().map(|res| res.to_string()).collect();
|
||||
*result = RefPtr::forget_into_raw(LocalizationRc::new(®, res_ids, is_sync));
|
||||
NS_OK
|
||||
pub extern "C" fn localization_parse_locale(input: &nsCString) -> *const c_void {
|
||||
let l: LanguageIdentifier = input.to_utf8().parse().unwrap();
|
||||
Box::into_raw(Box::new(l)) as *const c_void
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn localization_new_with_reg(
|
||||
pub extern "C" fn localization_new(
|
||||
res_ids: &ThinVec<nsCString>,
|
||||
is_sync: bool,
|
||||
reg: &GeckoL10nRegistry,
|
||||
reg: Option<&GeckoL10nRegistry>,
|
||||
result: &mut *const LocalizationRc,
|
||||
) {
|
||||
*result = std::ptr::null_mut();
|
||||
*result = std::ptr::null();
|
||||
|
||||
let res_ids: Vec<String> = res_ids.iter().map(|res| res.to_string()).collect();
|
||||
*result = RefPtr::forget_into_raw(LocalizationRc::new(®, res_ids, is_sync));
|
||||
*result = RefPtr::forget_into_raw(LocalizationRc::new(res_ids, is_sync, reg, None));
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn localization_new_with_locales(
|
||||
res_ids: &ThinVec<nsCString>,
|
||||
is_sync: bool,
|
||||
reg: Option<&GeckoL10nRegistry>,
|
||||
locales: Option<&ThinVec<nsCString>>,
|
||||
result: &mut *const LocalizationRc,
|
||||
) -> bool {
|
||||
*result = std::ptr::null();
|
||||
|
||||
let res_ids: Vec<String> = res_ids.iter().map(|res| res.to_string()).collect();
|
||||
let locales: Result<Option<Vec<LanguageIdentifier>>, _> = locales
|
||||
.map(|locales| {
|
||||
locales
|
||||
.iter()
|
||||
.map(|s| LanguageIdentifier::from_bytes(&s))
|
||||
.collect()
|
||||
})
|
||||
.transpose();
|
||||
|
||||
if let Ok(locales) = locales {
|
||||
*result = RefPtr::forget_into_raw(LocalizationRc::new(res_ids, is_sync, reg, locales));
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
|
Загрузка…
Ссылка в новой задаче