diff --git a/README.md b/README.md index 1674307..e9fa37d 100755 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ into resource files { "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 + "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", @@ -263,7 +263,7 @@ gulp.task('i18next', function() { resource: { // the source path is relative to current working directory loadPath: 'assets/i18n/{{lng}}/{{ns}}.json', - + // the destination path is relative to your `gulp.dest()` path savePath: 'i18n/{{lng}}/{{ns}}.json' } @@ -307,7 +307,7 @@ const Parser = require('i18next-scanner').Parser; const parser = new Parser(options); const code = "i18next.t('key'); ..."; -parser.parseFuncFromString(code); +parser.parseFuncFromString(code); const jsx = 'Default text'; parser.parseTransFromString(jsx); @@ -381,7 +381,7 @@ Get the value of a translation key or the whole i18n resource store // Returns the whole i18n resource store parser.get(); -// Returns the resource store with the top-level keys sorted by alphabetical order +// Returns the resource store with the top-level keys sorted by alphabetical order parser.get({ sort: true }); // Returns a value in fallback language (@see options.fallbackLng) with namespace and key @@ -438,12 +438,12 @@ For example: const customTransform = function _transform(file, enc, done) { const parser = this.parser; const content = fs.readFileSync(file.path, enc); - + parser.parseFuncFromString(content, { list: ['i18n.t'] }, function(key) { const defaultValue = '__L10N__'; parser.set(key, defaultValue); }); - + done(); }; ``` @@ -455,13 +455,13 @@ const hash = require('sha1'); const customTransform = function _transform(file, enc, done) { const parser = this.parser; const content = fs.readFileSync(file.path, enc); - + parser.parseFuncFromString(content, { list: ['i18n._'] }, function(key) { const value = key; const defaultKey = hash(value); parser.set(defaultKey, value); }); - + done(); }; ``` @@ -484,7 +484,7 @@ const customFlush = function _flush(done) { // add your code }); }); - + done(); }; @@ -500,6 +500,7 @@ Below are the configuration options with their default values: ```javascript { + compatibilityJSON: 'v3', // One of: 'v1', 'v2', 'v3', 'v4 debug: false, removeUnusedKeys: false, sort: false, @@ -553,6 +554,14 @@ Below are the configuration options with their default values: } ``` +#### compatibilityJSON + +Type: `String` Default: `'v3'` + +The `compatibilityJSON` version to use for plural suffixes. + +See https://https://www.i18next.com/misc/json-format for details. + #### debug Type: `Boolean` Default: `false` @@ -724,7 +733,7 @@ Resource options: ```js { // Default resource: { - // The path where resources get loaded from. Relative to current working directory. + // The path where resources get loaded from. Relative to current working directory. loadPath: 'i18n/{{lng}}/{{ns}}.json', // The path to store resources. Relative to the path specified by `gulp.dest(path)`. @@ -745,7 +754,7 @@ Resource options: ```js { // Default resource: { - // The path where resources get loaded from. Relative to current working directory. + // The path where resources get loaded from. Relative to current working directory. loadPath: function(lng, ns) { return 'i18n/'+lng+'/'+ns+'.json'; }, @@ -857,7 +866,7 @@ interpolation options Type: `Object` Default: `{}` -This can be used to pass any additional information regarding the string. +This can be used to pass any additional information regarding the string. #### allowDynamicKeys diff --git a/examples/i18next-scanner.config.js b/examples/i18next-scanner.config.js index 4227489..eb47191 100644 --- a/examples/i18next-scanner.config.js +++ b/examples/i18next-scanner.config.js @@ -11,6 +11,7 @@ module.exports = { ], output: './', options: { + compatibilityJSON: 'v3', debug: true, func: { list: ['i18next.t', 'i18n.t'], diff --git a/src/parser.js b/src/parser.js index ab17cef..0c2a202 100644 --- a/src/parser.js +++ b/src/parser.js @@ -18,11 +18,9 @@ import flattenObjectKeys from './flatten-object-keys'; import nodesToString from './nodes-to-string'; import omitEmptyObject from './omit-empty-object'; -i18next.init({ - compatibilityJSON: 'v3', -}); - const defaults = { + compatibilityJSON: 'v3', // JSON format + debug: false, // verbose logging sort: false, // sort keys in alphabetical order @@ -224,32 +222,6 @@ const normalizeOptions = (options) => { return options; }; -// Get an array of plural suffixes for a given language. -// @param {string} lng The language. -// @param {string} pluralSeparator pluralSeparator, default '_'. -// @return {array} An array of plural suffixes. -const getPluralSuffixes = (lng, pluralSeparator = '_') => { - const rule = i18next.services.pluralResolver.getRule(lng); - - if (!(rule && rule.numbers)) { - return []; // Return an empty array if lng is not supported - } - - if (rule.numbers.length === 1) { - return [`${pluralSeparator}0`]; - } - - if (rule.numbers.length === 2) { - return ['', `${pluralSeparator}plural`]; - } - - const suffixes = rule.numbers.reduce((acc, n, i) => { - return acc.concat(`${pluralSeparator}${i}`); - }, []); - - return suffixes; -}; - /** * Creates a new parser * @constructor @@ -272,6 +244,12 @@ class Parser { ...options }); + const i18nextInstance = i18next.createInstance(); + i18nextInstance.init({ + compatibilityJSON: this.options.compatibilityJSON, + pluralSeparator: this.options.pluralSeparator, + }); + const lngs = this.options.lngs; const namespaces = this.options.ns; @@ -279,7 +257,8 @@ class Parser { this.resStore[lng] = this.resStore[lng] || {}; this.resScan[lng] = this.resScan[lng] || {}; - this.pluralSuffixes[lng] = ensureArray(getPluralSuffixes(lng, this.options.pluralSeparator)); + this.pluralSuffixes[lng] = i18nextInstance.services.pluralResolver.getSuffixes(lng); + if (this.pluralSuffixes[lng].length === 0) { this.log(`No plural rule found for: ${lng}`); } diff --git a/test/parser.test.js b/test/parser.test.js index 31abb4b..8e7295c 100644 --- a/test/parser.test.js +++ b/test/parser.test.js @@ -791,6 +791,33 @@ describe('Plural', () => { }); }); + test('compatibilityJSON', () => { + const parser = new Parser({ + compatibilityJSON: 'v4', + lngs: ['en'], + }); + const content = fs.readFileSync(path.resolve(__dirname, 'fixtures/plural.js'), 'utf-8'); + parser.parseFuncFromString(content, { propsFilter: props => props }); + expect(parser.get()).toEqual({ + en: { + translation: { + 'key_one': '', + 'key_other': '', + 'keyWithCount_one': '', + 'keyWithCount_other': '', + 'keyWithVariable_one': '', + 'keyWithVariable_other': '', + 'keyWithCountAndDefaultValues_one': '{{count}} item', + 'keyWithCountAndDefaultValues_other': '{{count}} item', + 'keyWithDefaultValueAndCount_one': '{{count}} item', + 'keyWithDefaultValueAndCount_other': '{{count}} item', + 'keyWithDefaultValueAndVariable_one': '{{count}} item', + 'keyWithDefaultValueAndVariable_other': '{{count}} item', + } + } + }); + }); + test('User defined function', () => { const parser = new Parser({ plural: (lng, ns, key, options) => {