Socket
Socket
Sign inDemoInstall

i18next-scanner

Package Overview
Dependencies
Maintainers
1
Versions
92
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

i18next-scanner - npm Package Compare versions

Comparing version 1.9.4 to 2.0.0

lib/jsx-parser.js

2

lib/index.js

@@ -48,2 +48,4 @@ 'use strict';

parser.parseFuncFromString(content);
// Look for Trans components in JSX
parser.parseTransFromString(content);
}

@@ -50,0 +52,0 @@

127

lib/parser.js

@@ -74,2 +74,6 @@ 'use strict';

var _parse = require('parse5');
var _parse2 = _interopRequireDefault(_parse);
var _ensureArray = require('./ensure-array');

@@ -79,2 +83,6 @@

var _jsxParser = require('./jsx-parser');
var _jsxParser2 = _interopRequireDefault(_jsxParser);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

@@ -431,2 +439,31 @@

}
// Parses translation keys from `Trans` components in JSX
// <Trans i18nKey="some.key">Default text</Trans>
}, {
key: 'parseTransFromString',
value: function parseTransFromString(content) {
var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var customHandler = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
var pattern = '<Trans[^]*?i18nKey="([^"]+)"[^]*?>([^]*?)</\\s*Trans\\s*>';
var re = new RegExp(pattern, 'gim');
var setter = this.set.bind(this);
if ((0, _isFunction2.default)(opts)) {
setter = opts;
opts = {};
}
var r = void 0;
while (r = re.exec(content)) {
var _key3 = (0, _trim2.default)(r[1]);
var fragment = (0, _trim2.default)(r[2]);
fragment = fragment.replace(/\s+/g, ' ');
var defaultValue = (0, _jsxParser2.default)(fragment);
var _options = { defaultValue: defaultValue };
setter(_key3, _options);
}
return this;
}
// Parses translation keys from `data-i18n` attribute in HTML

@@ -439,9 +476,9 @@ // <div data-i18n="[attr]ns:foo.bar;[attr]ns:foo.baz">

value: function parseAttrFromString(content) {
var _this3 = this;
var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var customHandler = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
var setter = this.set.bind(this);
if ((0, _isFunction2.default)(opts)) {
customHandler = opts;
setter = opts;
opts = {};

@@ -456,36 +493,38 @@ }

var matchPattern = attrs.map(function (attr) {
return '(?:' + attr + ')';
}).join('|').replace(/\./g, '\\.');
var pattern = '(?:(?:^[\\s]*)|[^a-zA-Z0-9_])(?:' + matchPattern + ')=("[^"]*"|\'[^\']*\')';
var re = new RegExp(pattern, 'gim');
var ast = _parse2.default.parse(content);
var r = void 0;
var parseAttributeValue = function parseAttributeValue(key) {
key = (0, _trim2.default)(key);
if (key.length === 0) {
return;
}
if (key.indexOf('[') === 0) {
var parts = key.split(']');
key = parts[1];
}
if (key.indexOf(';') === key.length - 1) {
key = key.substr(0, key.length - 2);
}
while (r = re.exec(content)) {
var attr = (0, _trim2.default)(r[1], '\'"');
var keys = attr.indexOf(';') >= 0 ? attr.split(';') : [attr];
setter(key);
};
keys.forEach(function (key) {
key = (0, _trim2.default)(key);
if (key.length === 0) {
return;
var walk = function walk(nodes) {
nodes.forEach(function (node) {
if (node.attrs) {
node.attrs.forEach(function (attr) {
if (attrs.indexOf(attr.name) !== -1) {
var values = attr.value.split(';');
values.forEach(parseAttributeValue);
}
});
}
if (key.indexOf('[') === 0) {
var parts = key.split(']');
key = parts[1];
if (node.childNodes) {
walk(node.childNodes);
}
if (key.indexOf(';') === key.length - 1) {
key = key.substr(0, key.length - 2);
}
});
};
if (customHandler) {
customHandler(key);
return;
}
walk(ast.childNodes);
_this3.set(key);
});
}
return this;

@@ -584,3 +623,3 @@ }

value: function set(key) {
var _this4 = this;
var _this3 = this;

@@ -619,11 +658,11 @@ var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};

var _options = this.options,
lngs = _options.lngs,
context = _options.context,
contextFallback = _options.contextFallback,
contextSeparator = _options.contextSeparator,
plural = _options.plural,
pluralFallback = _options.pluralFallback,
pluralSeparator = _options.pluralSeparator,
defaultValue = _options.defaultValue;
var _options2 = this.options,
lngs = _options2.lngs,
context = _options2.context,
contextFallback = _options2.contextFallback,
contextSeparator = _options2.contextSeparator,
plural = _options2.plural,
pluralFallback = _options2.pluralFallback,
pluralSeparator = _options2.pluralSeparator,
defaultValue = _options2.defaultValue;

@@ -633,8 +672,8 @@ var keys = (0, _isString2.default)(keySeparator) ? key.split(keySeparator) : [key];

lngs.forEach(function (lng) {
var resLoad = _this4.resStore[lng] && _this4.resStore[lng][ns];
var resScan = _this4.resScan[lng] && _this4.resScan[lng][ns];
var resLoad = _this3.resStore[lng] && _this3.resStore[lng][ns];
var resScan = _this3.resScan[lng] && _this3.resScan[lng][ns];
if (!(0, _isObject2.default)(resLoad)) {
// Skip undefined namespace
_this4.log('The namespace "' + ns + '" does not exist:', { key: key, options: options });
_this3.log('The namespace "' + ns + '" does not exist:', { key: key, options: options });
return;

@@ -724,3 +763,3 @@ }

}
_this4.log('Added a new translation key { %s: %s } to %s', JSON.stringify(resKey), JSON.stringify(resLoad[resKey]), JSON.stringify(_this4.formatResourceLoadPath(lng, ns)));
_this3.log('Added a new translation key { %s: %s } to %s', JSON.stringify(resKey), JSON.stringify(resLoad[resKey]), JSON.stringify(_this3.formatResourceLoadPath(lng, ns)));
}

@@ -727,0 +766,0 @@

{
"name": "i18next-scanner",
"version": "1.9.4",
"version": "2.0.0",
"description": "Scan your code, extract translation keys/values, and merge them into i18n resource files.",

@@ -16,13 +16,8 @@ "homepage": "https://github.com/i18next/i18next-scanner",

"scripts": {
"prepublish": "npm run lint && npm run build && npm test",
"prepublish": "npm run eslint && npm run build && npm test",
"build": "babel ./src --out-dir ./lib",
"test": "tap test/*.js --node-arg=--require --node-arg=babel-register --node-arg=--require --node-arg=babel-polyfill",
"lint": "eslint ./src",
"lint:fix": "eslint --fix ./src",
"precommit-check": "npm run lint",
"coveralls": "tap test/*.js --coverage --coverage-report=text-lcov --nyc-arg=--require --nyc-arg=babel-register --nyc-arg=--require --nyc-arg=babel-polyfill | coveralls"
"eslint": "eslint ./src",
"coveralls": "tap test/*.js --coverage --coverage-report=text-lcov --nyc-arg=--require --nyc-arg=babel-register --nyc-arg=--require --nyc-arg=babel-polyfill | coveralls",
"test": "tap test/*.js --node-arg=--require --node-arg=babel-register --node-arg=--require --node-arg=babel-polyfill"
},
"pre-commit": [
"precommit-check"
],
"repository": {

@@ -34,3 +29,3 @@ "type": "git",

"engines": {
"node": ">=0.10.x"
"node": ">=4"
},

@@ -51,22 +46,22 @@ "keywords": [

"lodash": "^4.17.4",
"parse5": "^3.0.2",
"through2": "^2.0.3",
"vinyl": "^2.0.2",
"vinyl": "^2.1.0",
"vinyl-fs": "^2.4.4"
},
"devDependencies": {
"babel-cli": "^6.24.1",
"babel-core": "^6.25.0",
"babel-eslint": "^7.2.3",
"babel-cli": "^6.26.0",
"babel-core": "^6.26.0",
"babel-eslint": "^8.0.0",
"babel-preset-es2015": "^6.24.1",
"babel-preset-stage-0": "^6.24.1",
"coveralls": "^2.13.1",
"eslint": "^3.17.1",
"eslint": "^4.7.0",
"gulp": "^3.9.1",
"gulp-tap": "^0.1.3",
"gulp-tap": "^1.0.1",
"gulp-util": "^3.0.8",
"sha1": "^1.1.1",
"tap": "^10.3.3",
"text-table": "^0.2.0",
"which": "~1.2.14"
"tap": "^10.7.2",
"text-table": "^0.2.0"
}
}

@@ -7,2 +7,32 @@ # i18next-scanner [![build status](https://travis-ci.org/i18next/i18next-scanner.svg?branch=master)](https://travis-ci.org/i18next/i18next-scanner) [![Coverage Status](https://coveralls.io/repos/i18next/i18next-scanner/badge.svg?branch=master&service=github)](https://coveralls.io/github/i18next/i18next-scanner?branch=master)

Turns your code
```js
i18n._('Loading...');
i18n._('Backslashes in single quote: \' \\ \'');
i18n._('This is \
a multiline \
string');
i18n.t('car', { context: 'blue', count: 1 }); // output: 'One blue car'
i18n.t('car', { context: 'blue', count: 2 }); // output: '2 blue cars'
<Trans i18nKey="some.key">Default text</Trans>
```
into resource files
```js
{
"Loading...": "Wird geladen...", // uses existing translation
"Backslashes in single quote: ' \\ '": "__NOT_TRANSLATED__", // returns a custom string
"This is a multiline string": "this is a multiline string", // returns the key as the default value
"car": "car",
"car_blue": "One blue car",
"car_blue_plural": "{{count}} blue cars",
"some": {
"key": "Default text"
}
}
```
## Notice

@@ -15,2 +45,3 @@ There is a major breaking change since v1.0, and the API interface and options are not compatible with v0.x.

* Fully compatible with [i18next](https://github.com/i18next/i18next) - a full-featured i18n javascript library for translating your webapplication.
* Support [react-i18next](https://github.com/i18next/react-i18next) for parsing the <b>Trans</b> component
* Support [Key Based Fallback](http://i18next.com/translate/keyBasedFallback/) to write your code without the need to maintain i18n keys. This feature is available since [i18next@^2.1.0](https://github.com/i18next/i18next/blob/master/CHANGELOG.md#210)

@@ -30,11 +61,11 @@ * A standalone parser API

```js
var fs = require('fs');
var Parser = require('i18next-scanner').Parser;
const fs = require('fs');
const Parser = require('i18next-scanner').Parser;
var customHandler = function(key) {
const customHandler = function(key) {
parser.set(key, '__TRANSLATION__');
};
var parser = new Parser();
var content = '';
const parser = new Parser();
const content = '';

@@ -48,4 +79,10 @@ // Parse Translation Function

.parseFuncFromString(content, { list: ['i18next.t']}, customHandler)
.parseFuncFromString(content); // using default options and handler
.parseFuncFromString(content); // use default options and handler
// Parse Trans component
content = fs.readFileSync('/path/to/app.jsx', 'utf-8');
parser
.parseFuncFromString(content, customHandler) // pass a custom handler
.parseFuncFromString(content); // use default options and handler
// Parse HTML Attribute

@@ -70,6 +107,6 @@ // <div data-i18n="key"></div>

```js
var scanner = require('i18next-scanner');
var vfs = require('vinyl-fs');
var sort = require('gulp-sort');
var options = {
const scanner = require('i18next-scanner');
const vfs = require('vinyl-fs');
const sort = require('gulp-sort');
const options = {
// See options at https://github.com/i18next/i18next-scanner#options

@@ -94,5 +131,5 @@ };

```js
var gulp = require('gulp');
var sort = require('gulp-sort');
var scanner = require('i18next-scanner');
const gulp = require('gulp');
const sort = require('gulp-sort');
const scanner = require('i18next-scanner');

@@ -147,9 +184,12 @@ gulp.task('i18next', function() {

```js
var Parser = require('i18next-scanner').Parser;
var parser = new Parser(options);
const Parser = require('i18next-scanner').Parser;
const parser = new Parser(options);
var code = "i18next.t('key'); ...";
parser.parseFuncFromString(content);
const code = "i18next.t('key'); ...";
parser.parseFuncFromString(code);
var html = '<div data-i18n="key"></div>';
const jsx = '<Trans i18nKey="some.key">Default text</Trans>';
parser.parseTransFromString(jsx);
const html = '<div data-i18n="key"></div>';
parser.parseAttrFromString(html);

@@ -177,2 +217,13 @@

#### parser.parseTransFromString
Parse translation key from the [Trans component](https://github.com/i18next/react-i18next)
```js
parser.parseTransFromString(content);
parser.parseTransFromString(content, function(key, options) {
options.defaultValue = key; // use key as the value
parser.set(key, options);
});
```
#### parser.parseAttrFromString

@@ -210,2 +261,3 @@ Parse translation key from HTML attribute

```
#### parser.set

@@ -566,4 +618,2 @@ Set a translation key with an optional defaultValue to i18n resource store

Copyright (c) 2015-2016 Cheton Wu
Licensed under the [MIT License](https://github.com/i18next/i18next-scanner/blob/master/LICENSE).
MIT

@@ -23,2 +23,4 @@ import fs from 'fs';

parser.parseFuncFromString(content);
// Look for Trans components in JSX
parser.parseTransFromString(content);
}

@@ -25,0 +27,0 @@

@@ -18,3 +18,5 @@ /* eslint no-console: 0 */

import { parse } from 'esprima';
import parse5 from 'parse5';
import ensureArray from './ensure-array';
import jsxToText from './jsx-parser';

@@ -342,2 +344,25 @@ const defaults = {

}
// Parses translation keys from `Trans` components in JSX
// <Trans i18nKey="some.key">Default text</Trans>
parseTransFromString(content, opts = {}, customHandler = null) {
const pattern = '<Trans[^]*?i18nKey="([^"]+)"[^]*?>([^]*?)</\\s*Trans\\s*>';
const re = new RegExp(pattern, 'gim');
let setter = this.set.bind(this);
if (isFunction(opts)) {
setter = opts;
opts = {};
}
let r;
while ((r = re.exec(content))) {
const key = trim(r[1]);
let fragment = trim(r[2]);
fragment = fragment.replace(/\s+/g, ' ');
const defaultValue = jsxToText(fragment);
const options = { defaultValue };
setter(key, options);
}
return this;
}
// Parses translation keys from `data-i18n` attribute in HTML

@@ -347,4 +372,6 @@ // <div data-i18n="[attr]ns:foo.bar;[attr]ns:foo.baz">

parseAttrFromString(content, opts = {}, customHandler = null) {
let setter = this.set.bind(this);
if (isFunction(opts)) {
customHandler = opts;
setter = opts;
opts = {};

@@ -361,39 +388,38 @@ }

const matchPattern = attrs
.map(attr => ('(?:' + attr + ')'))
.join('|')
.replace(/\./g, '\\.');
const pattern = '(?:(?:^[\\s]*)|[^a-zA-Z0-9_])(?:' + matchPattern + ')=("[^"]*"|\'[^\']*\')';
const re = new RegExp(pattern, 'gim');
const ast = parse5.parse(content);
let r;
const parseAttributeValue = (key) => {
key = trim(key);
if (key.length === 0) {
return;
}
if (key.indexOf('[') === 0) {
const parts = key.split(']');
key = parts[1];
}
if (key.indexOf(';') === (key.length - 1)) {
key = key.substr(0, key.length - 2);
}
while ((r = re.exec(content))) {
const attr = trim(r[1], '\'"');
const keys = (attr.indexOf(';') >= 0)
? attr.split(';')
: [attr];
setter(key);
}
keys.forEach((key) => {
key = trim(key);
if (key.length === 0) {
return;
const walk = (nodes) => {
nodes.forEach(node => {
if (node.attrs) {
node.attrs.forEach(attr => {
if (attrs.indexOf(attr.name)!==-1) {
const values = attr.value.split(';');
values.forEach(parseAttributeValue);
}
});
}
if (key.indexOf('[') === 0) {
const parts = key.split(']');
key = parts[1];
if (node.childNodes) {
walk(node.childNodes);
}
if (key.indexOf(';') === (key.length - 1)) {
key = key.substr(0, key.length - 2);
}
})
}
if (customHandler) {
customHandler(key);
return;
}
walk(ast.childNodes)
this.set(key);
});
}
return this;

@@ -456,4 +482,4 @@ }

const keys = isString(this.options.keySeparator)
? key.split(this.options.keySeparator)
: [key];
? key.split(this.options.keySeparator)
: [key];
const lng = opts.lng

@@ -460,0 +486,0 @@ ? opts.lng

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc