i18next-parser
Advanced tools
Comparing version
@@ -39,3 +39,3 @@ #!/usr/bin/env node | ||
var output = config.output || program.output | ||
config.output = config.output || program.output | ||
@@ -74,3 +74,3 @@ var args = program.args || [] | ||
if (!output) { | ||
if (!config.output) { | ||
console.log(' [error] '.red + 'an `output` is required via --config or --output option') | ||
@@ -92,3 +92,3 @@ program.help() | ||
console.log(' Input: '.yellow + args.join(', ')) | ||
console.log(' Output: '.yellow + output) | ||
console.log(' Output: '.yellow + config.output) | ||
if (!program.silent) { | ||
@@ -95,0 +95,0 @@ console.log() |
@@ -6,2 +6,3 @@ 'use strict';Object.defineProperty(exports, "__esModule", { value: true });var _extends = Object.assign || function (target) {for (var i = 1; i < arguments.length; i++) {var source = arguments[i];for (var key in source) {if (Object.prototype.hasOwnProperty.call(source, key)) {target[key] = source[key];}}}return target;};var _createClass = function () {function defineProperties(target, props) {for (var i = 0; i < props.length; i++) {var descriptor = props[i];descriptor.enumerable = descriptor.enumerable || false;descriptor.configurable = true;if ("value" in descriptor) descriptor.writable = true;Object.defineProperty(target, descriptor.key, descriptor);}}return function (Constructor, protoProps, staticProps) {if (protoProps) defineProperties(Constructor.prototype, protoProps);if (staticProps) defineProperties(Constructor, staticProps);return Constructor;};}();var _events = require('events');var _events2 = _interopRequireDefault(_events); | ||
var _jsxLexer = require('./lexers/jsx-lexer');var _jsxLexer2 = _interopRequireDefault(_jsxLexer); | ||
var _typescriptLexer = require('./lexers/typescript-lexer');var _typescriptLexer2 = _interopRequireDefault(_typescriptLexer); | ||
var _path = require('path');var _path2 = _interopRequireDefault(_path);function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };}function _classCallCheck(instance, Constructor) {if (!(instance instanceof Constructor)) {throw new TypeError("Cannot call a class as a function");}}function _possibleConstructorReturn(self, call) {if (!self) {throw new ReferenceError("this hasn't been initialised - super() hasn't been called");}return call && (typeof call === "object" || typeof call === "function") ? call : self;}function _inherits(subClass, superClass) {if (typeof superClass !== "function" && superClass !== null) {throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);}subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } });if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;} | ||
@@ -20,2 +21,5 @@ | ||
ts: ['TypescriptLexer'], | ||
tsx: ['TypescriptLexer'], | ||
default: ['JavascriptLexer'] }; | ||
@@ -28,3 +32,4 @@ | ||
JavascriptLexer: _javascriptLexer2.default, | ||
JsxLexer: _jsxLexer2.default };var | ||
JsxLexer: _jsxLexer2.default, | ||
TypescriptLexer: _typescriptLexer2.default };var | ||
@@ -31,0 +36,0 @@ |
@@ -5,3 +5,3 @@ { | ||
"name": "i18next-parser", | ||
"version": "1.0.0-beta27", | ||
"version": "1.0.0-beta28", | ||
"license": "MIT", | ||
@@ -40,2 +40,3 @@ "main": "dist/index.js", | ||
}, | ||
"optionalDependencies": {}, | ||
"engines": { | ||
@@ -55,3 +56,4 @@ "node": ">=0.10.22" | ||
"gulp": "^4.0.0", | ||
"mocha": "^5.0.0" | ||
"mocha": "^5.0.0", | ||
"typescript": "^3.0.3" | ||
}, | ||
@@ -58,0 +60,0 @@ "keywords": [ |
@@ -5,3 +5,3 @@ # i18next Parser [](https://travis-ci.org/i18next/i18next-parser) | ||
When translating an application, maintaining the translation catalog by hand is painful. This package parses your code and automates this process. | ||
When translating an application, maintaining the translation catalog by hand is painful. This package parses your code and automates this process. | ||
@@ -19,3 +19,3 @@ Finally, if you want to make this process even less painful, I invite you to check [Locize](https://locize.com/). They are a sponsor of this project. Actually, if you use this package and like it, supporting me on [Patreon](https://www.patreon.com/karelledru) would mean a great deal! | ||
- Choose your weapon: A CLI, a standalone parser or a stream transform | ||
- 4 built in lexers: Javascript, JSX, HTML and Handlebars | ||
- 5 built in lexers: Javascript, JSX, HTML, Handlebars, and TypeScript+tsx | ||
- Creates one catalog file per locale and per namespace | ||
@@ -48,2 +48,4 @@ - Backs up the old keys your code doesn't use anymore in `namespace_old.json` catalog | ||
**IMPORTANT NOTE**: If you pass the globs as CLI argument, they must be relative to where you run the command (aka relative to `process.cwd()`). If you pass the globs via the `input` option of the config file, they must be relative to the config file. | ||
- **-c, --config <path>**: Path to the output directory (default: locales/$LOCALE/$NAMESPACE.json) | ||
@@ -88,3 +90,3 @@ - **-o, --output <path>**: Where to write the locale files. | ||
[Broccoli.js](https://github.com/broccolijs/broccoli) defines itself as a fast, reliable asset pipeline, supporting constant-time rebuilds and compact build definitions. | ||
[Broccoli.js](https://github.com/broccolijs/broccoli) defines itself as a fast, reliable asset pipeline, supporting constant-time rebuilds and compact build definitions. | ||
@@ -119,22 +121,22 @@ ```javascript | ||
contextSeparator: '_', | ||
// Key separator used in your translation keys | ||
// Key separator used in your translation keys | ||
createOldCatalogs: true, | ||
// Save the \_old files | ||
// Save the \_old files | ||
defaultNamespace: 'translation', | ||
// Default namespace used in your i18next config | ||
// Default namespace used in your i18next config | ||
defaultValue: '', | ||
// Default value to give to empty keys | ||
// Default value to give to empty keys | ||
indentation: 2, | ||
// Indentation of the catalog files | ||
// Indentation of the catalog files | ||
keepRemoved: false, | ||
// Keep keys from the catalog that are no longer in code | ||
// Keep keys from the catalog that are no longer in code | ||
keySeparator: '.', | ||
// Key separator used in your translation keys | ||
// If you want to use plain english keys, separators such as `.` and `:` will conflict. You might want to set `keySeparator: false` and `namespaceSeparator: false`. That way, `t('Status: Loading...')` will not think that there are a namespace and three separator dots for instance. | ||
// If you want to use plain english keys, separators such as `.` and `:` will conflict. You might want to set `keySeparator: false` and `namespaceSeparator: false`. That way, `t('Status: Loading...')` will not think that there are a namespace and three separator dots for instance. | ||
@@ -153,2 +155,5 @@ // see below for more details | ||
ts: ['TypescriptLexer'], | ||
tsx: ['TypescriptLexer'], | ||
default: ['JavascriptLexer'] | ||
@@ -161,6 +166,6 @@ }, | ||
locales: ['en', 'fr'], | ||
// An array of the locales in your applications | ||
// An array of the locales in your applications | ||
namespaceSeparator: ':', | ||
// Namespace separator used in your translation keys | ||
// Namespace separator used in your translation keys | ||
// If you want to use plain english keys, separators such as `.` and `:` will conflict. You might want to set `keySeparator: false` and `namespaceSeparator: false`. That way, `t('Status: Loading...')` will not think that there are a namespace and three separator dots for instance. | ||
@@ -170,6 +175,7 @@ | ||
// Supports $LOCALE and $NAMESPACE injection | ||
// Where to write the locale files relative to the base | ||
// Where to write the locale files relative to process.cwd() | ||
input: undefined, | ||
// An array of globs that describe where to look for source files | ||
// relative to the location of the configuration file | ||
@@ -205,3 +211,3 @@ reactNamespace: false, | ||
lexer: 'HtmlLexer', | ||
attr: 'data-i18n' // Attribute for the keys | ||
attr: 'data-i18n' // Attribute for the keys | ||
optionAttr: 'data-i18n-options' // Attribute for the options | ||
@@ -217,3 +223,3 @@ }] | ||
acorn: { | ||
sourceType: 'module', | ||
sourceType: 'module', | ||
ecmaVersion: 9, // forward compatibility | ||
@@ -235,3 +241,3 @@ plugins: { | ||
acorn: { | ||
sourceType: 'module', | ||
sourceType: 'module', | ||
ecmaVersion: 9, // forward compatibility | ||
@@ -244,2 +250,28 @@ plugins: { | ||
} | ||
}], | ||
// TypescriptLexer default config (ts/x) | ||
// TypescriptLexer can take all the options of the JsxLexer in addition to | ||
// optional tsOptions to pass as compilerOptions to TypeScript. | ||
ts: [{ | ||
lexer: 'TypescriptLexer', | ||
attr: 'i18nKey', // Attribute for the keys | ||
// compiler options (https://www.typescriptlang.org/docs/handbook/compiler-options.html) | ||
// note that jsx MUST be set to Preserve, or your strings will not be extracted. | ||
tsOptions: { | ||
jsx: 'Preserve', | ||
target: 'esnext' | ||
}, | ||
// acorn config (for more information on the acorn options, see here: https://github.com/acornjs/acorn#main-parser) | ||
acorn: { | ||
sourceType: 'module', | ||
ecmaVersion: 9, // forward compatibility | ||
plugins: { | ||
es7: true, // some es7 parsing that's not yet in acorn (decorators) | ||
stage3: true, // load some stage3 configs not yet in a version | ||
jsx: true // always defaults to true in .jsx files | ||
} | ||
} | ||
}] | ||
@@ -246,0 +278,0 @@ ] |
@@ -6,2 +6,3 @@ import EventEmitter from 'events' | ||
import JsxLexer from './lexers/jsx-lexer' | ||
import TypescriptLexer from './lexers/typescript-lexer' | ||
import path from 'path' | ||
@@ -20,2 +21,5 @@ | ||
ts: ['TypescriptLexer'], | ||
tsx: ['TypescriptLexer'], | ||
default: ['JavascriptLexer'] | ||
@@ -28,3 +32,4 @@ } | ||
JavascriptLexer, | ||
JsxLexer | ||
JsxLexer, | ||
TypescriptLexer | ||
} | ||
@@ -31,0 +36,0 @@ |
@@ -213,2 +213,40 @@ import { assert } from 'chai' | ||
it('parses typescript files', (done) => { | ||
let result | ||
const i18nextParser = new i18nTransform() | ||
const fakeFile = new Vinyl({ | ||
contents: fs.readFileSync( | ||
path.resolve(__dirname, 'templating/typescript.tsx') | ||
), | ||
path: 'typescript.tsx' | ||
}) | ||
const expected = { | ||
first: '', | ||
second: '', | ||
third: { | ||
first: 'Hello <1><0>{{name}}</0></1>, you have <3>{{count}}</3> unread message. <5>Go to messages</5>.', | ||
second: ' <1>Hello,</1> this shouldn\'t be trimmed.', | ||
third: '<0>Hello,</0>this should be trimmed.<2> and this shoudln\'t</2>' | ||
}, | ||
fourth: '', | ||
fifth: '', | ||
bar: '', | ||
foo: '', | ||
"This should be part of the value and the key": "This should be part of the value and the key", | ||
"don't split <1>{{on}}</1>": "don't split <1>{{on}}</1>" | ||
} | ||
i18nextParser.on('data', file => { | ||
if (file.relative.endsWith(enLibraryPath)) { | ||
result = JSON.parse(file.contents) | ||
} | ||
}) | ||
i18nextParser.on('end', () => { | ||
assert.deepEqual(result, expected) | ||
done() | ||
}) | ||
i18nextParser.end(fakeFile) | ||
}) | ||
it('creates one file per namespace and per locale', (done) => { | ||
@@ -215,0 +253,0 @@ let results = [] |
474262
2.97%78
4%4028
7.38%308
11.59%12
9.09%9
28.57%