Note: This project is still under active, early development.
babel-plugin-i18next-extract is a Babel Plugin that will
traverse your JavaScript/Typescript code in order to find i18next translation keys.
Installation
yarn add --dev babel-plugin-i18next-extract
npm i --save-dev babel-plugin-i18next-extract
Usage
If you already use Babel, chances are you already have an babel
configuration (e.g. a .babelrc
file). Just add declare the plugin and you're good to go:
{
"plugins": [
"i18next-extract",
]
}
You can also specify additional configuration options to the plugin:
{
"plugins": [
["i18next-extract", {"nsSeparator": "~"}],
]
}
Once you are set up, you can build your app normally or run Babel through Babel CLI:
yarn run babel -f .babelrc 'src/**/*.{js,jsx,ts,tsx}'
npm run babel -f .babelrc 'src/**/*.{js,jsx,ts,tsx}'
Extracted translations should land in the extractedTranslations/
directory. Magic huh?
If you don't have a babel configuration yet, you can follow the Configure Babel documentation to try setting it up.
Usage with create-react-app
create-react-app doesn't let you modify the babel
configuration. Fortunately, it's still possible to use this plugin without ejecting. First of all,
install Babel CLI:
yarn add --dev @babel/cli
npm add --save-dev @babel/cli
Create a minimal .babelrc
that uses the react-app
babel preset (DO NOT install it, it's already
shipped with CRA):
{
"presets": ["react-app"],
"plugins": ["i18next-extract"]
}
You should then be able to extract your translations using the CLI:
NODE_ENV=development yarn run babel -f .babelrc 'src/**/*.{js,jsx,ts,tsx}'
To simplify the extraction, you can add a script to your package.json
:
"scripts": {
[…]
"i18n-extract": "NODE_ENV=development babel -f .babelrc 'src/**/*.{js,jsx,ts,tsx}'",
[…]
}
And then just run:
yarn run i18n-extract
npm run i18n-extract
Features
Configuration
Option | Type | Description | Default |
---|
locales | string[] | All the locales your project supports. babel-plugin-i18next-extract will generate a JSON file for each locale. | ['en'] |
defaultNS | string | The default namespace that your translation use. | 'translation' |
pluralSeparator | string | String you want to use to split plural from keys. See i18next Configuration options | '_' |
contextSeparator | string | String you want to use to split context from keys. See i18next Configuration options | '_' |
keySeparator | string or null | String you want to use to split keys. Set to null if you don't want to split your keys or if you want to use keys as value. See i18next Configuration options | '.' |
nsSeparator | string or null | String you want to use to split namespace from keys. Set to null if you don't want to infer a namespace from key value or if you want to use keys as value. See See i18next Configuration options | ':' |
i18nextInstancesNames | string[] | Possible names of you i18next object instances. This will be used to detect i18next.t calls. | ['i18next', 'i18n'] |
defaultContexts | string[] | Default context keys to create when detecting a translation with context. | ['', '_male', '_female'] |
outputPath | string | Path where translation keys should be extracted to. You can put {{ns}} and {{locale}} placeholders in the value to change the location depending on the namespace or the locale. | extractedTranslations/{{locale}}/{{ns}}.json |
defaultValue | string or null | Default value for extracted keys. | '' (empty string) |
keyAsDefaultValue | boolean or string[] | If true, use the extracted key as defaultValue (ignoring defaultValue option). You can also specify an array of locales to apply this behavior only to a specific set locales (e.g. if you keys are in plain english, you may want to set this option to ['en'] ). | false |
keyAsDefaultValueForDerivedKeys | boolean | If false and keyAsDefaultValue is enabled, don't use derived keys (plural forms or contexts) as default value. defaultValue will be used instead. | true |
exporterJsonSpace | number | Number of indentation space to use in extracted JSON files. | 2 |
If the plugin extracts a key you want to skip or erroneously tries to parse a function that doesn't
belong to i18next, you can use a comment hint to disable the extraction:
i18next.t("this key won't be extracted")
i18next.t("neither this one")
i18next.t("or this one")
i18next.t("and this one")
i18next.t("but this one will be")
You can put a // i18next-extract-disable
comment at the top of the file in order to disable
extraction on the entire file.
Explicitly specify contexts for a key
This is very useful if you want to use different contexts than the default male
and female
for a given key:
i18next.t("this key will have dog and cat context", {context: dogOrCat})
i18next.t("this key will have default context, although no context is specified")
i18next.t("this key wont have a context, although a context is specified", {context})
i18next.t("can be used on line")
i18next.t("or on sections")
const transComponent = (
<Trans>it also works on Trans components</Trans>
)
Explicitly use a namespace for a key
i18next.t("this key will be in forced-ns namespace")
i18next.t("this one also", {ns: 'this-ns-wont-be-used'})
i18next.t("and still this one")
Explicitly enable/disable a plural form for a key
i18next.t("this key will be in forced in plural form")
i18next.t("this key wont have plural form", {count})
Gotchas
The plugin tries to be smart, but can't do magic. i18next has a runtime unlike this plugin which
must guess everything statically. For instance, you may want to disable extraction on dynamic
keys:
i18next.t(myVariable);
i18next.t(`error.${code}`);
If you try to extract keys from this code, the plugin will issue a warning because it won't be
able to infer the translations statically. If you really want to specify variable keys, you should
skip them with a comment hint. The same goes for plural forms, context and
namespace detection:
i18next.t("myKey", myOpts);
However, in React components, it might come handy to be a little smarter than that. That's why
when using a <Trans>
component, the plugin will try to resolve references before resigning. For
instance, this code should extract properly:
const foo = <p>Hello</p>
const bar = <Trans>{foo} world</Trans>