i18next-scanner
Advanced tools
Comparing version 0.1.0 to 0.2.0
@@ -64,7 +64,5 @@ var _ = require('lodash'); | ||
key = hash(value); // returns a hash value as default key | ||
parser.parseValue(value, key); | ||
return; | ||
} | ||
parser.parseKey(key, value); | ||
parser.parse(key, value); | ||
}); | ||
@@ -97,3 +95,3 @@ }()); | ||
key = hash(value); // returns a hash value as default key | ||
parser.parseValue(value, key); | ||
parser.parse(key, value); | ||
}); | ||
@@ -120,3 +118,3 @@ }()); | ||
key = hash(value); // returns a hash value as default key | ||
parser.parseValue(value, key); | ||
parser.parse(key, value); | ||
} | ||
@@ -123,0 +121,0 @@ }); |
@@ -33,3 +33,3 @@ var _ = require('lodash'); | ||
var keys = _.trim(r[1], '\'"'); | ||
parser.parseKeys(keys); | ||
parser.parseAttrs(keys); | ||
} | ||
@@ -52,3 +52,3 @@ }); | ||
var key = _.str.trim(r[1], '\'"'); | ||
parser.parseKey(key); | ||
parser.parse(key); | ||
} | ||
@@ -55,0 +55,0 @@ }); |
@@ -104,44 +104,7 @@ var fs = require('fs'); | ||
/** | ||
* Parses translation keys from `data-i18n` attribute in HTML | ||
* @param {string} attrs A semicolon-separated list of attributes | ||
*/ | ||
Parser.prototype.parseAttrs = function(attrs) { | ||
var _self = this; | ||
var keys = []; | ||
if (attrs.indexOf(';') <= attrs.length-1) { | ||
keys = attrs.split(';'); | ||
} else { | ||
keys = [ attrs ]; | ||
} | ||
_.each(keys, function(key) { | ||
var attr = 'text'; | ||
key = _.trim(key); | ||
if (key.length === 0) { | ||
return; | ||
} | ||
if (key.indexOf('[') === 0) { | ||
var parts = key.split(']'); | ||
key = parts[1]; | ||
attr = parts[0].substr(1, parts[0].length-1); | ||
} | ||
if (key.indexOf(';') === key.length-1) { | ||
key = key.substr(0, key.length-2); | ||
} | ||
_self.parseKey(key); | ||
}); | ||
}; | ||
/** | ||
* Parses a key string and stores the key-value pairs to i18n resource store | ||
* Parses a translation key and stores the key-value pairs to i18n resource store | ||
* @param {string} key The translation key | ||
* @param {string} [defaultValue] The key's value | ||
*/ | ||
Parser.prototype.parseKey = function(key, defaultValue) { | ||
Parser.prototype.parse = function(key, defaultValue) { | ||
var options = this.options; | ||
@@ -199,29 +162,35 @@ var resStore = this.resStore; | ||
/** | ||
* Parses a value string and stores the key-value pairs to i18n resource store | ||
* @param {string} value The key's value | ||
* @param {string} defaultKey The translation key | ||
* Parses translation keys from `data-i18n` attribute in HTML | ||
* @param {string} attrs A semicolon-separated list of attributes | ||
*/ | ||
Parser.prototype.parseValue = function(value, defaultKey) { | ||
var options = this.options; | ||
var resStore = this.resStore; | ||
Parser.prototype.parseAttrs = function(attrs) { | ||
var _self = this; | ||
var ns = _.isString(options.ns) ? options.ns : options.ns.defaultNs; | ||
console.assert(_.isString(ns) && !!ns.length, 'ns is not a valid string', ns); | ||
var keys = []; | ||
if (attrs.indexOf(';') <= attrs.length-1) { | ||
keys = attrs.split(';'); | ||
} else { | ||
keys = [ attrs ]; | ||
} | ||
var key = defaultKey; | ||
console.assert(_.isString(key) && !!key.length, 'defaultKey is not a valid string', key); | ||
_.each(keys, function(key) { | ||
var attr = 'text'; | ||
_.each(options.lngs, function(lng) { | ||
var lookupKey = '[' + lng + '][' + ns + '][' + key + ']'; | ||
key = _.trim(key); | ||
// Verify existing value | ||
var _value = map(resStore, lng + '.' + ns + '.' + key); | ||
if (_.isUndefined(_value)) { | ||
map(resStore, lng + '.' + ns + '.' + key, value); | ||
debuglog('[+] resStore' + lookupKey + '="' + map(resStore, lookupKey) + '"'); | ||
} else if (_value === value) { | ||
debuglog('[v] resStore' + lookupKey + '="' + map(resStore, lookupKey) + '"'); | ||
} else { | ||
console.error('[x] Key conflict in ' + lookupKey + '="' + _value + '"\n' + 'sha1' + '("' + value + '")=' + key); | ||
if (key.length === 0) { | ||
return; | ||
} | ||
if (key.indexOf('[') === 0) { | ||
var parts = key.split(']'); | ||
key = parts[1]; | ||
attr = parts[0].substr(1, parts[0].length-1); | ||
} | ||
if (key.indexOf(';') === key.length-1) { | ||
key = key.substr(0, key.length-2); | ||
} | ||
_self.parseKey(key); | ||
}); | ||
@@ -231,3 +200,4 @@ }; | ||
/** | ||
* Parses hash arguments | ||
* Parses hash arguments for Handlebars block helper | ||
* @see [Hash Arguments]{@http://code.demunskin.com/other/Handlebars/block_helpers.html#hash-arguments} | ||
* @see [Regular expression for parsing name value pairs]{@link http://stackoverflow.com/questions/168171/regular-expression-for-parsing-name-value-pairs} | ||
@@ -238,7 +208,8 @@ * @example <caption>Example usage:</caption> | ||
* str.match(/([^=,\s]*)\s*=\s*((?:"(?:\\.|[^"\\]+)*"|'(?:\\.|[^'\\]+)*')|[^'"\s]*)/igm) || []; | ||
* @param [string] hashArguments A string representation of hash arguments | ||
* @param [string] str A string representation of hash arguments | ||
* @return {object} | ||
*/ | ||
Parser.prototype.parseHashArguments = function(hashArguments) { | ||
Parser.prototype.parseHashArguments = function(str) { | ||
var hash = {}; | ||
var params = hashArguments.match(/([^=,\s]*)\s*=\s*((?:"(?:\\.|[^"\\]+)*"|'(?:\\.|[^'\\]+)*')|[^'"\s]*)/igm) || []; | ||
var params = str.match(/([^=,\s]*)\s*=\s*((?:"(?:\\.|[^"\\]+)*"|'(?:\\.|[^'\\]+)*')|[^'"\s]*)/igm) || []; | ||
var unquote = function(str, quoteChar) { | ||
@@ -278,2 +249,3 @@ quoteChar = quoteChar || '"'; | ||
}); | ||
return hash; | ||
@@ -280,0 +252,0 @@ }; |
{ | ||
"name": "i18next-scanner", | ||
"version": "0.1.0", | ||
"description": "A text scanner for i18next", | ||
"version": "0.2.0", | ||
"description": "i18next-scanner is a transfrom stream that can scan your code, extract translation keys/values, and merge them into i18n resource files.", | ||
"homepage": "https://github.com/cheton/i18next-scanner", | ||
@@ -6,0 +6,0 @@ "author": "Cheton Wu <cheton@gmail.com>", |
488
README.md
@@ -5,30 +5,47 @@ # i18next-scanner [![build status](https://travis-ci.org/cheton/i18next-scanner.svg?branch=master)](https://travis-ci.org/cheton/i18next-scanner) | ||
i18next-scanner is available as both gulp and grunt plugins that can scan your code, extracts translation keys/values, and merges them into i18n resource files. | ||
i18next-scanner is a transfrom stream that can scan your code, extract translation keys/values, and merge them into i18n resource files. | ||
It's available as both Gulp and Grunt plugins. | ||
## Features | ||
* Fully compatible with [i18next](https://github.com/i18next/i18next) - a full-featured i18n javascript library for translating your webapplication. | ||
* Support [i18next-text](https://github.com/cheton/i18next-text) to write your code without the need to maintain i18n keys. | ||
* A transform stream that works with both Gulp and Grunt task runner. | ||
* Support custom transform and flush functions. | ||
## Installation | ||
``` | ||
npm install --save-dev i18next-scanner | ||
``` | ||
`npm install i18next-scanner` | ||
## Usage | ||
The main entry function of [i18next-scanner](https://github.com/cheton/i18next-scanner) is a transform stream. You can use [vinyl-fs](https://github.com/wearefractal/vinyl) to create a readable stream, pipe the stream through [i18next-scanner](https://github.com/cheton/i18next-scanner) to transform your code into an i18n resource object, and write to a destination folder. | ||
Here is a simple example showing how that works: | ||
```javascript | ||
var i18next = require('i18next-scanner'); | ||
var vfs = require('vinyl-fs'); | ||
vfs.src(['path/to/src']) | ||
.pipe(i18next()) | ||
.pipe(vfs.dest('path/to/dest'); | ||
``` | ||
## Gulp Usage | ||
Now you are ready to set up a minimal configuration, and get started with Gulp. | ||
For example: | ||
```javascript | ||
gulp.task('i18next-scanner', function() { | ||
var i18next = require('i18next-scanner'); | ||
var gulp = require('gulp'); | ||
var i18next = require('i18next-scanner'); | ||
return gulp.src(['src/**/*.{js,html}'], {base: 'src'}) | ||
gulp.task('i18next', function() { | ||
return gulp.src(['src/**/*.{js,html}']) | ||
.pipe(i18next({ | ||
// Provides a list of supported languages by setting the lngs option. | ||
lngs: ['en', 'de'], | ||
// Sorts the keys in ascending order. | ||
sort: true, // default: false | ||
// Provides a default value if a value is not specified. | ||
defaultValue: '', // default: '' | ||
// The resGetPath is your source i18n path, it is relative to current working directory. | ||
resGetPath: 'assets/i18n/__lng__/__ns__.json', // default: 'i18n/__lng__/__ns__.json' | ||
// The resSetPath is your target i18n path, it is relative to your gulp.dest path. | ||
resSetPath: 'i18n/__lng__/__ns__.json', // default: 'i18n/__lng__/__ns__.json' | ||
// Default namespace is 'translation'. | ||
ns: 'translation' | ||
// a list of supported languages | ||
lngs: ['en', 'de'], | ||
// the source path is relative to current working directory | ||
resGetPath: 'assets/i18n/__lng__/__ns__.json', | ||
// the destination path is relative to your `gulp.dest()` path | ||
resSetPath: 'i18n/__lng__/__ns__.json' | ||
}) | ||
@@ -39,152 +56,345 @@ .pipe(gulp.dest('assets')); | ||
## Grunt Usage | ||
Once you've finished the installation, add this line to your project's Gruntfile: | ||
```javascript | ||
grunt.loadNpmTasks('i18next-scanner'); | ||
``` | ||
## Usage with i18next-text | ||
In your project's Gruntfile, add a section named `i18next` to the data object passed into `grunt.initConfig()`, like so: | ||
```javascript | ||
grunt.initConfig({ | ||
i18next: { | ||
dev: { | ||
src: 'src/**/*.{js,html}', | ||
dest: 'assets', | ||
options: { | ||
lngs: ['en', 'de'], | ||
resGetPath: 'assets/i18n/__lng__/__ns__.json', | ||
resSetPath: 'i18n/__lng__/__ns__.json' | ||
} | ||
} | ||
} | ||
}); | ||
```` | ||
### Parses the i18n._() method | ||
## Advanced Usage | ||
### Customize transform and flush functions | ||
As mentioned in the [Usage](#usage) section, the main entry function returns a [through2](https://github.com/rvagg/through2) object stream, you can pass in your `transform` and `flush` functions: | ||
```javascript | ||
i18next(options[, customTransform[, customFlush]]) | ||
``` | ||
gulp.task('i18next-scanner', function() { | ||
var i18next = require('i18next-scanner'); | ||
var hash = require('i18next-text').hash['sha1']; | ||
var options = { | ||
lngs: ['en', 'de'], | ||
defaultValue: '__STRING_NOT_TRANSLATED__', | ||
resGetPath: 'assets/i18n/__lng__/__ns__.json', | ||
resSetPath: 'i18n/__lng__/__ns__.json', | ||
ns: 'translation' | ||
}; | ||
var customTransform = function(file, enc, done) { | ||
var parser = this.parser; | ||
var extname = path.extname(file.path); | ||
var content = fs.readFileSync(file.path, enc); | ||
### Usage with i18next-text | ||
/* | ||
* Supports i18next-text's _() method for i18next: | ||
* | ||
* i18n._('This is text value'); | ||
* i18n._("text"); // result matched | ||
* i18n._('text'); // result matched | ||
* i18n._("text", { count: 1 }); // result matched | ||
* i18n._("text" + str); // skip run-time variables | ||
*/ | ||
(function() { | ||
var results = content.match(/i18n\._\(("[^"]*"|'[^']*')\s*[\,\)]/igm) || ''; | ||
_.each(results, function(result) { | ||
var key, value; | ||
var r = result.match(/i18n\._\(("[^"]*"|'[^']*')/); | ||
#### Example of parsing strings | ||
You might want to find all occurrences of the `i18n._()` function in your code. | ||
For example: | ||
```javascript | ||
i18n._('This is text value'); | ||
i18n._("text"); | ||
i18n._('text'); | ||
i18n._("text", { count: 1 }); | ||
i18n._("text" + str); // skip run-time variables | ||
``` | ||
if (r) { | ||
value = _.trim(r[1], '\'"'); | ||
key = hash(value); // returns a SHA-1 hash value as default key | ||
parser.parseValue(value, key); | ||
} | ||
}); | ||
}()); | ||
The content can be parsed with a regular expression, like below: | ||
```javascript | ||
i18n\._\(("[^"]*"|'[^']*')\s*[\,\)] | ||
``` | ||
done(); | ||
}; | ||
The code might look like this: | ||
```javascript | ||
var _ = require('lodash'); | ||
var hash = require('i18next-text').hash['sha1']; | ||
var customTransform = function(file, enc, done) { | ||
var parser = this.parser; | ||
var extname = path.extname(file.path); | ||
var content = fs.readFileSync(file.path, enc); | ||
return gulp.src(['src/**/*.js'], {base: 'src'}) | ||
.pipe(i18next(options)) | ||
.pipe(gulp.dest('assets')); | ||
}); | ||
(function() { | ||
var results = content.match(/i18n\._\(("[^"]*"|'[^']*')\s*[\,\)]/igm) || ''; | ||
_.each(results, function(result) { | ||
var key, value; | ||
var r = result.match(/i18n\._\(("[^"]*"|'[^']*')/); | ||
if (r) { | ||
value = _.trim(r[1], '\'"'); | ||
key = hash(value); // returns a hash value as its default key | ||
parser.parse(key, value); | ||
} | ||
}); | ||
}()); | ||
done(); | ||
}; | ||
``` | ||
### Handlebars i18n helper with block expressions | ||
#### Handlebars i18n helper | ||
**i18n function helper** | ||
```hbs | ||
{{i18n 'bar'}} | ||
{{i18n 'bar' defaultKey='foo'}} | ||
{{i18n 'baz' defaultKey='locale:foo'}} | ||
{{i18n defaultKey='noval'}} | ||
``` | ||
Using the regular expression for the above: | ||
```javascript | ||
{{i18n\s+("(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')?([^}]*)}} | ||
``` | ||
**i18n block helper** | ||
```hbs | ||
{{#i18n}}Some text{{/i18n}} | ||
{{#i18n this}}Description: {{description}}{{/i18n}} | ||
{{#i18n this last-name=lastname}}{{firstname}} ${last-name}{{/i18n}} | ||
``` | ||
gulp.task('i18next-scanner', function() { | ||
var i18next = require('i18next-scanner'); | ||
var hash = require('i18next-text').hash['sha1']; | ||
var options = { | ||
lngs: ['en', 'de'], | ||
defaultValue: '__STRING_NOT_TRANSLATED__', | ||
resGetPath: 'assets/i18n/__lng__/__ns__.json', | ||
resSetPath: 'i18n/__lng__/__ns__.json', | ||
ns: 'translation' | ||
}; | ||
Using the regular expression for the above: | ||
```javascript | ||
{{#i18n\s*([^}]*)}}((?:(?!{{\/i18n}})(?:.|\n))*){{\/i18n}} | ||
``` | ||
var customTransform = function(file, enc, done) { | ||
var parser = this.parser; | ||
var extname = path.extname(file.path); | ||
var content = fs.readFileSync(file.path, enc); | ||
**Sample code** | ||
/* | ||
* Supports Handlebars i18n helper | ||
* | ||
* {{i18n 'bar'}} | ||
* {{i18n 'bar' defaultKey='foo'}} | ||
* {{i18n 'baz' defaultKey='locale:foo'}} | ||
* {{i18n defaultKey='noval'}} | ||
*/ | ||
(function() { | ||
var results = content.match(/{{i18n\s+("(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')?([^}]*)}}/gm) || []; | ||
_.each(results, function(result) { | ||
var key, value; | ||
var r = result.match(/{{i18n\s+("(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')?([^}]*)}}/m) || []; | ||
The sample code might look like this: | ||
```javascript | ||
var _ = require('lodash'); | ||
var hash = require('i18next-text').hash['sha1']; | ||
var customTransform = function(file, enc, done) { | ||
var parser = this.parser; | ||
var extname = path.extname(file.path); | ||
var content = fs.readFileSync(file.path, enc); | ||
if ( ! _.isUndefined(r[1])) { | ||
value = _.trim(r[1], '\'"'); | ||
} | ||
// i18n function helper | ||
(function() { | ||
var results = content.match(/{{i18n\s+("(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')?([^}]*)}}/gm) || []; | ||
_.each(results, function(result) { | ||
var key, value; | ||
var r = result.match(/{{i18n\s+("(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')?([^}]*)}}/m) || []; | ||
var params = parser.parseHashArguments(r[2]); | ||
if (_.has(params, 'defaultKey')) { | ||
key = params['defaultKey']; | ||
} | ||
if (_.isUndefined(key) && _.isUndefined(value)) { | ||
return; | ||
} | ||
if ( ! _.isUndefined(r[1])) { | ||
value = _.trim(r[1], '\'"'); | ||
} | ||
if (_.isUndefined(key)) { | ||
key = hash(value); // returns a SHA-1 hash value as default key | ||
parser.parseValue(value, key); | ||
return; | ||
} | ||
var params = parser.parseHashArguments(r[2]); | ||
if (_.has(params, 'defaultKey')) { | ||
key = params['defaultKey']; | ||
} | ||
parser.parseKey(key, value); | ||
}); | ||
}()); | ||
if (_.isUndefined(key) && _.isUndefined(value)) { | ||
return; | ||
} | ||
/* | ||
* Supports Handlebars i18n helper with block expressions | ||
* | ||
* {{#i18n}}Some text{{/i18n}} | ||
* {{#i18n this}}Description: {{description}}{{/i18n}} | ||
* {{#i18n this last-name=lastname}}{{firstname}} ${last-name}{{/i18n}} | ||
* | ||
* http://stackoverflow.com/questions/406230/regular-expression-to-match-string-not-containing-a-wordo | ||
*/ | ||
(function() { | ||
var results = content.match(/{{#i18n\s*([^}]*)}}((?:(?!{{\/i18n}})(?:.|\n))*){{\/i18n}}/gm) || []; | ||
_.each(results, function(result) { | ||
var key, value; | ||
var r = result.match(/{{#i18n\s*([^}]*)}}((?:(?!{{\/i18n}})(?:.|\n))*){{\/i18n}}/m) || []; | ||
if (_.isUndefined(key)) { | ||
key = hash(value); // returns a hash value as its default key | ||
} | ||
if ( ! _.isUndefined(r[2])) { | ||
value = _.trim(r[2], '\'"'); | ||
} | ||
parser.parse(key, value); | ||
}); | ||
}()); | ||
if (_.isUndefined(value)) { | ||
return; | ||
} | ||
// i18n block helper | ||
(function() { | ||
var results = content.match(/{{#i18n\s*([^}]*)}}((?:(?!{{\/i18n}})(?:.|\n))*){{\/i18n}}/gm) || []; | ||
_.each(results, function(result) { | ||
var key, value; | ||
var r = result.match(/{{#i18n\s*([^}]*)}}((?:(?!{{\/i18n}})(?:.|\n))*){{\/i18n}}/m) || []; | ||
key = hash(value); // returns a SHA-1 hash value as default key | ||
parser.parseValue(value, key); | ||
}); | ||
}()); | ||
if ( ! _.isUndefined(r[2])) { | ||
value = _.trim(r[2], '\'"'); | ||
} | ||
done(); | ||
}; | ||
if (_.isUndefined(value)) { | ||
return; | ||
} | ||
return gulp.src(['src/**/*.hbs'], {base: 'src'}) | ||
.pipe(i18next(options)) | ||
.pipe(gulp.dest('assets')); | ||
}); | ||
key = hash(value); // returns a hash value as its default key | ||
parser.parse(key, value); | ||
}); | ||
}()); | ||
done(); | ||
}; | ||
``` | ||
## Options | ||
## API | ||
``` | ||
function(options[, customTransform[, customFlush]]) | ||
``` | ||
### options | ||
```javascript | ||
{ | ||
lngs: ['en'], | ||
sort: false, | ||
defaultValue: '', | ||
resGetPath: 'i18n/__lng__/__ns__.json', | ||
resSetPath: 'i18n/__lng__/__ns__.json', | ||
nsseparator: ':', | ||
keyseparator: '.', | ||
interpolationPrefix: '__', | ||
interpolationSuffix: '__', | ||
ns: { | ||
namespaces: [], | ||
defaultNs: 'translation' | ||
} | ||
} | ||
``` | ||
#### lngs | ||
Type: `Array` Default: `['en']` | ||
Provides a list of supported languages. | ||
#### sort | ||
Type: `Boolean` Default: `false` | ||
Set to `true` if you want to sort translation keys in ascending order. | ||
#### defaultValue | ||
Type: `String` Default: `''` | ||
Provides a default value if a value is not specified. | ||
#### resGetPath | ||
Type: `String` Default: `'i18n/__lng__/__ns__.json'` | ||
The source path of resource files. The `resGetPath` is relative to current working directory. | ||
#### resSetPath | ||
Type: `String` Default: `'i18n/__lng__/__ns__.json'` | ||
The target path of resource files. The `resSetPath` is relative to current working directory or your `gulp.dest()` path. | ||
#### nsseparator | ||
Type: `String` Default: `':'` | ||
The namespace separator. | ||
#### keyseparator | ||
Type: `String` Default: `'.'` | ||
The key separator. | ||
#### interpolationPrefix | ||
Type: `String` Default: `'__'` | ||
The prefix for variables. | ||
#### interpolationSuffix | ||
Type: `String` Default: `'__'` | ||
The suffix for variables. | ||
#### ns | ||
Type: `Object` or `String` | ||
If an `Object` is supplied, you can either specify a list of namespaces, or override the default namespace. | ||
For example: | ||
```javascript | ||
{ | ||
ns: { | ||
namespaces: [ // Default: [] | ||
'resource', | ||
'locale' | ||
], | ||
defaultNs: 'resource' // Default: 'translation' | ||
} | ||
} | ||
``` | ||
If a `String` is supplied instead, it will become the default namespace. | ||
For example: | ||
```javascript | ||
{ | ||
ns: 'resource' // Default: 'translation' | ||
} | ||
``` | ||
### customTransform | ||
The optional `customTransform` function is provided as the 2nd argument. It must have the following signature: `function (file, encoding, done) {}`. A minimal implementation should call the `done()` function to indicate that the transformation is done, even if that transformation means discarding the file. | ||
For example: | ||
```javascript | ||
var customTransform = function _transform(file, enc, done) { | ||
var parser = this.parser; | ||
var extname = path.extname(file.path); | ||
var content = fs.readFileSync(file.path, enc); | ||
// add custom code | ||
done(); | ||
}; | ||
``` | ||
To parse a translation key, call `parser.parse(key, defaultValue)` to assign the key with an optional `defaultValue`. | ||
For example: | ||
```javascript | ||
var _ = require('lodash'); | ||
var customTransform = function _transform(file, enc, done) { | ||
var parser = this.parser; | ||
var content = fs.readFileSync(file.path, enc); | ||
var results = []; | ||
// parse the content and loop over the results | ||
_.each(results, function(result) { | ||
var key = result.key; | ||
var value = result.defaultValue || ''; | ||
parser.parse(key, value); | ||
}); | ||
}; | ||
``` | ||
Alternatively, you may call `parser.parse(defaultKey, value)` to assign the value with a default key. The `defaultKey` should be unique string and can never be `null`, `undefined`, or empty. | ||
For example: | ||
```javascript | ||
var _ = require('lodash'); | ||
var hash = require('i18next-text').hash['sha1']; | ||
var customTransform = function _transform(file, enc, done) { | ||
var parser = this.parser; | ||
var content = fs.readFileSync(file.path, enc); | ||
var results = []; | ||
// parse the content and loop over the results | ||
_.each(results, function(result) { | ||
var key = result.defaultKey || hash(result.value); | ||
var value = result.value; | ||
parser.parse(key, value); | ||
}); | ||
}; | ||
``` | ||
### customFlush | ||
The optional `customFlush` function is provided as the last argument, it is called just prior to the stream ending. You can implement your `customFlush` function to override the default `flush` function. When everything's done, call the `done()` function to indicate the stream is finished. | ||
For example: | ||
```javascript | ||
var _ = require('lodash'); | ||
var customFlush = function _flush(done) { | ||
var that = this; | ||
var resStore = parser.toObject({ | ||
sort: !!parser.options.sort | ||
}); | ||
// loop over the resStore | ||
_.each(resStore, function(namespaces, lng) { | ||
_.each(namespaces, function(obj, ns) { | ||
// add custom code | ||
}); | ||
}); | ||
done(); | ||
}; | ||
``` | ||
## License | ||
@@ -191,0 +401,0 @@ |
46544
27
403
835