Skip to main content

Message Extraction

Now that you've declared some messages, it's time to extract them.

Installation​

npm i -D @formatjs/cli

Extraction​

Add the following command to your package.json scripts:

{
"scripts": {
"extract": "formatjs extract"
}
}

and execute with npm:

npm run extract -- 'src/**/*.ts*' --ignore='**/*.d.ts' --out-file lang/en.json --id-interpolation-pattern '[sha512:contenthash:base64:6]'
ID Interpolation Pattern

Make sure this pattern matches idInterpolationPattern when you use babel-plugin-formatjs or @formatjs/ts-transformer in Bundling with formatjs or you'll get a MISSING_TRANSLATION error.

Given a file that has the following messages:

import * as React from 'react'
import {FormattedMessage, useIntl, injectIntl} from 'react-intl'

class PasswordChangeWithIntl extends React.Component {
render() {
const {intl} = this.props
return (
<li>
<input
placeholder={intl.formatMessage({
defaultMessage: 'New Password',
description: 'placeholder text',
})}
/>
<input
placeholder={intl.formatMessage({
id: 'explicit-id',
defaultMessage: 'Confirm Password',
description: 'placeholder text',
})}
/>
</li>
)
}
}

const PasswordChange = injectIntl(PasswordChangeWithIntl)

export function List(props) {
const intl = useIntl()
return (
<section>
<header>
<FormattedMessage
defaultMessage="Control Panel"
description="title of control panel section"
/>
</header>
<ul>
<li>
<button>
<FormattedMessage
defaultMessage="Delete user {name}"
description="Delete button"
values={{
name: props.name,
}}
/>
</button>
</li>
<PasswordChange />
</ul>
</section>
)
}

running the above command will create a file called lang/en.json:

{
"hak27d": {
"defaultMessage": "Control Panel",
"description": "title of control panel section"
},
"haqsd": {
"defaultMessage": "Delete user {name}",
"description": "delete button"
},
"19hjs": {
"defaultMessage": "New Password",
"description": "placeholder text"
},
"explicit-id": {
"defaultMessage": "Confirm Password",
"description": "placeholder text"
}
}
Message ID

During extraction, we'll preserve explicit declared IDs and insert a hash as an ID for messages without. We recommend against explicit IDs since it can cause collision.

Automatic ID Generation​

Since manual IDs are discouraged, we've provided a babel plugin and a TypeScript AST transformer that will automatically insert message IDs in your transpiled code. For more details please visit Bundling with formatjs.

Translation Management System (TMS) Integration​

The default format generated from @formatjs/cli might not work with the specific TMS/vendor you're working with. You can specify a custom formatter with --format <formatFile> that allows you to convert that format into something tailored to your TMS. For example:

If your vendor accepts the format like

{
"[id]": {
"string": "[message]",
"comment": "[description]"
}
}

you can run

npm run extract -- "src/**/*.{ts,tsx,vue}" --out-file lang/en.json --id-interpolation-pattern '[sha512:contenthash:base64:6]' --format formatter.js

where formatter.js is:

exports.format = function (msgs) {
const results = {}
for (const [id, msg] of Object.entries(msgs)) {
results[id] = {
string: msg.defaultMessage,
comment: msg.description,
}
}
return results
}

We also provide several builtin formatters to integrate with 3rd party TMSes so feel free to create PRs to add more.

TMS--format
Transifex's Structured JSONtransifex
Smartling ICU JSONsmartling
Lingohubsimple
Phrasesimple
Crowdin Chrome JSONcrowdin
Lokalise Structured JSONlokalise
SimpleLocalize JSONsimple
POEditor Key-Value JSONsimple
Localize's Simple JSONsimple
locizesimple