Localization
Enterprise organizations operating in multiple regions or countries often must adapt to local cultures and preferences, while also maintaining a unified brand and user experience.
Internationalization and localization are critical for enterprises to reach a global audience, letting them to adjust their digital offering to meet local preferences and cultural norms. However, this process can be complex and time-consuming, requiring significant effort and resources to implement effectively. Systems must:
- Handle content for multiple languages and cultures
- Adjust content to regional market needs
- Translate content from one language to another.
The approach to content governance and operations can also affect how this content must be managed. Centralized teams may need to manage content across multiple regions to ensure consistency in branding and messaging. Distributed teams may need to manage content within a specific region, tailoring it to the local market. The operational model may also differ with how much autonomy a team has to create and maintain their own content and technology.
Uniform enables building internationalized projects, supporting both localization (serving different content to a locale, such as a regional promotion) and translation (serving the same content but in a different language). This is great for:
- Regional teams who have autonomy to create experiences but want to gain efficiency through a shared design system and shared content.
- A single, multi-lingual team working on the same experience but for different markets, or who needs to translate content into multiple languages.
- Any team looking to customize content or structures to account for regional differences.
Locales#
Locales, as defined by system architects, are at the center of Uniform internationalization. A locale is an object containing a display name (like "English US"), a locale code (such as en-us
), and a Boolean for if it's the default project locale. It can be any string value up to 32 characters. Uniform recommends using standard ISO language and region codes, such as en-GB
, de-AT
, or es-ES
, because this enables easy interoperability with other systems and browser locale preferences.
Parameters and fields can be configured so the value can be translated to different languages as configured by locales. A check box can be added to indicate the parameter or field is "Localizable."
info
Blocks can't be localized. Content within a block can, however, be localized.
System architects can control which objects can be localized as they're defined in Mesh integrations. They can set localization to be:
- On by default
- Off by default
- Forced on
- Forced off
See example code for how to configure localization for projects.
Create a locale#
To create a locale in Uniform:
Open your project.
Navigate to the Settings > Canvas Settings.
Click New Locale.
Add a new local from the Uniform Canvas Settings page.Enter the following data:
Field Description Is required? Display Name This is used to help editors choose between locales. Required Locale Code This is the code that will be stored with content and used for API requests. Uniform recommends ISO 638-1
codes. This can't be changed after creation.Required Default Choose if the locale is default. The default locale is automatically enabled for compositions once a locale is defined and is the default loaded when editing. API calls don't default to use this locale, they default to fetching all locales.
Translate content#
One common internationalization use case is to translate content data (parameters or fields) into different locales. Once you have defined locales in Uniform, you can configure components or content types to contain translated content.
Make a property locale-specific#
To configure a property for localization:
- Edit a component in the Component library.
- Add or edit a parameter on the component.
- Check off the "Localizable" option.
- Save the component definition.
- The parameter can now have a locale-specific value.
info
Certain parameter types, such a blocks, may not support localized values, in which case the localizable checkbox won't appear.
info
It's possible to change a parameter from localizable to not-localizable and back after there are instances of the parameter with content in them.
When changing to localizable, all locales will receive any previous parameter value.
When changing from localizable, the existing locale-specific behaviour will continue to occur until one edits the composition containing the parameter value. The editor will then convert the localized value into a non-locale-specific value automatically.
Object format of localizable parameter values#
When accessing localized parameters and all locales' data are present, this is how it's stored. This has a TypeScript type (import type { ComponentParameter } from '@uniformdev/canvas'
).
If the above example was run through a localize routine to en-US
(either by passing locale=en-US
to the composition API, or using the localize()
function - see the guide), it would end up like so:
Edit a locale-specific property#
When editing a composition and locales are defined for your project, you will see a locale selector in the upper right corner. When you edit a localizable parameter, the value being edited is always the selected locale's value. Changing the current locale will change the preview and parameters panes to show that locale's values instead. You can tell if you are editing a localizable parameter because a localizable parameter has a globe icon on it which shows the current locale code when you hover your mouse over it.
Non-localizable parameters can always be edited no matter what locale is selected, and they don't display the globe icon.
Compositions are required to enable locales before the use them, because sometimes content isn't available for all locales. For example the project might define en
, de
, and ko
as locales, but a specific composition might only have data in en
and ko
(either because the data isn't relevant to de
, or it might be out for translation). New compositions automatically enable the default locale, if there is a default locale. Additional locales can be enabled by clicking edit
in the locale selector or
Structural localization#
In Uniform all composition structure data is shared across every locale by default. This makes maintaining consistency of appearance easy, but sometimes it's necessary to alter the structure of the content for each locale in addition to translating values. For example a promotion might only be active in Romania, so we don't want to show it to German visitors. To accomplish this, Uniform provides the Localization component. The Localization component can be placed into a slot and contain child components that can be tagged to appear only in a specific locale.
Enable localization on a slot#
A localization component is like any other component, so if you have slots that have specifically allowed components in them, you must enable the Localization component to be used in the slot you want to localize.
tip
If you are using a slot that allows any component, you can skip this and go straight to "Localize components"
- In Uniform, edit a component with the slot to which you want to add localized components.
- Navigate to the slot.
- In the section Allowed Components, select the component Localization.
About this step
You must have other components selected on the slot. Those will be the component types that can be localized in this slot.
- Click OK.
- Save the component.
Localize components#
In Uniform, insert a component into a slot you have enabled localization for, or you can use an existing component.
Click the component.
Click the Localize This button.
About this step
A new component Localization is added to the slot, and the component is moved into that component. In this way localization works the same as personalization and testing.
Select the original component.
A new parameter Locale is available on the component. This parameter is a dropdown of the locales you defined in your project. Select the locale for the component.
The localized component within the structure panel of Canvas.About this step
The locale assigned to the component will appear in the box that represents the component in the composition.
Save the composition.
Add more components under the component Localization and assign a locale to each component you add. Each component will represent the locale you assigned.
Localized components within the localization structure.
Object format of the Localization component#
The following is an example of the JSON object that represents a slot with components localized for two locales (such as en-US
and da-DK
):
Enable localization on your frontend application#
Uniform supports three different strategies for resolving locale values, in increasing order by complexity and capability:
- Use a path segment from the project map as a locale value.
- Pass a locale to the Uniform API.
- Fetch all locales from the Uniform API and apply the localization yourself in your frontend application.
Regardless of the approach selected, the end result is the same: A locale will resolve to show the content for the current active locale and remove other locale data. This allows the frontend to act as if no localization took place and enables direct access to the localized values. If Uniform can't resolve the requested locale then it will return "not found".
Often, a front-end application will want to use an internationalization library such as next-intl
for Next.js to manage the user's selected locale, or negotiate the initial locale with a browser's Accept-Language
headers, among other tasks. Uniform's SDK is designed to complement any of these existing localization and static-translation management strategies. Uniform doesn't provide any frontend-side state management for localization of its own.
Use a project map node as the locale resolver (recommended)#
In this model a special node is added to the project map that dynamically represents the locale. This is appropriate when your project is using URLs and the locale code should be part of the URL such as /en-GB/about-us
. This has some significant advantages, as the source of the locale will be plain for authors and the frontend application will work automatically. When using the project map as a locale source, link parameters will be able to pass the current locale as a dynamic input, allowing simple maintenance of links without needing to define the target in every locale.
The locale node is added directly under the home node of the project map so that its route path becomes /<locale>
. However this isn't required and you may define locale nodes at any level in the project map. To add a locale node, add a project map node and choose "Locale" as the node type.
If you have existing project map nodes, you may need to move them under your locale node after doing this, noting that it could change your URL structure, and might require some redirects.
Pass a locale to Uniform APIs#
You can pass a locale parameter to all Uniform APIs that return routes, compositions, or entries. This parameter is also reflected in Uniform-provided API client classes and framework specific SDKs (if the option is missing, you may need to upgrade your SDK packages).
The locale parameter is allowed to be one of:
- A single locale code, such as
en
- A comma-separated list of locale codes, such as
en, en-US, de-DE
to enable language fallback - A list of locale codes in the format of the HTTP
Accept-Language
header, such asen;q=0.8,en-US;q=0.9
When the locale parameter is passed:
List responses will include only compositions which have either:
- Enabled one or more of the locale(s) provided by the locale parameter
- Not enabled any locales (this is to make it easier to migrate to locales).
Note that once a default locale has been added to a project, any composition that's edited will be set to enabled for the default locale and no longer match this criteria.
All responses will "localize" the composition data, to:
- Determine the target locale: This is the first locale in the locale parameter which has been enabled for the composition. For example, if the locale parameter is
en,de
and the composition has enabled['zh', 'de']
, thende
will be selected. - All locale data which isn't for the target locale is removed from the composition: This includes both localization components (replaced by their selected locale component, if any) and locale-specific parameter data (the target locale value is copied into the
value
property as if it weren't localized).
- Determine the target locale: This is the first locale in the locale parameter which has been enabled for the composition. For example, if the locale parameter is
tip
You can still pass an explicit locale if you are using a project-map based locale resolution. The explicit locale will override the value resolved from the project map. This can be useful to configure locale fallback chains, because you can explicitly pass more than one locale.
Fetch all locales and applying it in your application#
If the locale parameter isn't passed when fetching composition data, Uniform returns all the locales' data at the same time. This is a good option when you need to perform advanced, locale-selection logic of your own, or if you intend to cache composition data and don't want to vary the cache by locale.
When all locales are in a composition, Uniform provides a function that can be used to apply the same localization logic that the APIs use on demand:
About this step
Just like enhancers, localization changes the data available in the composition. It removes all the components that don't match the locale specified in the localize()
function call.
Localized routing in Next.js#
About this step
This section describes how to build a localized Next.js application using the Pages Router.
Localized routing using the App Router is specific to the implementation and will require some custom development.
To enable localized routing in Next.js we recommend to follow the sub-path routing strategy:
Step 1: Configure locales in next.config.js
to activate localization mode in Next.js. These should match the locales codes that are defined in your Uniform project.
next.config.js
Step 2: Update the dynamic route file (e.g. /pages/[[...slug]].tsx
) to pass the active locale to Uniform's Route API.
If you use the project map to resolve locales and your routes start with the locale identifier (e.g. /en-US/
) then you can pass the prependLocale
helper function from the @uniformdev/canvas-next
NPM package to the modifyPath
function.
/pages/[[...slug]].tsx
tip
The source code for a simple localization example using Next.js Pages Router be found in our Examples Github repository