What is i18next-parser?
i18next-parser is a tool that extracts translation keys from your source code to JSON, allowing you to manage and maintain your internationalization (i18n) files more efficiently. It supports various file formats and can be integrated into your build process.
What are i18next-parser's main functionalities?
Extract Translation Keys
This feature allows you to extract translation keys from your source code files and generate JSON files for each locale. The code sample demonstrates how to use i18next-parser to parse JavaScript files in the 'src' directory and output the translations to 'locales/en/translation.json' and 'locales/fr/translation.json'.
const parser = require('i18next-parser');
const fs = require('fs');
const options = {
locales: ['en', 'fr'],
output: 'locales/$LOCALE/$NAMESPACE.json'
};
parser.parseFiles('src/**/*.js', options, (err, translations) => {
if (err) throw err;
fs.writeFileSync('locales/en/translation.json', JSON.stringify(translations.en, null, 2));
fs.writeFileSync('locales/fr/translation.json', JSON.stringify(translations.fr, null, 2));
});
Support for Multiple File Formats
i18next-parser supports multiple file formats including JavaScript, JSX, TypeScript, and TSX. The code sample shows how to configure the parser to handle these different file types and extract translations from them.
const parser = require('i18next-parser');
const options = {
input: ['src/**/*.js', 'src/**/*.jsx', 'src/**/*.ts', 'src/**/*.tsx'],
output: 'locales/$LOCALE/$NAMESPACE.json'
};
parser.parseFiles(options.input, options, (err, translations) => {
if (err) throw err;
console.log('Translations extracted successfully');
});
Customizable Output
You can customize the output path and separators for namespaces and keys. The code sample demonstrates how to set a custom output path and define custom separators for namespaces and keys.
const parser = require('i18next-parser');
const options = {
locales: ['en', 'de'],
output: 'custom_locales/$LOCALE/$NAMESPACE.json',
namespaceSeparator: ':',
keySeparator: '.'
};
parser.parseFiles('src/**/*.js', options, (err, translations) => {
if (err) throw err;
console.log('Custom output path and separators applied');
});
Other packages similar to i18next-parser
babel-plugin-i18next-extract
babel-plugin-i18next-extract is a Babel plugin that extracts translation keys from your code and generates JSON files for i18next. It integrates directly with Babel, making it a good choice if you are already using Babel in your project. Compared to i18next-parser, it offers a more seamless integration with the Babel build process but may require more setup if you are not using Babel.
react-intl-translations-manager
react-intl-translations-manager is a tool for managing translations in projects using react-intl. It extracts messages from your React components and generates translation files. While it is specifically designed for use with react-intl, it offers similar functionality to i18next-parser in terms of extracting and managing translation keys. However, it is less flexible in terms of file format support and integration with non-React projects.
i18next Parser
When translating an application, maintaining the translation catalog by hand is painful. This package parses your code and automates this process.
Finally, if you want to make this process even less painful, I invite you to check Locize. They are a sponsor of this project. Actually, if you use this package and like it, supporting me on Patreon would mean a great deal!
Features
- Choose your weapon: A CLI, a standalone parser or a stream transform
- 4 built in lexers: Javascript, JSX, HTML and Handlebars
- Creates one catalog file per locale and per namespace
- Backs up the old keys your code doesn't use anymore in
namespace_old.json
catalog - Restores keys from the
_old
file if the one in the translation file is empty - Supports i18next features:
- Context: keys of the form
key_context
- Plural: keys of the form
key_plural
and key_plural_0
- Tested on Node 6+
DISCLAMER: 1.0.0-beta
1.x
is currently in beta. You can follow the pre-releases here. It is a deep rewrite of this package that solves many issues, the main one being that it was slowly becoming unmaintainable. The migration contains all the breaking changes. Everything that follows is related to 1.x
. If you rely on a 0.x.x
version, you can still find the old documentation on its dedicated branch.
Usage
CLI
You can use the CLI with the package installed locally but if you want to use it from anywhere, you better install it globally:
yarn global add i18next-parser@next
npm install -g i18next-parser@next
i18next 'app/**/*.{js,hbs}' 'lib/**/*.{js,hbs}' [-oc]
Multiple globbing patterns are supported to specify complex file selections. You can learn how to write globs here. Note that glob must be wrapped with single quotes when passed as arguments.
- -c, --config : Path to the output directory (default: locales/$LOCALE/$NAMESPACE.json)
- -o, --output : Where to write the locale files.
- -S, --silent: Disable logging to stdout.
Gulp
Save the package to your devDependencies:
yarn add -D i18next-parser@next
npm install --save-dev i18next-parser@next
Gulp defines itself as the streaming build system. Put simply, it is like Grunt, but performant and elegant.
const i18nextParser = require('i18next-parser').gulp;
gulp.task('i18next', function() {
gulp.src('app/**')
.pipe(new i18nextParser({
locales: ['en', 'de'],
output: 'locales/$LOCALE/$NAMESPACE.json'
}))
.pipe(gulp.dest('./'));
});
IMPORTANT: output
is required to know where to read the catalog from. You might think that gulp.dest()
is enough though it does not inform the transform where to read the existing catalog from.
Broccoli
Save the package to your devDependencies:
yarn add -D i18next-parser@next
npm install --save-dev i18next-parser@next
Broccoli.js defines itself as a fast, reliable asset pipeline, supporting constant-time rebuilds and compact build definitions.
const Funnel = require('broccoli-funnel')
const i18nextParser = require('i18next-parser').broccoli;
const appRoot = 'broccoli'
let i18n = new Funnel(appRoot, {
files: ['handlebars.hbs', 'javascript.js'],
annotation: 'i18next-parser'
})
i18n = new i18nextParser([i18n], {
output: 'broccoli/locales/$LOCALE/$NAMESPACE.json'
})
module.exports = i18n
Options
Using a config file gives you fine-grained control over how i18next-parser treats your files. Here's an example config showing all config options with their defaults.
module.exports = {
contextSeparator: '_',
createOldCatalogs: true,
defaultNamespace: 'translation',
defaultValue: '',
indentation: 2,
keepRemoved: false,
keySeparator: '.',
lexers: {
hbs: ['HandlebarsLexer'],
handlebars: ['HandlebarsLexer'],
htm: ['HTMLLexer'],
html: ['HTMLLexer'],
js: ['JavascriptLexer'],
jsx: ['JsxLexer'],
mjs: ['JavascriptLexer'],
default: ['JavascriptLexer']
},
lineEnding: 'auto',
locales: ['en', 'fr'],
namespaceSeparator: ':',
output: 'locales/$LOCALE/$NAMESPACE.json',
input: undefined,
reactNamespace: false,
sort: false,
verbose: false
}
Lexers
The lexers
option let you configure which Lexer to use for which extension. Here is the default:
Note the presence of a default
which will catch any extension that is not listed. There are 3 lexers available: HandlebarsLexer
, HTMLLexer
and JavascriptLexer
. Each has configurations of its own. If you need to change the defaults, you can do it like so:
[
handlebars: [{
lexer: 'HandlebarsLexer',
functions: ['t']
}]
html: [{
lexer: 'HtmlLexer',
attr: 'data-i18n'
optionAttr: 'data-i18n-options'
}]
js: [{
lexer: 'JavascriptLexer'
functions: ['t'],
acorn: {
sourceType: 'module',
ecmaVersion: 9,
plugins: {
es7: true,
stage3: true
}
}
}],
jsx: [{
lexer: 'JsxLexer',
attr: 'i18nKey',
acorn: {
sourceType: 'module',
ecmaVersion: 9,
plugins: {
es7: true,
stage3: true,
jsx: true
}
}
}]
]
Events
The transform emits a reading
event for each file it parses:
.pipe( i18next().on('reading', (file) => {}) )
The transform emits a error:json
event if the JSON.parse on json files fail:
.pipe( i18next().on('error:json', (path, error) => {}) )
The transform emits a warning:variable
event if the file has a key that contains a variable:
.pipe( i18next().on('warning:variable', (path, key) => {}) )
Contribute
Any contribution is welcome. Please read the guidelines first.
Thanks a lot to all the previous contributors.
If you use this package and like it, supporting me on Patreon is another great way to contribute!