Fuchsia has some conventions for how to communicate i18n preferences, whether from an end user to components, or among components.
This guide covers the following:
fuchsia.intl.PropertyProvider
in components to read internationalization preferences. Make sure that the product configuration includes intl_services
or another implementation of this protocol.fuchsia.settings.Intl
to write internationalization settings.The keystone of i18n preferences is the locale identifier, which is a string that concisely conveys information such as:
Locale identifiers can also convey more granular information, such as:
Specifying these details is particularly useful when overriding the default values for a given language and region (see next section).
Fuchsia uses the Unicode BCP-47 Locale Identifier standard for locale IDs.
For example, the following locale ID specifies the Serbian language (sr
) as spoken in Serbia (RS
), written in a Cyrillic script (Cyrl
):
"sr-Cyrl-RS"
You can use Unicode extension subtags in the locale ID to add overrides. Consider the following example:
"sr-Cyrl-RS-u-ca-hebrew-fw-monday-ms-ussystem-nu-deva-tz-usnyc"
This example specifies the following:
Subtag(s) | Meaning |
---|---|
sr | Specifies the Serbian language. |
Cyrl | Specifies the Cyrillic script. |
RS | Specifies Serbia as the country/region. |
u | Marks the start of the Unicode extension data. |
ca-hebrew | Specifies the Hebrew calendar. |
fw-monday | Specifies Monday as the first day of the week. |
ms-ussystem | Specifies the measurement system as “US”, e.g. feet, ounces, |
: : etc. : | |
nu-deva | Specifies Devanagari numerals. |
tz-usnyc | Specifies the time zone as America/New_York . |
Not all internationalization properties that one might want to express have a corresponding Unicode extension. For example, there is currently no extension for temperature units, so there is no way to express “use metric units, but use Fahrenheit for temperature” in a locale ID.
To send i18n preferences between Fuchsia components, use the fuchsia.intl.Profile
FIDL table:
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="sdk/fidl/fuchsia.intl/intl.fidl" indented_block="type Profile" exclude_regexp="(//.*)|(^$)" %}
The locale ID is only a building block in the Profile
. A profile contains a ranked list of locale IDs (to express relative preference, priority, or degree of support; see Locale fallback for a usage example), as well as other properties that cannot be fully expressed in a single locale ID. When there is a conflict, explicit settings in the Profile
override the values in the locale ID (e.g. specifying US measurement units in the locale ID but CELSIUS
in the temperature_unit
field).
When a component needs to provide i18n preferences to other components, it should implement the fuchsia.intl.PropertyProvider
protocol, which serves the Profile
and notifies of changes:
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="sdk/fidl/fuchsia.intl/property_provider.fidl" indented_block="protocol PropertyProvider" exclude_regexp="(//.*)|(^$)" %}
This protocol offers a read-only view of an internationalization profile. Depending on the implementation of the service and the realm in which it is intended to serve, the contents of the internationalization profile may be derived from user settings, a product‘s factory settings, a specific component’s requirements, or some combination of the above.
Fuchsia has no ambient or system locale. Locale and other i18n preferences depend on the context in which a component is running. This is in contrast to other operating systems, which may have APIs to obtain global or default locale settings, following Fuchsia's design principle of no ambient authority
In runtimes where the standard library offers access to some default locale (for example, Platform.localeName
in Dart and Flutter), it is the responsibility of the runner to retrieve the needed values from the realm of the component being run. In most cases, the runner should call fuchsia.intl.PropertyProvider.GetProfile
. See Runner integrations below.
Profile
sDepending on a product's design, it is possible that two component instances running concurrently on the same machine in different realms are connected to different PropertyProvider
instances and receive different Profile
s.
For example, an encyclopedia component showing a Spanish-language (es-ES
) article about Mallorca may choose to launch a map component with an es-ES
UI, while at the same time an English-language (en-US
) article launches the same map component, but tells it to display an en-US
UI. This can be accomplished with two different sub-realms that each receives a different PropertyProvider
instance.
intl_services
libraryA basic C++ library implementing fuchsia.intl.PropertyProvider
is found at //src/lib/intl/intl_property_provider_impl
.
The core
product configuration includes intl_services
, a component that wraps this implementation.
In the future, accessing the field Platform.localeName
in Dart will return the first LocaleId
from the vector fuchsia.intl.Profile.locales
. (This is currently blocked by a limitation in the Dart SDK.)
The Flutter runner on Fuchsia is wired up to fuchsia.intl.PropertyProvider
, so using the standard Flutter localization API should allow a Flutter application to access the current context's locale preferences and detect changes. For details and examples, see Localizing mods.
Note: Both Dart and Flutter components that are built only for Fuchsia have the option of directly accessing the fuchsia.intl.PropertyProvider
FIDL service — in addition to using the OS-agnostic APIs. Cross-platform apps should use the properties provided by their runtimes.
The list of preferred locales from Profile
is sent to web serves in the HTTP request header Accept-Language
. In the future, they may also be made available in JavaScript in navigator.languages
and navigator.language
.
As with other user settings on Fuchsia, internationalization settings are modified through the fuchsia.settings
FIDL protocols.
Specifically, the protocol fuchsia.settings.Intl
is used to write and monitor internationalization-related settings.
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="sdk/fidl/fuchsia.settings/intl.fidl" indented_block="protocol Intl" exclude_regexp="(//.*)|(^$)" %}
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="sdk/fidl/fuchsia.settings/intl.fidl" indented_block="type IntlSettings" exclude_regexp="(//.*)|(^$)" %}
This protocol is intended specifically for components that require direct access to user settings, such as a system control panel, a taskbar locale selector, or an implementor of fuchsia.intl.PropertyProvider
. In typical Fuchsia product configurations, this access should be restricted to a narrow allowlist.
Most client components will instead use the read-only view offered through fuchsia.intl.PropertyProvider
.
setui_service
The protocol fuchsia.settings.Intl
is implemented by the setui_service
(along with the other protocols under fuchsia.settings
). This service serves as the backend for settings UIs in Fuchsia products.