2017-01-26 02:58:14 +03:00
|
|
|
/* -*- 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__
|
|
|
|
|
2017-03-07 00:24:45 +03:00
|
|
|
#include "nsIObserver.h"
|
2017-01-26 02:58:14 +03:00
|
|
|
#include "nsString.h"
|
|
|
|
#include "nsTArray.h"
|
2017-09-09 03:51:43 +03:00
|
|
|
#include "nsWeakReference.h"
|
2017-01-26 02:58:14 +03:00
|
|
|
|
2017-02-05 23:29:39 +03:00
|
|
|
#include "mozILocaleService.h"
|
|
|
|
|
2017-01-26 02:58:14 +03:00
|
|
|
namespace mozilla {
|
|
|
|
namespace intl {
|
|
|
|
|
|
|
|
/**
|
|
|
|
* LocaleService is a manager of language negotiation in Gecko.
|
|
|
|
*
|
|
|
|
* It's intended to be the core place for collecting available and
|
|
|
|
* requested languages and negotiating them to produce a fallback
|
|
|
|
* chain of locales for the application.
|
2017-02-25 04:23:39 +03:00
|
|
|
*
|
Bug 1348042 - Refactor LocaleService to operate in server-client mode. r=Ehsan,qdot
LocaleService serves two main functions. It is a central place for all code in the
engine to learn about locales, but it also does the language negotiation and selection.
The former is relevant in all processes, but the latter should only be performed
by the "main" process. In case of current Desktop Firefox, the parent process
is the one performing all the language negotiation, and content processes should
operate in the "client" mode.
In Fennec, there's a Java app on top of Gecko which should work as a "server"
and then all processes, including parent process of Gecko is merely a "client" for that.
This refactor finalizes this duality making it easily configurable to define in
which mode a given LocaleService operates.
The server-client model allows all clients to stay in sync with the server,
but operate transparently for all callers just returning the right values.
In order to initialize LocaleService in the client mode in child process with the
right locales I'm adding the list of app locales to the XPCOMInitData,
and then fire LocaleService::SetAppLocales in the child process initialization.
In order to keep the list up to date, I'm adding intl:app-locales-changed to
the list of observed topics, and when triggered, I send the updated list
to the child process, which updates LocaleService::SetAppLocales with the new
list.
MozReview-Commit-ID: K9X6berF3IO
--HG--
extra : rebase_source : ca5e502d064023fddfd63fe6fe5eccefce8dee52
2017-03-26 08:09:45 +03:00
|
|
|
* Client / Server
|
|
|
|
*
|
|
|
|
* LocaleService may operate in one of two modes:
|
|
|
|
*
|
|
|
|
* server
|
|
|
|
* in the server mode, LocaleService is collecting and negotiating
|
|
|
|
* languages. It also subscribes to relevant observers.
|
|
|
|
* There should be at most one server per application instance.
|
|
|
|
*
|
|
|
|
* client
|
|
|
|
* in the client mode, LocaleService is not responsible for collecting
|
|
|
|
* or reacting to any system changes. It still distributes information
|
|
|
|
* about locales, but internally, it gets information from the server instance
|
|
|
|
* instead of collecting it on its own.
|
|
|
|
* This prevents any data desynchronization and minimizes the cost
|
|
|
|
* of running the service.
|
|
|
|
*
|
|
|
|
* In both modes, all get* methods should work the same way and all
|
|
|
|
* static methods are available.
|
|
|
|
*
|
|
|
|
* In the server mode, other components may inform LocaleService about their
|
|
|
|
* status either via calls to set* methods or via observer events.
|
|
|
|
* In the client mode, only the process communication should provide data
|
|
|
|
* to the LocaleService.
|
|
|
|
*
|
|
|
|
* At the moment desktop apps use the parent process in the server mode, and
|
|
|
|
* content processes in the client mode.
|
|
|
|
*
|
|
|
|
* Locale / Language
|
|
|
|
*
|
2017-02-25 04:23:39 +03:00
|
|
|
* The terms `Locale ID` and `Language ID` are used slightly differently
|
|
|
|
* by different organizations. Mozilla uses the term `Language ID` to describe
|
|
|
|
* a string that contains information about the language itself, script,
|
|
|
|
* region and variant. For example "en-Latn-US-mac" is a correct Language ID.
|
|
|
|
*
|
|
|
|
* Locale ID contains a Language ID plus a number of extension tags that
|
|
|
|
* contain information that go beyond language inforamation such as
|
|
|
|
* preferred currency, date/time formatting etc.
|
|
|
|
*
|
|
|
|
* An example of a Locale ID is `en-Latn-US-x-hc-h12-ca-gregory`
|
|
|
|
*
|
|
|
|
* At the moment we do not support full extension tag system, but we
|
|
|
|
* try to be specific when naming APIs, so the service is for locales,
|
|
|
|
* but we negotiate between languages etc.
|
2017-01-26 02:58:14 +03:00
|
|
|
*/
|
2017-03-07 00:24:45 +03:00
|
|
|
class LocaleService : public mozILocaleService,
|
2017-09-09 03:51:43 +03:00
|
|
|
public nsIObserver,
|
|
|
|
public nsSupportsWeakReference
|
2017-01-26 02:58:14 +03:00
|
|
|
{
|
|
|
|
public:
|
2017-02-05 23:29:39 +03:00
|
|
|
NS_DECL_ISUPPORTS
|
2017-03-07 00:24:45 +03:00
|
|
|
NS_DECL_NSIOBSERVER
|
2017-02-05 23:29:39 +03:00
|
|
|
NS_DECL_MOZILOCALESERVICE
|
|
|
|
|
2017-02-25 04:23:39 +03:00
|
|
|
/**
|
|
|
|
* List of available language negotiation strategies.
|
|
|
|
*
|
|
|
|
* See the mozILocaleService.idl for detailed description of the
|
|
|
|
* strategies.
|
|
|
|
*/
|
|
|
|
enum class LangNegStrategy {
|
|
|
|
Filtering,
|
|
|
|
Matching,
|
|
|
|
Lookup
|
|
|
|
};
|
|
|
|
|
Bug 1348042 - Refactor LocaleService to operate in server-client mode. r=Ehsan,qdot
LocaleService serves two main functions. It is a central place for all code in the
engine to learn about locales, but it also does the language negotiation and selection.
The former is relevant in all processes, but the latter should only be performed
by the "main" process. In case of current Desktop Firefox, the parent process
is the one performing all the language negotiation, and content processes should
operate in the "client" mode.
In Fennec, there's a Java app on top of Gecko which should work as a "server"
and then all processes, including parent process of Gecko is merely a "client" for that.
This refactor finalizes this duality making it easily configurable to define in
which mode a given LocaleService operates.
The server-client model allows all clients to stay in sync with the server,
but operate transparently for all callers just returning the right values.
In order to initialize LocaleService in the client mode in child process with the
right locales I'm adding the list of app locales to the XPCOMInitData,
and then fire LocaleService::SetAppLocales in the child process initialization.
In order to keep the list up to date, I'm adding intl:app-locales-changed to
the list of observed topics, and when triggered, I send the updated list
to the child process, which updates LocaleService::SetAppLocales with the new
list.
MozReview-Commit-ID: K9X6berF3IO
--HG--
extra : rebase_source : ca5e502d064023fddfd63fe6fe5eccefce8dee52
2017-03-26 08:09:45 +03:00
|
|
|
explicit LocaleService(bool aIsServer);
|
|
|
|
|
2017-02-05 23:29:39 +03:00
|
|
|
/**
|
|
|
|
* Create (if necessary) and return a raw pointer to the singleton instance.
|
|
|
|
* Use this accessor in C++ code that just wants to call a method on the
|
|
|
|
* instance, but does not need to hold a reference, as in
|
|
|
|
* nsAutoCString str;
|
2017-03-13 18:31:43 +03:00
|
|
|
* LocaleService::GetInstance()->GetAppLocaleAsLangTag(str);
|
2017-02-05 23:29:39 +03:00
|
|
|
*/
|
2017-01-26 02:58:14 +03:00
|
|
|
static LocaleService* GetInstance();
|
|
|
|
|
2017-02-05 23:29:39 +03:00
|
|
|
/**
|
|
|
|
* Return an addRef'd pointer to the singleton instance. This is used by the
|
|
|
|
* XPCOM constructor that exists to support usage from JS.
|
|
|
|
*/
|
|
|
|
static already_AddRefed<LocaleService> GetInstanceAddRefed()
|
|
|
|
{
|
|
|
|
return RefPtr<LocaleService>(GetInstance()).forget();
|
|
|
|
}
|
|
|
|
|
2017-01-26 02:58:14 +03:00
|
|
|
/**
|
|
|
|
* Returns a list of locales that the application should be localized to.
|
|
|
|
*
|
2017-02-25 04:23:39 +03:00
|
|
|
* The result is a ordered list of valid locale IDs and it should be
|
2017-01-26 02:58:14 +03:00
|
|
|
* used for all APIs that accept list of locales, like ECMA402 and L10n APIs.
|
|
|
|
*
|
|
|
|
* This API always returns at least one locale.
|
|
|
|
*
|
|
|
|
* Example: ["en-US", "de", "pl", "sr-Cyrl", "zh-Hans-HK"]
|
|
|
|
*
|
|
|
|
* Usage:
|
2017-02-09 00:12:16 +03:00
|
|
|
* nsTArray<nsCString> appLocales;
|
2017-03-13 18:31:43 +03:00
|
|
|
* LocaleService::GetInstance()->GetAppLocalesAsLangTags(appLocales);
|
2017-01-26 02:58:14 +03:00
|
|
|
*
|
2017-02-09 00:12:16 +03:00
|
|
|
* (See mozILocaleService.idl for a JS-callable version of this.)
|
2017-01-26 02:58:14 +03:00
|
|
|
*/
|
2017-03-13 18:31:43 +03:00
|
|
|
void GetAppLocalesAsLangTags(nsTArray<nsCString>& aRetVal);
|
|
|
|
void GetAppLocalesAsBCP47(nsTArray<nsCString>& aRetVal);
|
2017-01-26 02:58:14 +03:00
|
|
|
|
2017-07-08 23:54:04 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns a list of locales to use for any regional specific operations
|
|
|
|
* like date formatting, calendars, unit formatting etc.
|
|
|
|
*
|
|
|
|
* The result is a ordered list of valid locale IDs and it should be
|
|
|
|
* used for all APIs that accept list of locales, like ECMA402 and L10n APIs.
|
|
|
|
*
|
|
|
|
* This API always returns at least one locale.
|
|
|
|
*
|
|
|
|
* Example: ["en-US", "de", "pl", "sr-Cyrl", "zh-Hans-HK"]
|
|
|
|
*
|
|
|
|
* Usage:
|
|
|
|
* nsTArray<nsCString> rgLocales;
|
|
|
|
* LocaleService::GetInstance()->GetRegionalPrefsLocales(rgLocales);
|
|
|
|
*
|
|
|
|
* (See mozILocaleService.idl for a JS-callable version of this.)
|
|
|
|
*/
|
|
|
|
void GetRegionalPrefsLocales(nsTArray<nsCString>& aRetVal);
|
|
|
|
|
Bug 1348042 - Refactor LocaleService to operate in server-client mode. r=Ehsan,qdot
LocaleService serves two main functions. It is a central place for all code in the
engine to learn about locales, but it also does the language negotiation and selection.
The former is relevant in all processes, but the latter should only be performed
by the "main" process. In case of current Desktop Firefox, the parent process
is the one performing all the language negotiation, and content processes should
operate in the "client" mode.
In Fennec, there's a Java app on top of Gecko which should work as a "server"
and then all processes, including parent process of Gecko is merely a "client" for that.
This refactor finalizes this duality making it easily configurable to define in
which mode a given LocaleService operates.
The server-client model allows all clients to stay in sync with the server,
but operate transparently for all callers just returning the right values.
In order to initialize LocaleService in the client mode in child process with the
right locales I'm adding the list of app locales to the XPCOMInitData,
and then fire LocaleService::SetAppLocales in the child process initialization.
In order to keep the list up to date, I'm adding intl:app-locales-changed to
the list of observed topics, and when triggered, I send the updated list
to the child process, which updates LocaleService::SetAppLocales with the new
list.
MozReview-Commit-ID: K9X6berF3IO
--HG--
extra : rebase_source : ca5e502d064023fddfd63fe6fe5eccefce8dee52
2017-03-26 08:09:45 +03:00
|
|
|
/**
|
|
|
|
* This method should only be called in the client mode.
|
|
|
|
*
|
|
|
|
* It replaces all the language negotiation and is supposed to be called
|
|
|
|
* in order to bring the client LocaleService in sync with the server
|
|
|
|
* LocaleService.
|
|
|
|
*
|
|
|
|
* Currently, it's called by the IPC code.
|
|
|
|
*/
|
|
|
|
void AssignAppLocales(const nsTArray<nsCString>& aAppLocales);
|
|
|
|
void AssignRequestedLocales(const nsTArray<nsCString>& aRequestedLocales);
|
|
|
|
|
2017-03-07 00:24:45 +03:00
|
|
|
/**
|
|
|
|
* Returns a list of locales that the user requested the app to be
|
|
|
|
* localized to.
|
|
|
|
*
|
|
|
|
* The result is a sorted list of valid locale IDs and it should be
|
|
|
|
* used as a requestedLocales input list for languages negotiation.
|
|
|
|
*
|
|
|
|
* Example: ["en-US", "de", "pl", "sr-Cyrl", "zh-Hans-HK"]
|
|
|
|
*
|
|
|
|
* Usage:
|
2017-03-14 03:33:24 +03:00
|
|
|
* nsTArray<nsCString> reqLocales;
|
|
|
|
* LocaleService::GetInstance()->GetRequestedLocales(reqLocales);
|
2017-03-07 00:24:45 +03:00
|
|
|
*
|
|
|
|
* Returns a boolean indicating if the attempt to retrieve prefs
|
|
|
|
* was successful.
|
|
|
|
*
|
|
|
|
* (See mozILocaleService.idl for a JS-callable version of this.)
|
|
|
|
*/
|
|
|
|
bool GetRequestedLocales(nsTArray<nsCString>& aRetVal);
|
|
|
|
|
2017-03-14 03:33:24 +03:00
|
|
|
/**
|
|
|
|
* Returns a list of available locales that can be used to
|
|
|
|
* localize the app.
|
|
|
|
*
|
|
|
|
* The result is an unsorted list of valid locale IDs and it should be
|
|
|
|
* used as a availableLocales input list for languages negotiation.
|
|
|
|
*
|
|
|
|
* Example: ["de", "en-US", "pl", "sr-Cyrl", "zh-Hans-HK"]
|
|
|
|
*
|
|
|
|
* Usage:
|
|
|
|
* nsTArray<nsCString> availLocales;
|
|
|
|
* LocaleService::GetInstance()->GetAvailableLocales(availLocales);
|
|
|
|
*
|
|
|
|
* Returns a boolean indicating if the attempt to retrieve at least
|
|
|
|
* one locale was successful.
|
|
|
|
*
|
|
|
|
* (See mozILocaleService.idl for a JS-callable version of this.)
|
|
|
|
*/
|
|
|
|
bool GetAvailableLocales(nsTArray<nsCString>& aRetVal);
|
|
|
|
|
2017-01-26 02:58:14 +03:00
|
|
|
/**
|
Bug 1348042 - Refactor LocaleService to operate in server-client mode. r=Ehsan,qdot
LocaleService serves two main functions. It is a central place for all code in the
engine to learn about locales, but it also does the language negotiation and selection.
The former is relevant in all processes, but the latter should only be performed
by the "main" process. In case of current Desktop Firefox, the parent process
is the one performing all the language negotiation, and content processes should
operate in the "client" mode.
In Fennec, there's a Java app on top of Gecko which should work as a "server"
and then all processes, including parent process of Gecko is merely a "client" for that.
This refactor finalizes this duality making it easily configurable to define in
which mode a given LocaleService operates.
The server-client model allows all clients to stay in sync with the server,
but operate transparently for all callers just returning the right values.
In order to initialize LocaleService in the client mode in child process with the
right locales I'm adding the list of app locales to the XPCOMInitData,
and then fire LocaleService::SetAppLocales in the child process initialization.
In order to keep the list up to date, I'm adding intl:app-locales-changed to
the list of observed topics, and when triggered, I send the updated list
to the child process, which updates LocaleService::SetAppLocales with the new
list.
MozReview-Commit-ID: K9X6berF3IO
--HG--
extra : rebase_source : ca5e502d064023fddfd63fe6fe5eccefce8dee52
2017-03-26 08:09:45 +03:00
|
|
|
* Those three functions allow to trigger cache invalidation on one of the
|
|
|
|
* three cached values.
|
|
|
|
*
|
|
|
|
* In most cases, the functions will be called by the observer in
|
|
|
|
* LocaleService itself, but in a couple special cases, we have the
|
|
|
|
* other component call this manually instead of sending a global event.
|
2017-01-26 02:58:14 +03:00
|
|
|
*
|
|
|
|
* If the result differs from the previous list, it will additionally
|
Bug 1348042 - Refactor LocaleService to operate in server-client mode. r=Ehsan,qdot
LocaleService serves two main functions. It is a central place for all code in the
engine to learn about locales, but it also does the language negotiation and selection.
The former is relevant in all processes, but the latter should only be performed
by the "main" process. In case of current Desktop Firefox, the parent process
is the one performing all the language negotiation, and content processes should
operate in the "client" mode.
In Fennec, there's a Java app on top of Gecko which should work as a "server"
and then all processes, including parent process of Gecko is merely a "client" for that.
This refactor finalizes this duality making it easily configurable to define in
which mode a given LocaleService operates.
The server-client model allows all clients to stay in sync with the server,
but operate transparently for all callers just returning the right values.
In order to initialize LocaleService in the client mode in child process with the
right locales I'm adding the list of app locales to the XPCOMInitData,
and then fire LocaleService::SetAppLocales in the child process initialization.
In order to keep the list up to date, I'm adding intl:app-locales-changed to
the list of observed topics, and when triggered, I send the updated list
to the child process, which updates LocaleService::SetAppLocales with the new
list.
MozReview-Commit-ID: K9X6berF3IO
--HG--
extra : rebase_source : ca5e502d064023fddfd63fe6fe5eccefce8dee52
2017-03-26 08:09:45 +03:00
|
|
|
* trigger a corresponding event
|
|
|
|
*
|
|
|
|
* This code should be called only in the server mode..
|
2017-01-26 02:58:14 +03:00
|
|
|
*/
|
2017-10-10 20:39:12 +03:00
|
|
|
void AvailableLocalesChanged();
|
|
|
|
void RequestedLocalesChanged();
|
|
|
|
void LocalesChanged();
|
2017-01-26 02:58:14 +03:00
|
|
|
|
2017-02-25 04:23:39 +03:00
|
|
|
/**
|
|
|
|
* Negotiates the best locales out of an ordered list of requested locales and
|
|
|
|
* a list of available locales.
|
|
|
|
*
|
|
|
|
* Internally it uses the following naming scheme:
|
|
|
|
*
|
|
|
|
* Requested - locales requested by the user
|
|
|
|
* Available - locales for which the data is available
|
|
|
|
* Supported - locales negotiated by the algorithm
|
|
|
|
*
|
|
|
|
* Additionally, if defaultLocale is provided, it adds it to the end of the
|
|
|
|
* result list as a "last resort" locale.
|
|
|
|
*
|
|
|
|
* Strategy is one of the three strategies described at the top of this file.
|
|
|
|
*
|
|
|
|
* The result list is ordered according to the order of the requested locales.
|
|
|
|
*
|
|
|
|
* (See mozILocaleService.idl for a JS-callable version of this.)
|
|
|
|
*/
|
|
|
|
bool NegotiateLanguages(const nsTArray<nsCString>& aRequested,
|
|
|
|
const nsTArray<nsCString>& aAvailable,
|
|
|
|
const nsACString& aDefaultLocale,
|
|
|
|
LangNegStrategy aLangNegStrategy,
|
|
|
|
nsTArray<nsCString>& aRetVal);
|
2017-01-26 02:58:14 +03:00
|
|
|
|
2017-03-14 22:35:06 +03:00
|
|
|
/**
|
|
|
|
* Returns whether the current app locale is RTL.
|
|
|
|
*/
|
|
|
|
bool IsAppLocaleRTL();
|
|
|
|
|
2017-03-03 03:39:17 +03:00
|
|
|
static bool LanguagesMatch(const nsCString& aRequested,
|
|
|
|
const nsCString& aAvailable);
|
|
|
|
|
Bug 1348042 - Refactor LocaleService to operate in server-client mode. r=Ehsan,qdot
LocaleService serves two main functions. It is a central place for all code in the
engine to learn about locales, but it also does the language negotiation and selection.
The former is relevant in all processes, but the latter should only be performed
by the "main" process. In case of current Desktop Firefox, the parent process
is the one performing all the language negotiation, and content processes should
operate in the "client" mode.
In Fennec, there's a Java app on top of Gecko which should work as a "server"
and then all processes, including parent process of Gecko is merely a "client" for that.
This refactor finalizes this duality making it easily configurable to define in
which mode a given LocaleService operates.
The server-client model allows all clients to stay in sync with the server,
but operate transparently for all callers just returning the right values.
In order to initialize LocaleService in the client mode in child process with the
right locales I'm adding the list of app locales to the XPCOMInitData,
and then fire LocaleService::SetAppLocales in the child process initialization.
In order to keep the list up to date, I'm adding intl:app-locales-changed to
the list of observed topics, and when triggered, I send the updated list
to the child process, which updates LocaleService::SetAppLocales with the new
list.
MozReview-Commit-ID: K9X6berF3IO
--HG--
extra : rebase_source : ca5e502d064023fddfd63fe6fe5eccefce8dee52
2017-03-26 08:09:45 +03:00
|
|
|
bool IsServer();
|
|
|
|
|
2017-01-26 02:58:14 +03:00
|
|
|
private:
|
2017-02-25 04:23:39 +03:00
|
|
|
/**
|
|
|
|
* Locale object, a BCP47-style tag decomposed into subtags for
|
|
|
|
* matching purposes.
|
|
|
|
*
|
|
|
|
* If constructed with aRange = true, any missing subtags will be
|
|
|
|
* set to "*".
|
|
|
|
*/
|
|
|
|
class Locale
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
Locale(const nsCString& aLocale, bool aRange);
|
|
|
|
|
|
|
|
bool Matches(const Locale& aLocale) const;
|
2017-03-03 03:39:17 +03:00
|
|
|
bool LanguageMatches(const Locale& aLocale) const;
|
2017-02-25 04:23:39 +03:00
|
|
|
|
|
|
|
void SetVariantRange();
|
|
|
|
void SetRegionRange();
|
|
|
|
|
Bug 1400006 - Extend language negotiation in LocaleService to support looking for the best likelySubtag for the locale with region stripped. r=Pike
Add additional logic to our language negotation to do apply likelySubtags when a direct match is not available.
Currently, if the user specifies the locale with region, and we do not have a direct for that region, we pick all locales for the same language and other regions in no order.
The example of where it returns suboptimal results:
1) Requested locale "en-CA"
2) Available locales ["en-ZA", "en-GB", "en-US"]
3) Negotiated locales ["en-ZA", "en-GB", "en-US"]
This would not happen, if the user requested a generic "de", "en" etc.:
1) Requested locale "en"
2) Available locales ["en-ZA", "en-GB", "en-US"]
3) Negotiated locales ["en-US", "en-ZA", "en-GB"]
because after not finding a direct match, we would use likelySubtags to extend "en" to "en-Latn-US" and then find the priority match in "en-US".
This patch extends this logic to "en-US" or "de-LU" by adding a step which strips the region tag and then applies likelySubtag on the result.
This means that in absence of direct match the following fallbacks would happen:
"de-LU" -> "de-DE"
"es-CL" -> "es-ES"
"en-CA" -> "en-US"
This does not affect languages that use multiple scripts, so ar, sr and zh are not affected.
MozReview-Commit-ID: BR1WrgXSf6a
--HG--
extra : rebase_source : abc205c4f993680ab0cd0c8b8c016543d5462d01
2017-09-15 01:21:33 +03:00
|
|
|
// returns false if nothing changed
|
|
|
|
bool AddLikelySubtags();
|
|
|
|
bool AddLikelySubtagsWithoutRegion();
|
2017-02-25 04:23:39 +03:00
|
|
|
|
|
|
|
const nsCString& AsString() const {
|
|
|
|
return mLocaleStr;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator== (const Locale& aOther) {
|
|
|
|
const auto& cmp = nsCaseInsensitiveCStringComparator();
|
|
|
|
return mLanguage.Equals(aOther.mLanguage, cmp) &&
|
|
|
|
mScript.Equals(aOther.mScript, cmp) &&
|
|
|
|
mRegion.Equals(aOther.mRegion, cmp) &&
|
|
|
|
mVariant.Equals(aOther.mVariant, cmp);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
const nsCString& mLocaleStr;
|
|
|
|
nsCString mLanguage;
|
|
|
|
nsCString mScript;
|
|
|
|
nsCString mRegion;
|
|
|
|
nsCString mVariant;
|
Bug 1400006 - Extend language negotiation in LocaleService to support looking for the best likelySubtag for the locale with region stripped. r=Pike
Add additional logic to our language negotation to do apply likelySubtags when a direct match is not available.
Currently, if the user specifies the locale with region, and we do not have a direct for that region, we pick all locales for the same language and other regions in no order.
The example of where it returns suboptimal results:
1) Requested locale "en-CA"
2) Available locales ["en-ZA", "en-GB", "en-US"]
3) Negotiated locales ["en-ZA", "en-GB", "en-US"]
This would not happen, if the user requested a generic "de", "en" etc.:
1) Requested locale "en"
2) Available locales ["en-ZA", "en-GB", "en-US"]
3) Negotiated locales ["en-US", "en-ZA", "en-GB"]
because after not finding a direct match, we would use likelySubtags to extend "en" to "en-Latn-US" and then find the priority match in "en-US".
This patch extends this logic to "en-US" or "de-LU" by adding a step which strips the region tag and then applies likelySubtag on the result.
This means that in absence of direct match the following fallbacks would happen:
"de-LU" -> "de-DE"
"es-CL" -> "es-ES"
"en-CA" -> "en-US"
This does not affect languages that use multiple scripts, so ar, sr and zh are not affected.
MozReview-Commit-ID: BR1WrgXSf6a
--HG--
extra : rebase_source : abc205c4f993680ab0cd0c8b8c016543d5462d01
2017-09-15 01:21:33 +03:00
|
|
|
|
|
|
|
bool AddLikelySubtagsForLocale(const nsACString& aLocale);
|
2017-02-25 04:23:39 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
void FilterMatches(const nsTArray<nsCString>& aRequested,
|
|
|
|
const nsTArray<nsCString>& aAvailable,
|
|
|
|
LangNegStrategy aStrategy,
|
|
|
|
nsTArray<nsCString>& aRetVal);
|
|
|
|
|
2017-03-15 01:28:47 +03:00
|
|
|
void NegotiateAppLocales(nsTArray<nsCString>& aRetVal);
|
|
|
|
|
2017-03-07 00:24:45 +03:00
|
|
|
virtual ~LocaleService();
|
2017-02-05 23:29:39 +03:00
|
|
|
|
2017-09-23 14:46:28 +03:00
|
|
|
nsAutoCStringN<16> mDefaultLocale;
|
2017-02-25 04:23:39 +03:00
|
|
|
nsTArray<nsCString> mAppLocales;
|
Bug 1348042 - Refactor LocaleService to operate in server-client mode. r=Ehsan,qdot
LocaleService serves two main functions. It is a central place for all code in the
engine to learn about locales, but it also does the language negotiation and selection.
The former is relevant in all processes, but the latter should only be performed
by the "main" process. In case of current Desktop Firefox, the parent process
is the one performing all the language negotiation, and content processes should
operate in the "client" mode.
In Fennec, there's a Java app on top of Gecko which should work as a "server"
and then all processes, including parent process of Gecko is merely a "client" for that.
This refactor finalizes this duality making it easily configurable to define in
which mode a given LocaleService operates.
The server-client model allows all clients to stay in sync with the server,
but operate transparently for all callers just returning the right values.
In order to initialize LocaleService in the client mode in child process with the
right locales I'm adding the list of app locales to the XPCOMInitData,
and then fire LocaleService::SetAppLocales in the child process initialization.
In order to keep the list up to date, I'm adding intl:app-locales-changed to
the list of observed topics, and when triggered, I send the updated list
to the child process, which updates LocaleService::SetAppLocales with the new
list.
MozReview-Commit-ID: K9X6berF3IO
--HG--
extra : rebase_source : ca5e502d064023fddfd63fe6fe5eccefce8dee52
2017-03-26 08:09:45 +03:00
|
|
|
nsTArray<nsCString> mRequestedLocales;
|
|
|
|
nsTArray<nsCString> mAvailableLocales;
|
|
|
|
const bool mIsServer;
|
2017-02-25 04:23:39 +03:00
|
|
|
|
2017-02-05 23:29:39 +03:00
|
|
|
static StaticRefPtr<LocaleService> sInstance;
|
2017-01-26 02:58:14 +03:00
|
|
|
};
|
|
|
|
} // intl
|
|
|
|
} // namespace mozilla
|
|
|
|
|
|
|
|
#endif /* mozilla_intl_LocaleService_h__ */
|