Skip to content

Localization

Localization is the process of adapting an application to a specific language or region. This guide will explain how Cimpress UI enables you to localize your applications.

Cimpress UI components contain some built-in strings, mostly for non-visible content (ARIA labels, screen reader announcements, etc.). All of these strings are customizable, and Cimpress UI provides localized versions of these strings in several languages. All built-in strings use the ICU Message syntax.

Text content that you provide to Cimpress UI components is rendered as-is, and so should be localized beforehand. It’s up to you to localize your own text content, but we provide a set of tools to help with it. These tools will be showcased later in this guide.

Dates and numbers are formatted according to the specified locale. This is done using the ECMAScript Internationalization API built into modern browsers.

By default, Cimpress UI will use US English strings, and will detect the user’s preferred locale for date and number formatting. We recommend overriding the locale to match your application’s language.

You can override the locale by passing a locale prop to LocalizationProvider:

src/main.tsx
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import { LocalizationProvider } from '@cimpress-ui/react/i18n';
import App from './app.js';
// ...
createRoot(document.getElementById('root')!).render(
<StrictMode>
<App />
<LocalizationProvider locale="en-US">
<App />
</LocalizationProvider>
</StrictMode>,
);

Make sure to also set the localization attributes on your html element:

  • lang - language of your application
  • dir - directionality of the text; "ltr" for left-to-right content or "rtl" for right-to-left content
index.html
<!doctype html>
<html lang="en-US" dir="ltr">
<head>
<title>My App</title>
...
</head>
<body>
...
</body>
</html>

Built-in localizations can be imported from @cimpress-ui/react/i18n. To use one of the built-in localizations, pass it to LocalizationProvider in the messages prop.

src/main.tsx
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import { LocalizationProvider } from '@cimpress-ui/react/i18n';
import { enUS, LocalizationProvider } from '@cimpress-ui/react/i18n';
import App from './app.js';
// ...
createRoot(document.getElementById('root')!).render(
<StrictMode>
<LocalizationProvider locale="en-US">
<LocalizationProvider locale="en-US" messages={enUS}>
<App />
</LocalizationProvider>
</StrictMode>,
);

To create a custom localization, create an object using the LocalizedMessages interface. This object can then be provided to Cimpress UI’s LocalizationProvider.

src/main.tsx
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import { LocalizationProvider } from '@cimpress-ui/react/i18n';
import { LocalizationProvider, type LocalizedMessages } from '@cimpress-ui/react/i18n';
import App from './app.js';
// ...
const customLocale = '...';
const customMessages: LocalizedMessages = {
// ...
};
createRoot(document.getElementById('root')!).render(
<StrictMode>
<LocalizationProvider locale="en-US">
<LocalizationProvider locale={customLocale} messages={customMessages}>
<App />
</LocalizationProvider>
</StrictMode>,
);

LocalizationProvider accepts a partial messages object, so you can override a specific message for a specific component usage. For example, this is how you would override the ARIA labels of the NumberField component:

src/rating.tsx
import { NumberField } from '@cimpress-ui/react';
import { LocalizationProvider, type LocalizedMessages, type PartialMessages } from '@cimpress-ui/react/i18n';
const messages: PartialMessages<LocalizedMessages> = {
numberField: {
increment: 'Increase rating',
decrement: 'Decrease rating',
},
};
export function Rating() {
return (
<NumberField label="Rating" />
<LocalizationProvider messages={messages}>
<NumberField label="Rating" />
</LocalizationProvider>
);
}

You can use Cimpress UI’s localization system to localize your custom components by following the steps below:

  1. Define a type for your custom messages. Messages must be nested within an object (usually keyed with a component name), and there can only be one level of nesting. Make sure to extend LocalizedMessages if you want to use Cimpress UI messages as well.

    src/localization.ts
    import type { LocalizedMessages, LocalizedString } from '@cimpress-ui/react/i18n';
    export type CustomLocalizedMessages = LocalizedMessages & {
    customComponent: {
    customMessage: LocalizedString;
    };
    };
  2. Use the UNSTABLE_createLocalizationTools function to create type-safe tools based on your custom type.

    src/localization.ts
    import type { LocalizedMessages, LocalizedString } from '@cimpress-ui/react/i18n';
    import {
    type LocalizedMessages,
    type LocalizedString,
    UNSTABLE_createLocalizationTools,
    } from '@cimpress-ui/react/i18n';
    export type CustomLocalizedMessages = LocalizedMessages & {
    customComponent: {
    customMessage: LocalizedString;
    };
    };
    export const { LocalizationProvider, useLocalizedMessages } =
    UNSTABLE_createLocalizationTools<CustomLocalizedMessages>();
  3. Use the LocalizationProvider created in step 2 to provide your custom messages.

    src/main.tsx
    import { StrictMode } from 'react';
    import { createRoot } from 'react-dom/client';
    import { enUS, LocalizationProvider } from '@cimpress-ui/react/i18n';
    import { enUS } from '@cimpress-ui/react/i18n';
    import App from './app.js';
    import { type CustomLocalizedMessages, LocalizationProvider } from './localization.js';
    // ...
    const customMessages: CustomLocalizedMessages = {
    ...enUS,
    customComponent: {
    customMessage: 'My custom message',
    },
    };
    createRoot(document.getElementById('root')!).render(
    <StrictMode>
    <LocalizationProvider locale="en-US" messages={enUS}>
    <LocalizationProvider locale="en-US" messages={customMessages}>
    <App />
    </LocalizationProvider>
    </StrictMode>,
    );
  4. Access your custom messages within your components using the useLocalizedMessages hook created in step 2.

    src/custom-component.tsx
    // ...
    import { useLocalizedMessages } from '@cimpress-ui/react/i18n';
    import { useLocalizedMessages } from './localization.js';
    export function CustomComponent() {
    const messages = useLocalizedMessages('customComponent');
    const customMessage = messages.format('customMessage');
    return (
    // ...
    );
    }
  5. If your component needs to know the current locale, you can obtain it using the useLocaleInfo hook.

    src/custom-component.tsx
    // ...
    import { useLocaleInfo } from '@cimpress-ui/react/i18n';
    import { useLocalizedMessages } from './localization.js';
    export function CustomComponent() {
    const messages = useLocalizedMessages('customComponent');
    const customMessage = messages.format('customMessage');
    const { locale, direction } = useLocaleInfo();
    return (
    // ...
    );
    }