Bug 1346617 - Add LocaleService::SetRequestedLocales. r=jfkthame
MozReview-Commit-ID: FrziO9fOs3R
--- a/intl/locale/LocaleService.cpp
+++ b/intl/locale/LocaleService.cpp
@@ -138,18 +138,16 @@ LocaleService::GetAppLocalesAsBCP47(nsTA
}
}
bool
LocaleService::GetRequestedLocales(nsTArray<nsCString>& aRetVal)
{
nsAutoCString locale;
- nsCOMPtr<nsIPrefBranch> prefs(do_GetService("@mozilla.org/preferences-service;1"));
-
// First, we'll try to check if the user has `matchOS` pref selected
bool matchOSLocale = Preferences::GetBool(MATCH_OS_LOCALE_PREF);
if (matchOSLocale) {
// If he has, we'll pick the locale from the system
if (OSPreferences::GetInstance()->GetSystemLocales(aRetVal)) {
// If we succeeded, return.
return true;
@@ -158,17 +156,16 @@ LocaleService::GetRequestedLocales(nsTAr
// Otherwise, we'll try to get the requested locale from the prefs.
// In some cases, mainly on Fennec and on Linux version,
// `general.useragent.locale` is a special 'localized' value, like:
// "chrome://global/locale/intl.properties"
if (!NS_SUCCEEDED(Preferences::GetLocalizedCString(SELECTED_LOCALE_PREF, &locale))) {
// If not, we can attempt to retrieve it as a simple string value.
- //rv = prefs->GetCharPref(SELECTED_LOCALE_PREF, getter_Copies(locale));
if (!NS_SUCCEEDED(Preferences::GetCString(SELECTED_LOCALE_PREF, &locale))) {
return false;
}
}
// At the moment we just take a single locale, but in the future
// we'll want to allow user to specify a list of requested locales.
aRetVal.AppendElement(locale);
@@ -636,8 +633,24 @@ LocaleService::GetRequestedLocales(uint3
return NS_ERROR_FAILURE;
}
*aCount = requestedLocales.Length();
*aOutArray = CreateOutArray(requestedLocales);
return NS_OK;
}
+
+NS_IMETHODIMP
+LocaleService::SetRequestedLocales(const char** aRequested,
+ uint32_t aRequestedCount)
+{
+ MOZ_ASSERT(aRequestedCount < 2, "We can only handle one requested locale");
+
+ if (aRequestedCount == 0) {
+ Preferences::ClearUser(SELECTED_LOCALE_PREF);
+ } else {
+ Preferences::SetCString(SELECTED_LOCALE_PREF, aRequested[0]);
+ }
+
+ Preferences::SetBool(MATCH_OS_LOCALE_PREF, aRequestedCount == 0);
+ return NS_OK;
+}
--- a/intl/locale/LocaleService.h
+++ b/intl/locale/LocaleService.h
@@ -1,17 +1,16 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode:nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */
#ifndef mozilla_intl_LocaleService_h__
#define mozilla_intl_LocaleService_h__
-#include "mozilla/StaticPtr.h"
#include "nsIObserver.h"
#include "nsString.h"
#include "nsTArray.h"
#include "mozILocaleService.h"
namespace mozilla {
namespace intl {
--- a/intl/locale/mozILocaleService.idl
+++ b/intl/locale/mozILocaleService.idl
@@ -128,9 +128,28 @@ interface mozILocaleService : nsISupport
*
* The result is an ordered list of locale IDs which should be
* used as a requestedLocales input list for language negotiation.
*
* Example: ["en-US", "de", "pl", "sr-Cyrl", "zh-Hans-HK"]
*/
void getRequestedLocales([optional] out unsigned long aCount,
[retval, array, size_is(aCount)] out string aLocales);
+
+ /**
+ * Sets a list of locales that the user requested the app to be
+ * localized to.
+ *
+ * The argument is an ordered list of locale IDs which should be
+ * used as a requestedLocales input list for language negotiation.
+ *
+ * The current implementation is limited to handle at most one
+ * locale passed to the API. In the future we'll transition to support
+ * whole fallback chain.
+ *
+ * If an empty list is passed, the list of requested locales will
+ * be picked from the operating system.
+ *
+ * Example: ["de"]
+ */
+ void setRequestedLocales([array, size_is(aRequestedCount)] in string aRequested,
+ [optional] in unsigned long aRequestedCount);
};
--- a/intl/locale/tests/unit/test_localeService.js
+++ b/intl/locale/tests/unit/test_localeService.js
@@ -5,33 +5,29 @@
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
const { Services } = Cu.import('resource://gre/modules/Services.jsm', {});
const osPrefs = Cc["@mozilla.org/intl/ospreferences;1"].
getService(Ci.mozIOSPreferences);
+const localeService =
+ Components.classes["@mozilla.org/intl/localeservice;1"]
+ .getService(Components.interfaces.mozILocaleService);
+
/**
* Make sure the locale service can be instantiated.
*/
function run_test()
{
- const localeService =
- Components.classes["@mozilla.org/intl/localeservice;1"]
- .getService(Components.interfaces.mozILocaleService);
-
run_next_test();
}
add_test(function test_getAppLocalesAsLangTags() {
- const localeService =
- Components.classes["@mozilla.org/intl/localeservice;1"]
- .getService(Components.interfaces.mozILocaleService);
-
const appLocale = localeService.getAppLocaleAsLangTag();
do_check_true(appLocale != "", "appLocale is non-empty");
const appLocales = localeService.getAppLocalesAsLangTags();
do_check_true(Array.isArray(appLocales), "appLocales returns an array");
do_check_true(appLocale == appLocales[0], "appLocale matches first entry in appLocales");
@@ -41,20 +37,16 @@ add_test(function test_getAppLocalesAsLa
run_next_test();
});
const PREF_MATCH_OS_LOCALE = "intl.locale.matchOS";
const PREF_SELECTED_LOCALE = "general.useragent.locale";
const REQ_LOC_CHANGE_EVENT = "intl:requested-locales-changed";
add_test(function test_getRequestedLocales() {
- const localeService =
- Components.classes["@mozilla.org/intl/localeservice;1"]
- .getService(Components.interfaces.mozILocaleService);
-
const requestedLocales = localeService.getRequestedLocales();
do_check_true(Array.isArray(requestedLocales), "requestedLocales returns an array");
run_next_test();
});
/**
* In this test we verify that after we set an observer on the LocaleService
@@ -62,20 +54,16 @@ add_test(function test_getRequestedLocal
* pref for matchOS is set to true.
*
* Then, we test that when the matchOS is set to true, we will retrieve
* OS locale from getRequestedLocales.
*/
add_test(function test_getRequestedLocales_matchOS() {
do_test_pending();
- const localeService =
- Components.classes["@mozilla.org/intl/localeservice;1"]
- .getService(Components.interfaces.mozILocaleService);
-
Services.prefs.setBoolPref(PREF_MATCH_OS_LOCALE, false);
Services.prefs.setCharPref(PREF_SELECTED_LOCALE, "ar-IR");
const observer = {
observe: function (aSubject, aTopic, aData) {
switch (aTopic) {
case REQ_LOC_CHANGE_EVENT:
const reqLocs = localeService.getRequestedLocales();
@@ -95,20 +83,16 @@ add_test(function test_getRequestedLocal
/**
* In this test we verify that after we set an observer on the LocaleService
* event for requested locales change, it will be fired when the
* pref for browser UI locale changes.
*/
add_test(function test_getRequestedLocales_matchOS() {
do_test_pending();
- const localeService =
- Components.classes["@mozilla.org/intl/localeservice;1"]
- .getService(Components.interfaces.mozILocaleService);
-
Services.prefs.setBoolPref(PREF_MATCH_OS_LOCALE, false);
Services.prefs.setCharPref(PREF_SELECTED_LOCALE, "ar-IR");
const observer = {
observe: function (aSubject, aTopic, aData) {
switch (aTopic) {
case REQ_LOC_CHANGE_EVENT:
const reqLocs = localeService.getRequestedLocales();
@@ -120,12 +104,28 @@ add_test(function test_getRequestedLocal
};
Services.obs.addObserver(observer, REQ_LOC_CHANGE_EVENT, false);
Services.prefs.setCharPref(PREF_SELECTED_LOCALE, "sr-RU");
run_next_test();
});
+add_test(function test_setRequestedLocales() {
+ localeService.setRequestedLocales([]);
+
+ let matchOS = Services.prefs.getBoolPref(PREF_MATCH_OS_LOCALE);
+ do_check_true(matchOS === true);
+
+ localeService.setRequestedLocales(['de-AT']);
+
+ matchOS = Services.prefs.getBoolPref(PREF_MATCH_OS_LOCALE);
+ do_check_true(matchOS === false);
+ let locales = localeService.getRequestedLocales();;
+ do_check_true(locales[0] === 'de-AT');
+
+ run_next_test();
+});
+
do_register_cleanup(() => {
Services.prefs.clearUserPref(PREF_SELECTED_LOCALE);
Services.prefs.clearUserPref(PREF_MATCH_OS_LOCALE);
});
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -1711,39 +1711,21 @@ var BrowserApp = {
let appLocale = this.getUALocalePref();
this.computeAcceptLanguages(languageTag, appLocale);
break;
}
case "Locale:Changed": {
if (data) {
- // The value provided to Locale:Changed should be a BCP47 language tag
- // understood by Gecko -- for example, "es-ES" or "de".
- console.log("Locale:Changed: " + data.languageTag);
-
- // We always write a localized pref, even though sometimes the value is a char pref.
- // (E.g., on desktop single-locale builds.)
- this.setLocalizedPref("general.useragent.locale", data.languageTag);
+ Services.locale.setRequestedLocales([data.languageTag]);
} else {
- // Resetting.
- console.log("Switching to system locale.");
- Services.prefs.clearUserPref("general.useragent.locale");
+ Services.locale.setRequestedLocales([]);
}
- Services.prefs.setBoolPref("intl.locale.matchOS", !data);
-
- // Ensure that this choice is immediately persisted, because
- // Gecko won't be told again if it forgets.
- Services.prefs.savePrefFile(null);
-
- // Blow away the string cache so that future lookups get the
- // correct locale.
- Strings.flush();
-
// Make sure we use the right Accept-Language header.
let osLocale;
try {
// This should never not be set at this point, but better safe than sorry.
osLocale = Services.prefs.getCharPref("intl.locale.os");
} catch (e) {
}