Message Declaration
While you can declare your messages using only id
s, we highly recommend declaring defaultMessage
s inline along with their usages because of the following reasons:
- Messages colocated with their usages become self-managed, as their usages change/removed, so are the messages.
- Messages are highly contextual. We've seen a lot of cases where developers assume a certain grammar when they write their messages. Buttons/Call-To-Actions and labels are also translated differently.
- Text styling is also dependent on the message itself. Things like truncation, capitalization... certainly affect the messages themselves.
- Better integrations with toolchains. Most toolchains cannot verify cross-file references to validate syntax/usage.
At a high level, formatjs messages use ICU Syntax with a couple of enhancements common in other message format such as Fluent. This section focuses on the actual supported ways of calling formatjs
APIs so messages can be extracted.
Using imperative API intl.formatMessage
// Method must be exactly `intl.formatMessage`
intl.formatMessage(
{
description: 'A message', // Description should be a string literal
defaultMessage: 'My name is {name}', // Message should be a string literal
},
{
name: userName,
} // Values should be an object literal, but not necessarily every value inside
)
Using React API <FormattedMessage/>
import {FormattedMessage} from 'react-intl'
;<FormattedMessage
description="A message" // Description should be a string literal
defaultMessage="My name is {name}" // Message should be a string literal
values={
{
name: userName,
} // Values should be an object literal, but not necessarily every value inside
}
/>
Using Vue API & template methods such as $formatMessage
<template>
<p>{{ $formatNumber(3, {style: 'currency', currency: 'USD'}) }}</p>
</template>
Pre-declaring using defineMessage
for later consumption (less recommended)
import {defineMessage} from 'react-intl'
const message = defineMessage({
description: 'A message', // Description should be a string literal
defaultMessage: 'My name is {name}', // Message should be a string literal
})
intl.formatMessage(message, {name: 'John'}) // My name is John
<FormattedMessage
{...message}
values={{
name: 'John',
}}
/> // My name is John
We rely on AST to extract messages from the codebase, so make sure you call intl.formatMessage()
, use our builtin React components, use our Vue methods or configure --additionalFunctionNames
/--additionalComponentNames
in our CLI properly.
You can declare a message without immediately formatting it with defineMessage
and our extractor would still be able to extract it. However, our enforce-placeholders linter rule won't be able to analyze it.