Universal build plugin for FormatJS — supports Vite, Webpack, Rollup, esbuild, and Rspack with one codebase.
Process string messages for translation from modules that use react-intl, specifically:
- Parse and verify that messages are ICU-compliant w/o any syntax issues.
- Remove
descriptionfrom message descriptor to save bytes since it isn't used at runtime. - Option to remove
defaultMessagefrom message descriptor to save bytes since it isn't used at runtime. - Automatically inject message ID based on specific pattern.
This plugin provides the same transformations as babel-plugin-formatjs and @formatjs/ts-transformer without requiring Babel or TypeScript custom transformers. It uses oxc-parser + magic-string for fast, compiler-agnostic builds.
Installation#
npm i -D @formatjs/unplugin
Usage#
The plugin processes message descriptors from: defineMessages(), defineMessage(), intl.formatMessage, $t, $formatMessage and <FormattedMessage>.
Vite#
// vite.config.ts
import {defineConfig} from 'vite'
import formatjs from '@formatjs/unplugin/vite'
export default defineConfig({
plugins: [
formatjs({
idInterpolationPattern: '[sha512:contenthash:base64:6]',
ast: true,
}),
],
})
Webpack#
// webpack.config.js
const formatjs = require('@formatjs/unplugin/webpack').default
module.exports = {
plugins: [
formatjs({
idInterpolationPattern: '[sha512:contenthash:base64:6]',
ast: true,
}),
],
}
Rollup#
// rollup.config.js
import formatjs from '@formatjs/unplugin/rollup'
export default {
plugins: [
formatjs({
idInterpolationPattern: '[sha512:contenthash:base64:6]',
ast: true,
}),
],
}
esbuild#
import esbuild from 'esbuild'
import formatjs from '@formatjs/unplugin/esbuild'
esbuild.build({
plugins: [
formatjs({
idInterpolationPattern: '[sha512:contenthash:base64:6]',
ast: true,
}),
],
})
Rspack#
// rspack.config.js
const formatjs = require('@formatjs/unplugin/rspack').default
module.exports = {
plugins: [
formatjs({
idInterpolationPattern: '[sha512:contenthash:base64:6]',
ast: true,
}),
],
}
For example, given this component:
<FormattedMessage
description="A message"
defaultMessage="My name is {name}"
values={{
name: userName,
}}
/>
The plugin will produce:
React.createElement(FormattedMessage, {
id: '179jda',
defaultMessage: 'My name is {name}',
values: {
name: userName,
},
})
description
Our plugin also removes description because it's only for translator, not
end-user.
Migrating from babel-plugin-formatjs#
Replace your Babel plugin configuration with the appropriate bundler import from @formatjs/unplugin. The options are the same.
Migrating from @formatjs/vite-plugin#
@formatjs/vite-plugin now re-exports from @formatjs/unplugin/vite internally. You can switch your import with no configuration changes:
// vite.config.ts
- import formatjs from '@formatjs/vite-plugin'
+ import formatjs from '@formatjs/unplugin/vite'
Options#
overrideIdFn#
A function with the signature (id: string, defaultMessage: string, description: string, filePath: string) => string which allows you to override the ID both in the extracted javascript and messages.
idInterpolationPattern#
If certain message descriptors don't have id, this pattern will be used to automatically generate IDs for them. Default to [sha512:contenthash:base64:6]. See nodejs crypto createHash for hash algorithms & nodejs buffer docs for digest encodings.
removeDefaultMessage#
Remove defaultMessage field in generated js after extraction.
additionalComponentNames#
Additional component names to extract messages from, e.g: ['FormattedFooBarMessage'].
formatjs({
idInterpolationPattern: '[sha512:contenthash:base64:6]',
additionalComponentNames: ['CustomButton'],
})
additionalFunctionNames#
Additional function names to extract messages from, e.g: ['$formatMessage'].
formatjs({
idInterpolationPattern: '[sha512:contenthash:base64:6]',
additionalFunctionNames: ['t', '$formatMessage'],
})
ast#
Pre-parse defaultMessage into AST for faster runtime perf. This flag doesn't do anything when removeDefaultMessage is true.
preserveWhitespace#
When set to true, message trimming is disabled.