i18next-parser
Advanced tools
Comparing version 1.0.0-beta1 to 1.0.0-beta10
# Changelog | ||
## 1.0.0-beta10 - latest | ||
- See [release](https://github.com/i18next/i18next-parser/releases/tag/1.0.0-beta10) | ||
## 1.0.0-beta9 | ||
- See [release](https://github.com/i18next/i18next-parser/releases/tag/1.0.0-beta9) | ||
## 1.0.0-beta8 | ||
- See [release](https://github.com/i18next/i18next-parser/releases/tag/1.0.0-beta8) | ||
## 1.0.0-beta7 | ||
- See [release](https://github.com/i18next/i18next-parser/releases/tag/1.0.0-beta7) | ||
## 1.0.0-beta2 | ||
- See [release](https://github.com/i18next/i18next-parser/releases/tag/1.0.0-beta2) | ||
## 1.0.0-beta1 | ||
- See [release](https://github.com/i18next/i18next-parser/releases/tag/1.0.0-beta1) | ||
## 0.13.0 | ||
## 0.13.0 - latest | ||
- Support `defaultValue` option along the translation key (#68) | ||
@@ -10,0 +30,0 @@ |
@@ -1,8 +0,11 @@ | ||
'use strict';Object.defineProperty(exports, "__esModule", { value: true });exports.populateHash = exports.mergeHashes = exports.dotPathToHash = undefined;var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {return typeof obj;} : function (obj) {return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;};var _lodash = require('lodash');var _lodash2 = _interopRequireDefault(_lodash);function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };} | ||
'use strict';Object.defineProperty(exports, "__esModule", { value: true });exports.ParsingError = exports.populateHash = exports.mergeHashes = exports.dotPathToHash = undefined;var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {return typeof obj;} : function (obj) {return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;};var _lodash = require('lodash');var _lodash2 = _interopRequireDefault(_lodash);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;} | ||
// Takes a `path` of the form 'foo.bar' and | ||
// turn it into a hash {foo: {bar: ""}}. | ||
// The generated hash can be attached to an | ||
// optional `hash`. | ||
function dotPathToHash(path) {var separator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '.';var value = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';var target = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; | ||
// Turn an entry for the Parser and turn in into a hash, | ||
// turning the key path 'foo.bar' into an hash {foo: {bar: ""}} | ||
// The generated hash can be attached to an optional `target`. | ||
function dotPathToHash(entry) {var target = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; | ||
var path = entry.key; | ||
var separator = options.separator || '.'; | ||
var value = entry.defaultValue || options.value || ''; | ||
if (path.endsWith(separator)) { | ||
@@ -16,2 +19,5 @@ path = path.slice(0, -separator.length); | ||
segments.reduce(function (hash, segment, index) { | ||
if (!segment) { | ||
return hash; | ||
} else | ||
if (index === segments.length - 1) { | ||
@@ -101,8 +107,15 @@ hash[segment] = value; | ||
return target; | ||
}exports. | ||
}var | ||
ParsingError = function (_Error) {_inherits(ParsingError, _Error); | ||
function ParsingError(message) {_classCallCheck(this, ParsingError);var _this = _possibleConstructorReturn(this, (ParsingError.__proto__ || Object.getPrototypeOf(ParsingError)).call(this, | ||
message)); | ||
_this.name = 'ParsingError';return _this; | ||
}return ParsingError;}(Error);exports. | ||
dotPathToHash = dotPathToHash;exports. | ||
mergeHashes = mergeHashes;exports. | ||
populateHash = populateHash; | ||
populateHash = populateHash;exports. | ||
ParsingError = ParsingError; |
@@ -9,3 +9,4 @@ '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 _helpers = require('./helpers'); | ||
var _vinyl = require('vinyl');var _vinyl2 = _interopRequireDefault(_vinyl); | ||
var _yamljs = require('yamljs');var _yamljs2 = _interopRequireDefault(_yamljs);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;}var | ||
var _yamljs = require('yamljs');var _yamljs2 = _interopRequireDefault(_yamljs); | ||
var _baseLexer = require('./lexers/base-lexer');var _baseLexer2 = _interopRequireDefault(_baseLexer);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;}var | ||
@@ -19,3 +20,3 @@ i18nTransform = function (_Transform) {_inherits(i18nTransform, _Transform); | ||
contextSeparator: '_', | ||
createOldLibraries: true, | ||
createOldCatalogs: true, | ||
defaultNamespace: 'translation', | ||
@@ -33,2 +34,3 @@ defaultValue: '', | ||
output: 'locales', | ||
reactNamespace: false, | ||
sort: false }; | ||
@@ -38,5 +40,11 @@ | ||
_this.options = _extends({}, _this.defaults, options); | ||
if (_this.options.keySeparator === false) { | ||
_this.options.keySeparator = '__!NO_KEY_SEPARATOR!__'; | ||
} | ||
if (_this.options.namespaceSeparator === false) { | ||
_this.options.namespaceSeparator = '__!NO_NAMESPACE_SEPARATOR!__'; | ||
} | ||
_this.entries = []; | ||
_this.parser = new _parser2.default(_this.options.lexers); | ||
_this.parser = new _parser2.default(_this.options); | ||
_this.parser.on('error', function (error) {return _this.emit('error', error);}); | ||
@@ -52,3 +60,3 @@ _this.parser.on('warning', function (warning) {return _this.emit('warning', warning);}); | ||
if (file.isBuffer()) { | ||
content = file.contents; | ||
content = file.contents.toString('utf8'); | ||
} else | ||
@@ -61,4 +69,4 @@ { | ||
var extenstion = _path2.default.extname(file.path).substring(1); | ||
var entries = this.parser.parse(content, extenstion); | ||
var extension = _path2.default.extname(file.path).substring(1); | ||
var entries = this.parser.parse(content, extension); | ||
@@ -72,5 +80,6 @@ entries.forEach(function (entry) { | ||
} else | ||
{ | ||
entry.namespace = _this2.options.defaultNamespace; | ||
if (extension === 'jsx' || _this2.options.reactNamespace) { | ||
entry.namespace = _this2.grabReactNamespace(content); | ||
} | ||
entry.namespace = entry.namespace || _this2.options.defaultNamespace; | ||
@@ -100,7 +109,9 @@ key = parts.join(_this2.options.namespaceSeparator); | ||
catalog = (0, _helpers.dotPathToHash)( | ||
entry.key, | ||
_this3.options.keySeparator, | ||
entry.defaultValue || _this3.options.defaultValue, | ||
catalog); | ||
entry, | ||
catalog, | ||
{ | ||
separator: _this3.options.keySeparator, | ||
value: _this3.options.defaultValue }); | ||
}); | ||
@@ -146,3 +157,3 @@ | ||
_this3.pushFile(namespacePath, newCatalog); | ||
if (_this3.options.createOldLibraries) { | ||
if (_this3.options.createOldCatalogs) { | ||
_this3.pushFile(namespaceOldPath, oldCatalog); | ||
@@ -215,2 +226,12 @@ } | ||
this.push(file); | ||
} }, { key: 'grabReactNamespace', value: function grabReactNamespace( | ||
content) { | ||
var reactTranslateRegex = new RegExp( | ||
'translate\\((?:\\s*\\[?\\s*)(' + _baseLexer2.default.stringPattern + ')'); | ||
var translateMatches = content.match(reactTranslateRegex); | ||
if (translateMatches) { | ||
return translateMatches[1].slice(1, -1); | ||
} | ||
} }]);return i18nTransform;}(_stream.Transform);exports.default = i18nTransform; |
@@ -18,3 +18,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 _baseLexer = require('./base-lexer');var _baseLexer2 = _interopRequireDefault(_baseLexer);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;}var | ||
var regex = new RegExp( | ||
'<([A-Z][A-Z0-9]*)([^>]*\\s' + this.attr + '[^>]*)>(?:(.*?)<\\/\\1>)?', | ||
'<([A-Z][A-Z0-9]*)([^>]*\\s' + this.attr + '[^>]*)>(?:((?:\\s|.)*?)<\\/\\1>)?', | ||
'gi');var _loop = function _loop() { | ||
@@ -21,0 +21,0 @@ |
@@ -5,2 +5,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 _javascriptLexer = require('./lexers/javascript-lexer');var _javascriptLexer2 = _interopRequireDefault(_javascriptLexer); | ||
var _jsxLexer = require('./lexers/jsx-lexer');var _jsxLexer2 = _interopRequireDefault(_jsxLexer); | ||
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;} | ||
@@ -16,2 +17,3 @@ | ||
js: ['JavascriptLexer'], | ||
jsx: ['JavascriptLexer', 'JsxLexer'], | ||
mjs: ['JavascriptLexer'], | ||
@@ -25,3 +27,4 @@ | ||
HTMLLexer: _htmlLexer2.default, | ||
JavascriptLexer: _javascriptLexer2.default };var | ||
JavascriptLexer: _javascriptLexer2.default, | ||
JsxLexer: _jsxLexer2.default };var | ||
@@ -32,3 +35,9 @@ | ||
options)); | ||
_this.lexers = _extends({}, lexers, options);return _this; | ||
_this.options = options; | ||
if (options.reactNamespace) { | ||
lexers.js = lexers.jsx; | ||
} | ||
_this.lexers = _extends({}, lexers, options.lexers);return _this; | ||
}_createClass(Parser, [{ key: 'parse', value: function parse( | ||
@@ -35,0 +44,0 @@ |
@@ -38,3 +38,3 @@ # Contribute | ||
``` | ||
mocha --require babel-register --require babel-polyfill test/**/*.js | ||
yarn test | ||
``` | ||
@@ -58,1 +58,9 @@ | ||
I will not maintain the old version but will welcome bug fixes as PRs. | ||
## Deploy | ||
- `yarn watch` | ||
- update `package.json` version | ||
- create commit and add version tag | ||
- `npm pulish --tag next` (skip next tag if not in beta) | ||
- create a github release |
@@ -5,5 +5,5 @@ { | ||
"name": "i18next-parser", | ||
"version": "1.0.0-beta1", | ||
"version": "1.0.0-beta10", | ||
"license": "MIT", | ||
"main": "src/index.js", | ||
"main": "dist/index.js", | ||
"bin": { | ||
@@ -13,4 +13,4 @@ "i18next": "./bin/cli.js" | ||
"scripts": { | ||
"test": "mocha --require babel-register --require babel-polyfill test/**/*.test.js", | ||
"watch": "babel src -d dist -w" | ||
"test": "mocha --require babel-register --require babel-polyfill 'test/**/*.test.js'", | ||
"watch": "./node_modules/babel-cli/bin/babel.js src -d dist -w" | ||
}, | ||
@@ -22,2 +22,3 @@ "repository": { | ||
"dependencies": { | ||
"acorn-jsx": "^4.1.1", | ||
"colors": "~1.2.0-rc0", | ||
@@ -24,0 +25,0 @@ "commander": "~2.9.0", |
@@ -22,5 +22,5 @@ # i18next Parser [![Build Status](https://travis-ci.org/i18next/i18next-parser.svg?branch=master)](https://travis-ci.org/i18next/i18next-parser) | ||
## `1.x` | ||
## DISCLAMER: `1.0.0-beta` | ||
`1.x` is currently in beta. It is a deep rewrite of this package that solves many issues, the main one being that it was slowly becoming unmaintainable. The [migration](docs/migration.md) contains all the breaking changes. If you rely on a `0.x.x` version, you can still find the old documentation on its dedicated [branch](https://github.com/i18next/i18next-parser/tree/0.x.x). | ||
`1.x` is currently in beta. You can follow the pre-releases [here](https://github.com/i18next/i18next-parser/releases). It is a deep rewrite of this package that solves many issues, the main one being that it was slowly becoming unmaintainable. The [migration](docs/migration.md) 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](https://github.com/i18next/i18next-parser/tree/0.x.x). | ||
@@ -35,4 +35,4 @@ | ||
``` | ||
yarn global add i18next-parser | ||
npm install -g i18next-parser | ||
yarn global add i18next-parser@next | ||
npm install -g i18next-parser@next | ||
i18next 'app/**/*.{js,hbs}' 'lib/**/*.{js,hbs}' [-oc] | ||
@@ -52,3 +52,3 @@ ``` | ||
``` | ||
yarn add -D i18next-parser | ||
yarn add -D i18next-parser@next | ||
npm install --save-dev i18next-parser | ||
@@ -77,23 +77,25 @@ ``` | ||
Option | Description | Default | ||
Option | Description | Default | ||
---------------------- | ----------------------------------------------------- | --- | ||
**contextSeparator** | Key separator used in your translation keys | `_` | ||
**createOldLibraries** | Save the \_old files | `true` | ||
**defaultNamespace** | Default namespace used in your i18next config | `translation` | ||
**defaultValue** | Default value to give to empty keys | `''` | ||
**extension** | Edit the extension of the locale files | `.json` | ||
**filename** | Edit the filename of the locale files | `'$NAMESPACE'` | ||
**indentation** | Indentation of the catalog files | `2` | ||
**keepRemoved** | Keep keys from the catalog that are no longer in code | `false` | ||
**keySeparator** | Key separator used in your translation keys | `.` | ||
**lexers** | See below for details | `{}` | ||
**lineEnding** | Control the line ending. See options at [eol](https://github.com/ryanve/eol) | `auto` | ||
**locales** | An array of the locales in your applications | `['en','fr']` | ||
**namespaceSeparator** | Namespace separator used in your translation keys | `:` | ||
**output** | Where to write the locale files relative to the base | `locales` | ||
**sort** | Whether or not to sort the catalog | `false` | ||
**contextSeparator** | Key separator used in your translation keys | `_` | ||
**createOldCatalogs** | Save the \_old files | `true` | ||
**defaultNamespace** | Default namespace used in your i18next config | `translation` | ||
**defaultValue** | Default value to give to empty keys | `''` | ||
**extension** <sup>1<sup>| Extenstion of the catalogs | `.json` | ||
**filename** <sup>1<sup>| Filename of the catalogs | `'$NAMESPACE'` | ||
**indentation** | Indentation of the catalog files | `2` | ||
**keepRemoved** | Keep keys from the catalog that are no longer in code | `false` | ||
**keySeparator** <sup>2<sup>| Key separator used in your translation keys | `.` | ||
**lexers** | See below for details | `{}` | ||
**lineEnding** | Control the line ending. See options at [eol](https://github.com/ryanve/eol) | `auto` | ||
**locales** | An array of the locales in your applications | `['en','fr']` | ||
**namespaceSeparator** <sup>2<sup>| Namespace separator used in your translation keys | `:` | ||
**output** | Where to write the locale files relative to the base | `locales` | ||
**reactNamespace** <sup>3<sup>| For react file, extract the [defaultNamespace](https://react.i18next.com/components/translate-hoc.html) | `false` | ||
**sort** | Whether or not to sort the catalog | `false` | ||
### Catalog filenames | ||
1. Both `filename` and `extension` options support injection of `$LOCALE` and `$NAMESPACE` variables. The file output is JSON by default, if you want YAML, the `extension` must end with `yml`. | ||
2. 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. | ||
3. If the file being parsed has a `.jsx` extension, this option is ignored and the namespace is being extracted. | ||
Both `filename` and `extension` options support injection of `$LOCALE` and `$NAMESPACE` variables. | ||
@@ -104,3 +106,3 @@ ### Lexers | ||
``` | ||
```js | ||
{ | ||
@@ -115,2 +117,3 @@ lexers: { | ||
js: ['JavascriptLexer'], | ||
jsx: ['JavascriptLexer', 'JsxLexer'], | ||
mjs: ['JavascriptLexer'], | ||
@@ -125,3 +128,3 @@ | ||
``` | ||
```js | ||
{ | ||
@@ -135,3 +138,3 @@ lexers: { | ||
], | ||
... | ||
// ... | ||
} | ||
@@ -160,4 +163,10 @@ } | ||
**`JsxLexer` options** | ||
Option | Description | Default | ||
------------- | ---------------------- | ------- | ||
**attr** | Attribute for the keys | `i18nKey` | ||
## Events | ||
@@ -164,0 +173,0 @@ |
import _ from 'lodash' | ||
// Takes a `path` of the form 'foo.bar' and | ||
// turn it into a hash {foo: {bar: ""}}. | ||
// The generated hash can be attached to an | ||
// optional `hash`. | ||
function dotPathToHash(path, separator = '.', value = '', target = {}) { | ||
// Turn an entry for the Parser and turn in into a hash, | ||
// turning the key path 'foo.bar' into an hash {foo: {bar: ""}} | ||
// The generated hash can be attached to an optional `target`. | ||
function dotPathToHash(entry, target = {}, options = {}) { | ||
let path = entry.key | ||
const separator = options.separator || '.' | ||
const value = entry.defaultValue || options.value || '' | ||
if (path.endsWith(separator)) { | ||
@@ -16,3 +19,6 @@ path = path.slice(0, -separator.length) | ||
segments.reduce((hash, segment, index) => { | ||
if (index === segments.length - 1) { | ||
if (!segment) { | ||
return hash | ||
} | ||
else if (index === segments.length - 1) { | ||
hash[segment] = value | ||
@@ -103,2 +109,8 @@ } | ||
class ParsingError extends Error { | ||
constructor(message) { | ||
super(message); | ||
this.name = 'ParsingError'; | ||
} | ||
} | ||
@@ -108,3 +120,4 @@ export { | ||
mergeHashes, | ||
populateHash | ||
populateHash, | ||
ParsingError | ||
} |
@@ -10,2 +10,3 @@ import { dotPathToHash, mergeHashes, populateHash } from './helpers' | ||
import YAML from 'yamljs' | ||
import BaseLexer from './lexers/base-lexer'; | ||
@@ -19,3 +20,3 @@ export default class i18nTransform extends Transform { | ||
contextSeparator: '_', | ||
createOldLibraries: true, | ||
createOldCatalogs: true, | ||
defaultNamespace: 'translation', | ||
@@ -33,2 +34,3 @@ defaultValue: '', | ||
output: 'locales', | ||
reactNamespace: false, | ||
sort: false | ||
@@ -38,5 +40,11 @@ } | ||
this.options = { ...this.defaults, ...options } | ||
if (this.options.keySeparator === false) { | ||
this.options.keySeparator = '__!NO_KEY_SEPARATOR!__' | ||
} | ||
if (this.options.namespaceSeparator === false) { | ||
this.options.namespaceSeparator = '__!NO_NAMESPACE_SEPARATOR!__' | ||
} | ||
this.entries = [] | ||
this.parser = new Parser(this.options.lexers) | ||
this.parser = new Parser(this.options) | ||
this.parser.on('error', error => this.emit('error', error)) | ||
@@ -52,3 +60,3 @@ this.parser.on('warning', warning => this.emit('warning', warning)) | ||
if (file.isBuffer()) { | ||
content = file.contents | ||
content = file.contents.toString('utf8') | ||
} | ||
@@ -61,4 +69,4 @@ else { | ||
const extenstion = path.extname(file.path).substring(1) | ||
const entries = this.parser.parse(content, extenstion) | ||
const extension = path.extname(file.path).substring(1) | ||
const entries = this.parser.parse(content, extension) | ||
@@ -72,5 +80,6 @@ entries.forEach(entry => { | ||
} | ||
else { | ||
entry.namespace = this.options.defaultNamespace | ||
else if (extension === 'jsx' || this.options.reactNamespace) { | ||
entry.namespace = this.grabReactNamespace(content) | ||
} | ||
entry.namespace = entry.namespace || this.options.defaultNamespace | ||
@@ -100,6 +109,8 @@ key = parts.join(this.options.namespaceSeparator) | ||
catalog = dotPathToHash( | ||
entry.key, | ||
this.options.keySeparator, | ||
entry.defaultValue || this.options.defaultValue, | ||
catalog | ||
entry, | ||
catalog, | ||
{ | ||
separator: this.options.keySeparator, | ||
value: this.options.defaultValue | ||
} | ||
) | ||
@@ -146,3 +157,3 @@ }) | ||
this.pushFile(namespacePath, newCatalog) | ||
if (this.options.createOldLibraries) { | ||
if (this.options.createOldCatalogs) { | ||
this.pushFile(namespaceOldPath, oldCatalog) | ||
@@ -216,2 +227,12 @@ } | ||
} | ||
grabReactNamespace(content) { | ||
const reactTranslateRegex = new RegExp( | ||
'translate\\((?:\\s*\\[?\\s*)(' + BaseLexer.stringPattern + ')' | ||
) | ||
const translateMatches = content.match(reactTranslateRegex) | ||
if (translateMatches) { | ||
return translateMatches[1].slice(1, -1) | ||
} | ||
} | ||
} |
@@ -18,3 +18,3 @@ import BaseLexer from './base-lexer' | ||
const regex = new RegExp( | ||
'<([A-Z][A-Z0-9]*)([^>]*\\s' + this.attr + '[^>]*)>(?:(.*?)<\\/\\1>)?', | ||
'<([A-Z][A-Z0-9]*)([^>]*\\s' + this.attr + '[^>]*)>(?:((?:\\s|.)*?)<\\/\\1>)?', | ||
'gi' | ||
@@ -21,0 +21,0 @@ ) |
@@ -5,2 +5,3 @@ import EventEmitter from 'events' | ||
import JavascriptLexer from './lexers/javascript-lexer' | ||
import JsxLexer from './lexers/jsx-lexer' | ||
import path from 'path' | ||
@@ -16,2 +17,3 @@ | ||
js: ['JavascriptLexer'], | ||
jsx: ['JavascriptLexer', 'JsxLexer'], | ||
mjs: ['JavascriptLexer'], | ||
@@ -25,3 +27,4 @@ | ||
HTMLLexer, | ||
JavascriptLexer | ||
JavascriptLexer, | ||
JsxLexer | ||
} | ||
@@ -32,3 +35,9 @@ | ||
super(options) | ||
this.lexers = { ...lexers, ...options } | ||
this.options = options | ||
if (options.reactNamespace) { | ||
lexers.js = lexers.jsx | ||
} | ||
this.lexers = { ...lexers, ...options.lexers } | ||
} | ||
@@ -35,0 +44,0 @@ |
import { assert } from 'chai' | ||
import { dotPathToHash } from '../../src/helpers' | ||
describe('dotPathToHash helper function', function () { | ||
it('creates an object from a string path', function (done) { | ||
const res = dotPathToHash('one') | ||
describe('dotPathToHash helper function', () => { | ||
it('creates an object from a string path', (done) => { | ||
const res = dotPathToHash({ key: 'one' }) | ||
assert.deepEqual(res, { one: '' }) | ||
@@ -11,4 +11,8 @@ done() | ||
it('ignores trailing separator', function (done) { | ||
const res = dotPathToHash('one..', '..') | ||
it('ignores trailing separator', (done) => { | ||
const res = dotPathToHash( | ||
{ key: 'one.' }, | ||
{}, | ||
{ separator: '.' } | ||
) | ||
assert.deepEqual(res, { one: '' }) | ||
@@ -18,4 +22,6 @@ done() | ||
it('ignores duplicated separator', function (done) { | ||
const res = dotPathToHash('one..two', '..') | ||
it('ignores duplicated separator', (done) => { | ||
const res = dotPathToHash( | ||
{ key: 'one..two' } | ||
) | ||
assert.deepEqual(res, { one: { two: '' } }) | ||
@@ -25,10 +31,17 @@ done() | ||
it('use provided default value', function (done) { | ||
const res = dotPathToHash('one', null, 'myDefaultValue') | ||
assert.deepEqual(res, { one: 'myDefaultValue' }) | ||
it('handles a target hash', (done) => { | ||
const res = dotPathToHash( | ||
{ key: 'one.two.three' }, | ||
{ one: { twenty: '' } } | ||
) | ||
assert.deepEqual(res, { one: { two: { three: '' }, twenty: '' } }) | ||
done() | ||
}) | ||
it('use provided default value', function (done) { | ||
const res = dotPathToHash('one', null, 'myDefaultValue') | ||
it('handles a `defaultValue` option', (done) => { | ||
const res = dotPathToHash( | ||
{ key: 'one' }, | ||
{}, | ||
{ value: 'myDefaultValue' } | ||
) | ||
assert.deepEqual(res, { one: 'myDefaultValue' }) | ||
@@ -38,10 +51,8 @@ done() | ||
it('handles a target hash', function (done) { | ||
const res = dotPathToHash('one.two.three', '.', '', { one: { twenty: '' } }) | ||
assert.deepEqual(res, { one: { two: { three: '' }, twenty: '' } }) | ||
done() | ||
}) | ||
it('handles a different separator', function (done) { | ||
const res = dotPathToHash('one_two_three.', '_') | ||
it('handles a `separator` option', (done) => { | ||
const res = dotPathToHash( | ||
{ key: 'one_two_three.' }, | ||
{}, | ||
{ separator: '_' } | ||
) | ||
assert.deepEqual(res, { one: { two: { 'three.': '' } } }) | ||
@@ -48,0 +59,0 @@ done() |
import { assert } from 'chai' | ||
import { mergeHashes } from '../../src/helpers' | ||
describe('mergeHashes helper function', function () { | ||
it('replaces empty `target` keys with `source`', function (done) { | ||
describe('mergeHashes helper function', () => { | ||
it('replaces empty `target` keys with `source`', (done) => { | ||
const source = { key1: 'value1' } | ||
@@ -15,3 +15,3 @@ const target = { key1: '' } | ||
it('does not replaces empty `target` keys with `source` if it is a hash', function (done) { | ||
it('does not replaces empty `target` keys with `source` if it is a hash', (done) => { | ||
const source = { key1: { key11: 'value1'} } | ||
@@ -24,5 +24,5 @@ const target = { key1: '' } | ||
done() | ||
}) | ||
}) | ||
it('keeps `target` keys not in `source`', function (done) { | ||
it('keeps `target` keys not in `source`', (done) => { | ||
const source = { key1: 'value1' } | ||
@@ -37,3 +37,3 @@ const target = { key1: '', key2: '' } | ||
it('stores into `old` the keys from `source` that are not in `target`', function (done) { | ||
it('stores into `old` the keys from `source` that are not in `target`', (done) => { | ||
const source = { key1: 'value1', key2: 'value2' } | ||
@@ -48,3 +48,3 @@ const target = { key1: '' } | ||
it('copies `source` keys to `target` regardless of presence when keepRemoved is enabled', function (done) { | ||
it('copies `source` keys to `target` regardless of presence when keepRemoved is enabled', (done) => { | ||
const source = { key1: 'value1', key2: 'value2' } | ||
@@ -59,3 +59,3 @@ const target = { key1: '', key3: '' } | ||
it('restores plural keys when the singular one exists', function (done) { | ||
it('restores plural keys when the singular one exists', (done) => { | ||
const source = { key1: '', key1_plural: 'value1' } | ||
@@ -70,3 +70,3 @@ const target = { key1: '' } | ||
it('does not restores plural keys when the singular one does not', function (done) { | ||
it('does not restores plural keys when the singular one does not', (done) => { | ||
const source = { key1: '', key1_plural: 'value1' } | ||
@@ -81,3 +81,3 @@ const target = { key2: '' } | ||
it('restores context keys when the singular one exists', function (done) { | ||
it('restores context keys when the singular one exists', (done) => { | ||
const source = { key1: '', key1_context: 'value1' } | ||
@@ -92,3 +92,3 @@ const target = { key1: '' } | ||
it('does not restores context keys when the singular one does not', function (done) { | ||
it('does not restores context keys when the singular one does not', (done) => { | ||
const source = { key1: '', key1_context: 'value1' } | ||
@@ -103,3 +103,3 @@ const target = { key2: '' } | ||
it('works with deep objects', function (done) { | ||
it('works with deep objects', (done) => { | ||
const source = { | ||
@@ -158,3 +158,3 @@ key1: 'value1', | ||
it('leaves arrays of values (multiline) untouched', function (done) { | ||
it('leaves arrays of values (multiline) untouched', (done) => { | ||
const source = { key1: ['Line one.', 'Line two.'] } | ||
@@ -161,0 +161,0 @@ const target = { key1: '' } |
import { assert } from 'chai' | ||
import { populateHash } from '../../src/helpers' | ||
describe('populateHash helper function', function () { | ||
it('replaces `target` empty keys with `source` ones', function (done) { | ||
describe('populateHash helper function', () => { | ||
it('replaces `target` empty keys with `source` ones', (done) => { | ||
const source = { key1: 'value1' } | ||
@@ -14,3 +14,3 @@ const target = { key1: '' } | ||
it('leaves untouched `target` keys that are not empty', function (done) { | ||
it('leaves untouched `target` keys that are not empty', (done) => { | ||
const source = { key1: 'value1' } | ||
@@ -24,3 +24,3 @@ const target = { key1: 'value2' } | ||
it('leaves untouched `target` keys not in `source`', function (done) { | ||
it('leaves untouched `target` keys not in `source`', (done) => { | ||
const source = { key1: 'value1' } | ||
@@ -34,3 +34,3 @@ const target = { key1: '', key2: '' } | ||
it('works with deep objects', function (done) { | ||
it('works with deep objects', (done) => { | ||
const source = { | ||
@@ -37,0 +37,0 @@ key1: 'value1', |
@@ -7,4 +7,6 @@ import { assert } from 'chai' | ||
const enLibraryPath = path.normalize('en/translation.json') | ||
describe('parser', () => { | ||
it('parses globally on multiple lines', done => { | ||
it('parses globally on multiple lines', (done) => { | ||
let result | ||
@@ -19,3 +21,3 @@ const i18nextParser = new i18nTransform() | ||
i18nextParser.once('data', file => { | ||
if (file.relative.endsWith('en/translation.json')) { | ||
if (file.relative.endsWith(enLibraryPath)) { | ||
result = JSON.parse(file.contents) | ||
@@ -31,3 +33,3 @@ } | ||
it('parses multiline function calls', done => { | ||
it('parses multiline function calls', (done) => { | ||
let result | ||
@@ -43,3 +45,3 @@ const i18nextParser = new i18nTransform() | ||
i18nextParser.on('data', file => { | ||
if (file.relative.endsWith('en/translation.json')) { | ||
if (file.relative.endsWith(enLibraryPath)) { | ||
result = JSON.parse(file.contents) | ||
@@ -56,3 +58,3 @@ } | ||
it('creates context keys', done => { | ||
it('creates context keys', (done) => { | ||
let result | ||
@@ -66,3 +68,3 @@ const i18nextParser = new i18nTransform() | ||
i18nextParser.on('data', file => { | ||
if (file.relative.endsWith('en/translation.json')) { | ||
if (file.relative.endsWith(enLibraryPath)) { | ||
result = JSON.parse(file.contents) | ||
@@ -82,3 +84,3 @@ } | ||
it('parses html files', done => { | ||
it('parses html files', (done) => { | ||
let result | ||
@@ -102,3 +104,3 @@ const i18nextParser = new i18nTransform() | ||
i18nextParser.on('data', file => { | ||
if (file.relative.endsWith('en/translation.json')) { | ||
if (file.relative.endsWith(enLibraryPath)) { | ||
result = JSON.parse(file.contents) | ||
@@ -114,3 +116,3 @@ } | ||
it('parses handlebars files', done => { | ||
it('parses handlebars files', (done) => { | ||
let result | ||
@@ -139,3 +141,3 @@ const i18nextParser = new i18nTransform() | ||
i18nextParser.on('data', file => { | ||
if (file.relative.endsWith('en/translation.json')) { | ||
if (file.relative.endsWith(enLibraryPath)) { | ||
result = JSON.parse(file.contents) | ||
@@ -152,3 +154,3 @@ } | ||
it('parses javascript files', done => { | ||
it('parses javascript files', (done) => { | ||
let result | ||
@@ -170,3 +172,3 @@ const i18nextParser = new i18nTransform() | ||
i18nextParser.on('data', file => { | ||
if (file.relative.endsWith('en/translation.json')) { | ||
if (file.relative.endsWith(enLibraryPath)) { | ||
result = JSON.parse(file.contents) | ||
@@ -183,3 +185,40 @@ } | ||
it('creates two files per namespace and per locale', done => { | ||
it('parses react files', (done) => { | ||
let result | ||
const i18nextParser = new i18nTransform() | ||
const fakeFile = new Vinyl({ | ||
contents: fs.readFileSync( | ||
path.resolve(__dirname, 'templating/react.jsx') | ||
), | ||
path: 'react.jsx' | ||
}) | ||
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: '' | ||
} | ||
i18nextParser.on('data', file => { | ||
// support for a default Namespace | ||
if (file.relative.endsWith(path.normalize('en/react.json'))) { | ||
result = JSON.parse(file.contents) | ||
} | ||
}) | ||
i18nextParser.on('end', () => { | ||
assert.deepEqual(result, expected) | ||
done() | ||
}) | ||
i18nextParser.end(fakeFile) | ||
}) | ||
it('creates two files per namespace and per locale', (done) => { | ||
let results = [] | ||
@@ -198,3 +237,3 @@ const i18nextParser = new i18nTransform({ | ||
i18nextParser.on('data', file => { | ||
results.push(file.relative.replace('locales/', '')) | ||
results.push(file.relative.replace(/locales[\//\\]/, '')) | ||
}) | ||
@@ -225,3 +264,3 @@ i18nextParser.on('end', () => { | ||
expectedFiles.forEach(filename => { | ||
assert.include(results, filename) | ||
assert.include(results, path.normalize(filename)) | ||
if (!--length) done() | ||
@@ -234,3 +273,3 @@ }) | ||
it('handles escaped single and double quotes', done => { | ||
it('handles escaped single and double quotes', (done) => { | ||
let result | ||
@@ -246,3 +285,3 @@ const i18nextParser = new i18nTransform() | ||
i18nextParser.on('data', file => { | ||
if (file.relative.endsWith('en/translation.json')) { | ||
if (file.relative.endsWith(enLibraryPath)) { | ||
result = JSON.parse(file.contents) | ||
@@ -261,3 +300,3 @@ } | ||
it('handles escaped characters', done => { | ||
it('handles escaped characters', (done) => { | ||
let result | ||
@@ -273,3 +312,3 @@ const i18nextParser = new i18nTransform() | ||
i18nextParser.on('data', file => { | ||
if (file.relative.endsWith('en/translation.json')) { | ||
if (file.relative.endsWith(enLibraryPath)) { | ||
result = JSON.parse(file.contents) | ||
@@ -287,3 +326,3 @@ } | ||
it('returns buffers', done => { | ||
it('returns buffers', (done) => { | ||
const i18nextParser = new i18nTransform() | ||
@@ -305,3 +344,3 @@ const fakeFile = new Vinyl({ | ||
it('retrieves values in existing catalog', done => { | ||
it('retrieves values in existing catalog', (done) => { | ||
let result | ||
@@ -315,3 +354,3 @@ const i18nextParser = new i18nTransform({ output: 'test/locales' }) | ||
i18nextParser.on('data', file => { | ||
if (file.relative.endsWith('en/test_merge.json')) { | ||
if (file.relative.endsWith(path.normalize('en/test_merge.json'))) { | ||
result = JSON.parse(file.contents) | ||
@@ -328,3 +367,3 @@ } | ||
it('does not leak values between locales', done => { | ||
it('does not leak values between locales', (done) => { | ||
let resultEN | ||
@@ -339,6 +378,6 @@ let resultFR | ||
i18nextParser.on('data', file => { | ||
if (file.relative.endsWith('en/test_leak.json')) { | ||
if (file.relative.endsWith(path.normalize('en/test_leak.json'))) { | ||
resultEN = JSON.parse(file.contents) | ||
} | ||
if (file.relative.endsWith('fr/test_leak.json')) { | ||
if (file.relative.endsWith(path.normalize('fr/test_leak.json'))) { | ||
resultFR = JSON.parse(file.contents) | ||
@@ -356,3 +395,3 @@ } | ||
it('retrieves context values in existing catalog', done => { | ||
it('retrieves context values in existing catalog', (done) => { | ||
let result | ||
@@ -372,3 +411,3 @@ const i18nextParser = new i18nTransform({ output: 'test/locales' }) | ||
i18nextParser.on('data', file => { | ||
if (file.relative.endsWith('en/test_context.json')) { | ||
if (file.relative.endsWith(path.normalize('en/test_context.json'))) { | ||
result = JSON.parse(file.contents) | ||
@@ -385,3 +424,3 @@ } | ||
it('retrieves plural values in existing catalog', done => { | ||
it('retrieves plural values in existing catalog', (done) => { | ||
let result | ||
@@ -405,3 +444,3 @@ const i18nextParser = new i18nTransform({ output: 'test/locales' }) | ||
i18nextParser.on('data', file => { | ||
if (file.relative.endsWith('en/test_plural.json')) { | ||
if (file.relative.endsWith(path.normalize('en/test_plural.json'))) { | ||
result = JSON.parse(file.contents) | ||
@@ -418,3 +457,3 @@ } | ||
it('retrieves plural and context values in existing catalog', done => { | ||
it('retrieves plural and context values in existing catalog', (done) => { | ||
let result | ||
@@ -434,3 +473,3 @@ const i18nextParser = new i18nTransform({ output: 'test/locales' }) | ||
i18nextParser.on('data', file => { | ||
if (file.relative.endsWith('en/test_context_plural.json')) { | ||
if (file.relative.endsWith(path.normalize('en/test_context_plural.json'))) { | ||
result = JSON.parse(file.contents) | ||
@@ -448,3 +487,3 @@ } | ||
describe('options', () => { | ||
it('handles filename and extension with $LOCALE and $NAMESPACE var', done => { | ||
it('handles filename and extension with $LOCALE and $NAMESPACE var', (done) => { | ||
let results = [] | ||
@@ -463,3 +502,3 @@ const i18nextParser = new i18nTransform({ | ||
i18nextParser.on('data', file => { | ||
results.push(file.relative.replace('locales/', '')) | ||
results.push(file.relative.replace(/locales[\\\/]/, '')) | ||
}) | ||
@@ -474,3 +513,3 @@ i18nextParser.on('end', () => { | ||
expectedFiles.forEach(filename => { | ||
assert.include(results, filename) | ||
assert.include(results, path.normalize(filename)) | ||
if (!--length) done() | ||
@@ -483,3 +522,3 @@ }) | ||
it('handles custom namespace and key separators', done => { | ||
it('handles custom namespace and key separators', (done) => { | ||
let result | ||
@@ -498,3 +537,3 @@ const i18nextParser = new i18nTransform({ | ||
i18nextParser.on('data', file => { | ||
if (file.relative.endsWith('en/test_separators.json')) { | ||
if (file.relative.endsWith(path.normalize('en/test_separators.json'))) { | ||
result = JSON.parse(file.contents) | ||
@@ -511,5 +550,29 @@ } | ||
it('supports a defaultValue', done => { | ||
it('handles disabling namespace and key separators', (done) => { | ||
let result | ||
const i18nextParser = new i18nTransform({ | ||
namespaceSeparator: false, | ||
keySeparator: false | ||
}) | ||
const fakeFile = new Vinyl({ | ||
contents: Buffer.from("asd t('Status: loading...')"), | ||
path: 'file.js' | ||
}) | ||
i18nextParser.on('data', file => { | ||
if (file.relative.endsWith(enLibraryPath)) { | ||
result = JSON.parse(file.contents) | ||
} | ||
}) | ||
i18nextParser.once('end', () => { | ||
assert.deepEqual(result, { 'Status: loading...': '' }) | ||
done() | ||
}) | ||
i18nextParser.end(fakeFile) | ||
}) | ||
it('supports a defaultValue', (done) => { | ||
let result | ||
const i18nextParser = new i18nTransform({ | ||
defaultValue: 'NOT_TRANSLATED' | ||
@@ -523,3 +586,3 @@ }) | ||
i18nextParser.on('data', file => { | ||
if (file.relative.endsWith('en/translation.json')) { | ||
if (file.relative.endsWith(enLibraryPath)) { | ||
result = JSON.parse(file.contents) | ||
@@ -536,5 +599,44 @@ } | ||
it('supports outputing to yml', done => { | ||
it('parses Trans if reactNamespace is true', (done) => { | ||
let result | ||
const i18nextParser = new i18nTransform({ | ||
reactNamespace: true | ||
}) | ||
const fakeFile = new Vinyl({ | ||
contents: fs.readFileSync( | ||
path.resolve(__dirname, 'templating/react.jsx') | ||
), | ||
path: 'react.js' | ||
}) | ||
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: '' | ||
} | ||
i18nextParser.on('data', file => { | ||
// support for a default Namespace | ||
if (file.relative.endsWith(path.normalize('en/react.json'))) { | ||
result = JSON.parse(file.contents) | ||
} | ||
}) | ||
i18nextParser.on('end', () => { | ||
assert.deepEqual(result, expected) | ||
done() | ||
}) | ||
i18nextParser.end(fakeFile) | ||
}) | ||
it('supports outputing to yml', (done) => { | ||
let result | ||
const i18nextParser = new i18nTransform({ | ||
extension: '.yml' | ||
@@ -548,3 +650,3 @@ }) | ||
i18nextParser.on('data', file => { | ||
if (file.relative.endsWith('en/translation.yml')) { | ||
if (file.relative.endsWith(path.normalize('en/translation.yml'))) { | ||
result = file.contents.toString('utf8') | ||
@@ -554,3 +656,3 @@ } | ||
i18nextParser.once('end', () => { | ||
assert.equal(result, 'first: ""\n') | ||
assert.equal(result.replace(/\r\n/g, '\n'), 'first: ""\n') | ||
done() | ||
@@ -562,3 +664,3 @@ }) | ||
it('supports an indentation option', done => { | ||
it('supports an indentation option', (done) => { | ||
let result | ||
@@ -574,3 +676,3 @@ const i18nextParser = new i18nTransform({ | ||
i18nextParser.on('data', file => { | ||
if (file.relative.endsWith('en/translation.json')) { | ||
if (file.relative.endsWith(enLibraryPath)) { | ||
result = file.contents.toString('utf8') | ||
@@ -580,3 +682,3 @@ } | ||
i18nextParser.once('end', () => { | ||
assert.deepEqual(result.split('\n')[1], ' "first": ""') | ||
assert.deepEqual(result.replace(/\r\n/g, '\n').split('\n')[1], ' "first": ""') | ||
done() | ||
@@ -588,12 +690,11 @@ }) | ||
it('handles skipping the old catalog with createOldLibraries=false', done => { | ||
it('handles skipping the old catalog with createOldCatalogs=false', (done) => { | ||
let results = [] | ||
const i18nextParser = new i18nTransform({ | ||
locales: ['en', 'de', 'fr'], | ||
defaultNamespace: 'default', | ||
createOldLibraries: false | ||
createOldCatalogs: false | ||
}) | ||
const fakeFile = new Vinyl({ | ||
contents: Buffer.from( | ||
"asd t('ns1:first') t('second') \n asd t('ns2:third') ad t('fourth')" | ||
"asd t('ns1:first') t('second') \n asd ad t('fourth')" | ||
), | ||
@@ -604,3 +705,3 @@ path: 'file.js' | ||
i18nextParser.on('data', file => { | ||
results.push(file.relative.replace('locales/', '')) | ||
results.push(file.relative.replace(/locales[\\\/]/, '')) | ||
}) | ||
@@ -611,14 +712,10 @@ i18nextParser.on('end', () => { | ||
'en/ns1.json', | ||
'en/ns2.json', | ||
'de/default.json', | ||
'de/ns1.json', | ||
'de/ns2.json', | ||
'fr/default.json', | ||
'fr/ns1.json', | ||
'fr/ns2.json' | ||
'fr/ns1.json' | ||
] | ||
let length = expectedFiles.length | ||
assert.equal(results.length, expectedFiles.length) | ||
expectedFiles.forEach(filename => { | ||
assert.include(results, filename) | ||
assert.include(results, path.normalize(filename)) | ||
if (!--length) done() | ||
@@ -632,3 +729,3 @@ }) | ||
describe('lexers', () => { | ||
it('support custom lexers options', done => { | ||
it('support custom lexers options', (done) => { | ||
let result | ||
@@ -651,3 +748,3 @@ const i18nextParser = new i18nTransform({ | ||
i18nextParser.on('data', file => { | ||
if (file.relative.endsWith('en/translation.json')) { | ||
if (file.relative.endsWith(enLibraryPath)) { | ||
result = JSON.parse(file.contents) | ||
@@ -666,3 +763,3 @@ } | ||
describe('sort', () => { | ||
it('does not sort by default', done => { | ||
it('does not sort by default', (done) => { | ||
let result | ||
@@ -678,3 +775,3 @@ const i18nextParser = new i18nTransform() | ||
i18nextParser.on('data', file => { | ||
if (file.relative.endsWith('en/translation.json')) { | ||
if (file.relative.endsWith(enLibraryPath)) { | ||
result = JSON.parse(file.contents) | ||
@@ -692,3 +789,3 @@ } | ||
it('supports sort as an option', done => { | ||
it('supports sort as an option', (done) => { | ||
let result | ||
@@ -706,3 +803,3 @@ const i18nextParser = new i18nTransform({ | ||
i18nextParser.on('data', file => { | ||
if (file.relative.endsWith('en/translation.json')) { | ||
if (file.relative.endsWith(enLibraryPath)) { | ||
result = JSON.parse(file.contents) | ||
@@ -723,3 +820,3 @@ } | ||
describe('events', () => { | ||
it('emits a `reading` event', done => { | ||
it('emits a `reading` event', (done) => { | ||
let result | ||
@@ -742,3 +839,3 @@ const i18nextParser = new i18nTransform() | ||
it('emits a `error` event if the catalog is not valid json', done => { | ||
it('emits a `error` event if the catalog is not valid json', (done) => { | ||
const i18nextParser = new i18nTransform({ output: 'test/locales' }) | ||
@@ -751,3 +848,3 @@ const fakeFile = new Vinyl({ | ||
i18nextParser.on('error', error => { | ||
assert.equal(error.message, 'Unexpected token / in JSON at position 0') | ||
assert.equal(error.message.startsWith('Unexpected token /'), true) | ||
done() | ||
@@ -758,3 +855,3 @@ }) | ||
it('emits an `error` if a lexer does not exist', done => { | ||
it('emits an `error` if a lexer does not exist', (done) => { | ||
const results = [] | ||
@@ -774,3 +871,3 @@ const i18nextParser = new i18nTransform({ lexers: { js: ['fakeLexer'] } }) | ||
it('emits a `warning` event if a key contains a variable', done => { | ||
it('emits a `warning` event if a key contains a variable', (done) => { | ||
const i18nextParser = new i18nTransform({ output: 'test/locales' }) | ||
@@ -777,0 +874,0 @@ const fakeFile = new Vinyl({ |
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
218163
51
3208
184
0
11
+ Addedacorn-jsx@^4.1.1
+ Addedacorn@5.7.4(transitive)
+ Addedacorn-jsx@4.1.1(transitive)