The Canva translation process supports a subset of ICU MessageFormat
syntax. For more information about ICU, see the official FormatJS documentation.
ICU basics
This section describes the supported ICU syntax, with recommendations and examples.
Follow these examples and guidelines so that your app can be translated more accurately and efficiently.
Basic messages
How to do basic message localization with React, using the FormattedMessage
component from react-intl
.
- The
defaultMessage
string is the source for translation text. It's displayed to users that either have an English locale, or a locale with no translations available. - Use the
description
string to give as much context as possible to a human translator. For guidance on writing translator notes, see Add notes for translators.
For example:
<FormattedMessagedefaultMessage="My internationalized app"description="The title the user sees when opening the app. Appears at top of page."/>
Interpolation
You can use dynamic values (like firstName
) in the defaultMessage
prop of FormattedMessage
. This process is known as interpolation.
This section explains how to use interpolation for localized messages in React, using the FormattedMessage
component from react-intl
.
For example:
const name = "John"// ...<FormattedMessagedefaultMessage="Welcome to the world of AI creativity, {firstName}!"description="A greeting that welcomes the user to the AI image generation app"values={{firstName: name,}}/>
This renders as: "Welcome to the world of AI creativity, John!"
Plurals
How to handle plurals in localized messages in React.
For example:
export const CreditUsage = ({creditsCost,remainingCredits,}: {creditsCost: number;remainingCredits: number;}) => (<Text><FormattedMessagedefaultMessage={`Use {creditsCost, number} of {remainingCredits, plural,one {# credit}other {# credits}}`}description="Informs the user about the number of credits they will use for the image generation task. Appears below the image generation button."values={{creditsCost,remainingCredits,}}/></Text>);
<CreditUsage creditsCost={5} remainingCredits={50} /><CreditUsage creditsCost={1} remainingCredits={1} />
This would render as:
- "Use 5 of 50 credits"
- "Use 1 of 1 credit"
Numbers, dates, and time
When passing number, date, or time values, make sure you use the correct ICU argument so that the values are formatted in a way that respects the user's locale.
Numbers
This examples shows how to format numbers in localized messages in React, using the FormattedMessage
component from react-intl
.
<FormattedMessagedefaultMessage="Image generation is {progress, number, ::percent} complete."description="Displays the progress of the current image generation task that the user requested"values={{progress: 0.75,}}/>
Assuming the locale uses this percentage format, this can render as: "Image generation is 75% complete."
Dates
This example demonstrates how to format dates and times in localized messages in React, using the FormattedMessage
component from react-intl
.
<FormattedMessagedefaultMessage="Credits refresh on: {refreshDate, date, short} at {refreshTime, time, short}"description="Informs users when their credits for image generation will refresh, including the time"values={{refreshDate: new Date("2023-11-24T15:00:00"),refreshTime: new Date("2023-11-24T15:00:00"),}}/>
Depending on the user's locale, this can render as "Credits refresh on: 11/24/23 at 3:00 PM"
Time
Relative time formatting
This section provides guidelines for displaying relative time.
const LastGeneratedMessage = ({lastGeneratedTime,}: {lastGeneratedTime: Date;}) => {const intl = useIntl();const [generatedTimeAgoInSeconds, setGeneratedTimeAgoInSeconds] = React.useState(0);// ...return (<Text><FormattedMessagedefaultMessage="Last image generated {timeAgo}"description="Tells the user how long ago they generated their last image. timeAgo is a relative time string. e.g. '5 seconds ago'"values={{timeAgo: intl.formatRelativeTime(-generatedTimeAgoInSeconds,"seconds",),}}/></Text>);};
Select
Rich text
How to format rich text in localized messages in React, using the FormattedMessage
component from react-intl
.
For example:
<FormattedMessagedefaultMessage="Discover stunning AI-generated example images in our <link>gallery</link> and <callToAction>start exploring now!</callToAction>"description="A call to action directing the user to explore the AI image gallery"values={{link: (chunks) => (<Linkhref={DOCS_URL}requestOpenExternalUrl={() => openExternalUrl(DOCS_URL)}>{chunks}</Link>),callToAction: (chunks) => <strong>{chunks}</strong>,}}>{(chunks) => <Text>{chunks}</Text>}</FormattedMessage>
This can render as: "Discover stunning AI-generated example images in our gallery and start exploring now!"
Message as string type
How to use localized strings as button labels in React, using formatMessage
from react-intl
.
For example:
<Button variant="primary">{intl.formatMessage({defaultMessage: "Generate image",description: "A button label to generate an image from a prompt",})}</Button>
This renders a button with the label "Generate image", and the text is localized based on the user's locale.
Non-visible text for accessibility
How to use non-visible text for accessibility purposes (such as screen reader descriptions) in React, using ariaLabel
and formatMessage
from react-intl
.
For example:
<Buttonvariant="primary"icon={SortIcon}ariaLabel={intl.formatMessage({defaultMessage: "Sort images by creation date (Newest to Oldest)",description:"Screenreader text for a button. When pressed, the button will sort the generated images by creation date from newest to oldest.",})}/>
The screen reader will read the aria label as: "Sort images by creation date (Newest to Oldest)".
LTR and RTL languages
To support left-to-right (LTR) and right-to-left (RTL) languages, you can use CSS properties in UI components.
This example uses paddingStart
instead of paddingLeft
or paddingRight
, which lets your UI automatically adapt to the language's text direction.
<Box paddingStart="2u"><Slider min={0} max={100} /></Box>
Lists
How to format lists in a way that is compatible with localization.
In this example, the SelectedEffects
component defines a list of image effects, each formatted for localization.
const SelectedEffects = () => {const intl = useIntl();// TODO: Make this list change based on user selection!const selectedEffects = [intl.formatMessage({defaultMessage: "black and white",description:"An option that when selected, will apply a black and white effect to the generated image",}),intl.formatMessage({defaultMessage: "high contrast",description:"An option that when selected, will apply a high contrast effect to the generated image",}),intl.formatMessage({defaultMessage: "cartoon",description:"An option that when selected, will apply a cartoon effect to the generated image",}),];return (<Text><FormattedMessagedefaultMessage="You have selected the following image effects: {effects}"description="Informs the user about the image effects they have selected. effects is a list of effects that will be applied to the generated image."values={{effects: intl.formatList(selectedEffects, {type: "conjunction",}),}}/></Text>);};
This component renders based on the user's locale. For example, an English list uses an Oxford comma, but German does not:
- English (en-US): "You have selected the following image effects: black and white, high contrast, and cartoon."
- German (de-DE): "Sie haben die folgenden Bildeffekte ausgewählt: Schwarzweiß, hoher Kontrast und Cartoon."
Display name formatting
How to use display name formatting to inform users about the app's active language, using the FormattedMessage
component with React.
For example:
<FormattedMessagedefaultMessage="You are currently viewing this app in {language}"description="Shows the user which language the app is currently using"values={{language: intl.formatDisplayName(intl.locale, {type: "language",}),}}/>
Unsupported syntax
More information
- Overview of the localization process: Localization overview
- How to use the recommended workflow: Recommended workflow
- How to localize an existing app: Migrate an existing app
- Review the localization design guidelines: Localization