Message Extraction
Now that you've declared some messages, it's time to extract them.
Installation​
- npm
- yarn
npm i -D @formatjs/cli
yarn add -D @formatjs/cli
Extraction​
Add the following command to your package.json
scripts
:
{
"scripts": {
"extract": "formatjs extract"
}
}
and execute with npm
:
- npm
- yarn
npm run extract -- 'src/**/*.ts*' --ignore='**/*.d.ts' --out-file lang/en.json --id-interpolation-pattern '[sha512:contenthash:base64:6]'
yarn 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:
- React
- Vue3
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>
)
}
<template>
<section>
<header>
{{
$formatMessage({
defaultMessage: 'Control Panel',
description: 'title of control panel section',
})
}}
</header>
<ul>
<li>
<button>
{{
$formatMessage(
{
defaultMessage: 'Delete user {name}',
description: 'Delete button',
},
{
name: props.name,
}
)
}}
</button>
</li>
<li>
<input :placeholder="newPwdPlaceholder" />
<input :placeholder="confirmPwdPlaceholder" />
</li>
</ul>
</section>
</template>
<script>
export default {
inject: ['intl'],
props: ['name'],
data() {
return {
name: this.name,
newPwdPlaceholder: intl.formatMessage({
defaultMessage: 'New Password',
description: 'placeholder text',
}),
confirmPwdPlaceholder: intl.formatMessage({
id: 'explicit-id',
defaultMessage: 'Confirm Password',
description: 'placeholder text',
}),
}
},
}
</script>
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
- yarn
npm run extract -- "src/**/*.{ts,tsx,vue}" --out-file lang/en.json --id-interpolation-pattern '[sha512:contenthash:base64:6]' --format formatter.js
yarn 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 JSON | transifex |
Smartling ICU JSON | smartling |
Lingohub | simple |
Phrase | simple |
Crowdin Chrome JSON | crowdin |
Lokalise Structured JSON | lokalise |
SimpleLocalize JSON | simple |
POEditor Key-Value JSON | simple |
Localize's Simple JSON | simple |
locize | simple |