Awesome
babel-plugin-react-intl-auto
i18n for the component age. Auto management react-intl ID.
React Intl is awesome. But, Global ID management is difficult and confusing.
Many projects, like react-boilerplate, give the ID to the name of the component as a prefix. But it is redundant and troublesome.
This babel-plugin releases you from cumbersome ID management. Based on the file path, this automatically generates a prefixed id.
Also, we strongly encourage you to use extract-react-intl-messages. You can generate json automatically.
Goodbye, global ID!!
Before
import { defineMessages, FormattedMessage } from 'react-intl'
export default defineMessages({
hello: {
id: 'App.Components.Greeting.hello',
defaultMessage: 'hello {name}',
},
welcome: {
id: 'App.Components.Greeting.welcome',
defaultMessage: 'Welcome!',
},
})
const MyComponent = () => (
<FormattedMessage
id="App.Components.Greeting.goodbye"
defaultMessage="goodbye {name}"
/>
)
After
With babel-plugin-react-intl-auto.
import { defineMessages, FormattedMessage } from 'react-intl'
export default defineMessages({
hello: 'hello {name}',
welcome: 'Welcome!',
})
const MyComponent = () => <FormattedMessage defaultMessage="goodbye {name}" />
See examples.
With extract-react-intl-messages
Example usage with extract-react-intl-messages.
$ extract-messages -l=en -o translations 'src/**/*.js'
en.json
{
"components.App.hello": "hello {name}",
"components.App.welcome": "Welcome",
"components.App.189751785": "goodbye {name}" // unique hash of defaultMessage
}
Install
npm
$ npm install --save-dev babel-plugin-react-intl-auto
# Optional: TypeScript support
$ npm install --save-dev @babel/plugin-transform-typescript
yarn
$ yarn add --dev babel-plugin-react-intl-auto
# Optional: TypeScript support
$ yarn add --dev @babel/plugin-transform-typescript
Usage
.babelrc
{
"plugins": [
[
"react-intl-auto",
{
"removePrefix": "app/",
"filebase": false
}
]
]
}
with injectIntl
Input:
import { injectIntl } from 'react-intl'
const MyComponent = ({ intl }) => {
const label = intl.formatMessage({ defaultMessage: 'Submit button' })
return <button aria-label={label}>{label}</button>
}
injectIntl(MyComponent)
↓ ↓ ↓
Output:
import { injectIntl } from 'react-intl'
const MyComponent = ({ intl }) => {
const label = intl.formatMessage({
id: 'App.Components.Button.label',
defaultMessage: 'Submit button',
})
return <button aria-label={label}>{label}</button>
}
injectIntl(MyComponent)
with useIntl
Input:
import { useIntl } from 'react-intl'
const MyComponent = () => {
const intl = useIntl()
const label = intl.formatMessage({ defaultMessage: 'Submit button' })
return <button aria-label={label}>{label}</button>
}
↓ ↓ ↓
Output:
import { useIntl } from 'react-intl'
const MyComponent = () => {
const intl = useIntl()
const label = intl.formatMessage({
id: 'App.Components.Button.label',
defaultMessage: 'Submit button',
})
return <button aria-label={label}>{label}</button>
}
Options
removePrefix
remove prefix.
Type: string | boolean
| regexp
<br>
Default: ''
if removePrefix
is true
, no file path prefix is included in the id.
Example (src/components/App/messages.js)
when removePrefix
is "src"
import { defineMessages } from 'react-intl';
export default defineMessages({
hello: 'hello world'
});
↓ ↓ ↓ ↓ ↓ ↓
import { defineMessages } from 'react-intl';
export default defineMessages({
hello: {
id: 'components.App.hello',
defaultMessage: 'hello world'
}
});
when removePrefix
is "src.components"
import { defineMessages } from 'react-intl';
export default defineMessages({
hello: 'hello world'
});
↓ ↓ ↓ ↓ ↓ ↓
import { defineMessages } from 'react-intl';
export default defineMessages({
hello: {
id: 'App.hello',
defaultMessage: 'hello world'
}
});
when removePrefix
is true
import { defineMessages } from 'react-intl';
export default defineMessages({
hello: 'hello world'
});
↓ ↓ ↓ ↓ ↓ ↓
import { defineMessages } from 'react-intl';
export default defineMessages({
hello: {
id: 'hello',
defaultMessage: 'hello world'
}
});
filebase
Type: boolean
<br>
Default: false
if filebase
is true
, generate id with filename.
moduleSourceName
Type: string
<br>
Default: react-intl
if set, enables to use custom module as a source for defineMessages etc.
https://github.com/akameco/babel-plugin-react-intl-auto/issues/74#issuecomment-528562743
includeExportName
Type: boolean | 'all'
<br>
Default: false
if includeExportName
is true
, adds named exports as part of the id.
Only works with defineMessages
.
Example
export const test = defineMessages({
hello: 'hello {name}',
})
↓ ↓ ↓ ↓ ↓ ↓
export const test = defineMessages({
hello: {
id: 'path.to.file.test.hello',
defaultMessage: 'hello {name}',
},
})
If includeExportName is 'all'
, it will also add default
to the id on default
exports.
extractComments
Use leading comments as the message description.
Only works with defineMessages
Type: boolean
<br>
Default: true
Example
export const test = defineMessages({
// Message used to greet the user
hello: 'hello {name}',
})
↓ ↓ ↓ ↓ ↓ ↓
export const test = defineMessages({
hello: {
id: 'path.to.file.test.hello',
defaultMessage: 'hello {name}',
description: 'Message used to greet the user',
},
})
useKey
Only works with intl.formatMessage
, FormattedMessage
and FormattedHTMLMessage
. Instead of
generating an ID by hashing defaultMessage
, it will use the key
property if
it exists.
Type: boolean
<br>
Default: false
Example
intl.formatMessage({
key: 'foobar',
defaultMessage: 'hello'
});
↓ ↓ ↓ ↓ ↓ ↓
intl.formatMessage({
key: 'foobar',
defaultMessage: 'hello',
"id": "path.to.file.foobar"
});
<FormattedMessage key="foobar" defaultMessage="hello" />
↓ ↓ ↓ ↓ ↓ ↓
<FormattedMessage id="path.to.file.foobar" key="foobar" defaultMessage="hello" />
separator
Allows you to specify a custom separator
Type: string
<br>
Default: .
Example
when separator
is "_"
export const test = defineMessages({
hello: 'hello {name}',
})
↓ ↓ ↓ ↓ ↓ ↓
export const test = defineMessages({
hello: {
id: 'path_to_file_test_hello',
defaultMessage: 'hello {name}',
},
})
relativeTo
Allows you to specify the directory that is used when determining a file's prefix.
This option is useful for monorepo setups.
Type: string
<br>
Default: process.cwd()
Example
Folder structure with two sibling packages. packageB
contains babel config and depends on packageA
.
|- packageA
| |
| -- componentA
|
|- packageB
| |
| -- componentB
| |
| -- .babelrc
Set relativeTo
to parent directory in packageB
babel config
{
"plugins": [
[
"react-intl-auto",
{
"relativeTo": "..",
// ...
},
],
]
}
Run babel in packageB
cd packageB && babel
Messages in componentA
are prefixed relative to the project root
export const test = defineMessages({
hello: 'hello {name}',
})
↓ ↓ ↓ ↓ ↓ ↓
export const test = defineMessages({
hello: {
id: 'packageA.componentA.hello',
defaultMessage: 'hello {name}',
},
})
Support variable
Example
const messages = { hello: 'hello world' }
export default defineMessages(messages)
↓ ↓ ↓ ↓ ↓ ↓
const messages = {
hello: {
id: 'path.to.file.hello',
defaultMessage: 'hello wolrd'
}
};
export default defineMessages(messages);
TypeScript
TypeScript support is bundled with this package. Be sure to include our type
definition and run @babel/plugin-transform-typescript
beforehand. This way,
you can also be empowered by extract-react-intl-messages.
tsconfig.json
{
"compilerOptions": {
// ...
"jsx": "preserve"
// ...
},
"include": ["node_modules/babel-plugin-react-intl-auto/**/*.d.ts"]
}
.babelrc
{
"plugins": [["@babel/plugin-transform-typescript"], ["react-intl-auto"]]
}
webpack.config.js
Use babel-loader
along with ts-loader
when using webpack as well.
module.exports = {
module: {
rules: [
{
test: /\.tsx?$/,
exclude: [/node_modules/],
use: [
{
loader: 'babel-loader',
},
{
loader: 'ts-loader',
},
],
},
],
},
}
Related
babel-plugin-react-intl-id-hash
If you want short consistent hash values for the ID, you can use react-intl-id-hash in addition to this plugin to help reduce your applications bundle size.
extract-react-intl-messages
Extract react-intl messages.
Contributors
Thanks goes to these wonderful people (emoji key):
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section --> <!-- prettier-ignore-start --> <!-- markdownlint-disable --> <table> <tr> <td align="center"><a href="http://akameco.github.io"><img src="https://avatars2.githubusercontent.com/u/4002137?v=4" width="100px;" alt=""/><br /><sub><b>akameco</b></sub></a><br /><a href="https://github.com/akameco/babel-plugin-react-intl-auto/commits?author=akameco" title="Code">💻</a> <a href="https://github.com/akameco/babel-plugin-react-intl-auto/commits?author=akameco" title="Tests">⚠️</a> <a href="https://github.com/akameco/babel-plugin-react-intl-auto/pulls?q=is%3Apr+reviewed-by%3Aakameco" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/akameco/babel-plugin-react-intl-auto/commits?author=akameco" title="Documentation">📖</a></td> <td align="center"><a href="http://alxandr.me"><img src="https://avatars0.githubusercontent.com/u/112334?v=4" width="100px;" alt=""/><br /><sub><b>Aleksander Heintz</b></sub></a><br /><a href="https://github.com/akameco/babel-plugin-react-intl-auto/commits?author=Alxandr" title="Code">💻</a> <a href="https://github.com/akameco/babel-plugin-react-intl-auto/commits?author=Alxandr" title="Documentation">📖</a></td> <td align="center"><a href="https://github.com/mehcode"><img src="https://avatars1.githubusercontent.com/u/753919?v=4" width="100px;" alt=""/><br /><sub><b>Ryan Leckey</b></sub></a><br /><a href="https://github.com/akameco/babel-plugin-react-intl-auto/commits?author=mehcode" title="Code">💻</a></td> <td align="center"><a href="https://github.com/adam-26"><img src="https://avatars1.githubusercontent.com/u/2652619?v=4" width="100px;" alt=""/><br /><sub><b>Adam</b></sub></a><br /><a href="https://github.com/akameco/babel-plugin-react-intl-auto/commits?author=adam-26" title="Code">💻</a> <a href="https://github.com/akameco/babel-plugin-react-intl-auto/commits?author=adam-26" title="Documentation">📖</a></td> <td align="center"><a href="https://ephys.github.io"><img src="https://avatars0.githubusercontent.com/u/1280915?v=4" width="100px;" alt=""/><br /><sub><b>Guylian Cox</b></sub></a><br /><a href="https://github.com/akameco/babel-plugin-react-intl-auto/commits?author=Ephys" title="Code">💻</a> <a href="https://github.com/akameco/babel-plugin-react-intl-auto/commits?author=Ephys" title="Documentation">📖</a> <a href="https://github.com/akameco/babel-plugin-react-intl-auto/commits?author=Ephys" title="Tests">⚠️</a></td> <td align="center"><a href="http://carlgrundberg.github.io/"><img src="https://avatars1.githubusercontent.com/u/928407?v=4" width="100px;" alt=""/><br /><sub><b>Carl Grundberg</b></sub></a><br /><a href="#example-carlgrundberg" title="Examples">💡</a> <a href="https://github.com/akameco/babel-plugin-react-intl-auto/commits?author=carlgrundberg" title="Documentation">📖</a></td> <td align="center"><a href="http://bradbarrow.com"><img src="https://avatars3.githubusercontent.com/u/1264276?v=4" width="100px;" alt=""/><br /><sub><b>bradbarrow</b></sub></a><br /><a href="https://github.com/akameco/babel-plugin-react-intl-auto/commits?author=bradbarrow" title="Code">💻</a> <a href="https://github.com/akameco/babel-plugin-react-intl-auto/commits?author=bradbarrow" title="Documentation">📖</a> <a href="https://github.com/akameco/babel-plugin-react-intl-auto/commits?author=bradbarrow" title="Tests">⚠️</a></td> </tr> <tr> <td align="center"><a href="https://github.com/mgtitimoli"><img src="https://avatars2.githubusercontent.com/u/4404683?v=4" width="100px;" alt=""/><br /><sub><b>Mauro Gabriel Titimoli</b></sub></a><br /><a href="https://github.com/akameco/babel-plugin-react-intl-auto/commits?author=mgtitimoli" title="Code">💻</a> <a href="https://github.com/akameco/babel-plugin-react-intl-auto/commits?author=mgtitimoli" title="Tests">⚠️</a></td> <td align="center"><a href="https://github.com/stanislav-ermakov"><img src="https://avatars2.githubusercontent.com/u/15980086?v=4" width="100px;" alt=""/><br /><sub><b>Stanislav Ermakov</b></sub></a><br /><a href="https://github.com/akameco/babel-plugin-react-intl-auto/commits?author=stanislav-ermakov" title="Code">💻</a></td> <td align="center"><a href="https://chitoku.jp/"><img src="https://avatars1.githubusercontent.com/u/6535425?v=4" width="100px;" alt=""/><br /><sub><b>Chitoku</b></sub></a><br /><a href="https://github.com/akameco/babel-plugin-react-intl-auto/commits?author=chitoku-k" title="Code">💻</a></td> <td align="center"><a href="https://github.com/kuma-kuma"><img src="https://avatars0.githubusercontent.com/u/12218082?v=4" width="100px;" alt=""/><br /><sub><b>Kouta Kumagai</b></sub></a><br /><a href="https://github.com/akameco/babel-plugin-react-intl-auto/commits?author=kuma-kuma" title="Documentation">📖</a> <a href="https://github.com/akameco/babel-plugin-react-intl-auto/commits?author=kuma-kuma" title="Code">💻</a> <a href="https://github.com/akameco/babel-plugin-react-intl-auto/commits?author=kuma-kuma" title="Tests">⚠️</a></td> <td align="center"><a href="http://shah.yar.gs"><img src="https://avatars0.githubusercontent.com/u/255846?v=4" width="100px;" alt=""/><br /><sub><b>Shahyar G</b></sub></a><br /><a href="https://github.com/akameco/babel-plugin-react-intl-auto/commits?author=shahyar" title="Code">💻</a></td> <td align="center"><a href="https://gitlab.com/remcohaszing"><img src="https://avatars2.githubusercontent.com/u/779047?v=4" width="100px;" alt=""/><br /><sub><b>Remco Haszing</b></sub></a><br /><a href="https://github.com/akameco/babel-plugin-react-intl-auto/commits?author=remcohaszing" title="Code">💻</a></td> <td align="center"><a href="https://github.com/jmarceli"><img src="https://avatars1.githubusercontent.com/u/4281333?v=4" width="100px;" alt=""/><br /><sub><b>jmarceli</b></sub></a><br /><a href="https://github.com/akameco/babel-plugin-react-intl-auto/commits?author=jmarceli" title="Code">💻</a> <a href="https://github.com/akameco/babel-plugin-react-intl-auto/commits?author=jmarceli" title="Tests">⚠️</a></td> </tr> <tr> <td align="center"><a href="https://github.com/dominik-zeglen"><img src="https://avatars3.githubusercontent.com/u/6833443?v=4" width="100px;" alt="Dominik Żegleń"/><br /><sub><b>Dominik Żegleń</b></sub></a><br /><a href="https://github.com/akameco/babel-plugin-react-intl-auto/commits?author=dominik-zeglen" title="Code">💻</a> <a href="https://github.com/akameco/babel-plugin-react-intl-auto/commits?author=dominik-zeglen" title="Tests">⚠️</a></td> <td align="center"><a href="https://github.com/Filson14"><img src="https://avatars1.githubusercontent.com/u/4540538?v=4" width="100px;" alt="Filip "Filson" Pasternak"/><br /><sub><b>Filip "Filson" Pasternak</b></sub></a><br /><a href="https://github.com/akameco/babel-plugin-react-intl-auto/commits?author=Filson14" title="Code">💻</a></td> <td align="center"><a href="https://github.com/ericmasiello"><img src="https://avatars3.githubusercontent.com/u/3525886?v=4" width="100px;" alt="Eric Masiello"/><br /><sub><b>Eric Masiello</b></sub></a><br /><a href="https://github.com/akameco/babel-plugin-react-intl-auto/commits?author=ericmasiello" title="Code">💻</a> <a href="https://github.com/akameco/babel-plugin-react-intl-auto/commits?author=ericmasiello" title="Tests">⚠️</a></td> <td align="center"><a href="https://github.com/pooleparty"><img src="https://avatars3.githubusercontent.com/u/5461259?v=4" width="100px;" alt="Josh Poole"/><br /><sub><b>Josh Poole</b></sub></a><br /><a href="https://github.com/akameco/babel-plugin-react-intl-auto/commits?author=pooleparty" title="Code">💻</a> <a href="https://github.com/akameco/babel-plugin-react-intl-auto/commits?author=pooleparty" title="Tests">⚠️</a></td> </tr> </table> <!-- markdownlint-enable --> <!-- prettier-ignore-end --> <!-- ALL-CONTRIBUTORS-LIST:END -->This project follows the all-contributors specification. Contributions of any kind welcome!
License
MIT © akameco