Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

react-intl-po

Package Overview
Dependencies
Maintainers
1
Versions
20
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-intl-po - npm Package Compare versions

Comparing version 2.1.0 to 2.1.1

lib/utils/po2jsonHelper.js

9

CHANGELOG.md

@@ -6,2 +6,11 @@ # react-intl-po

## [v2.1.1]
> Jul 19, 2017
* chore(env): add node 8 to travisCI & switch to yarn
* chore(dev): introduce prettier & switch from eslint-config-m to airbnb-base
* chore(test): upgrade Jest to 20
* refactor(ramda): switch from lodash to ramda.js
* fix(context): missing the `messageContext` arguments for extractAndWritePOTFromMessagesSync function.
## [v2.1.0]

@@ -8,0 +17,0 @@ > Jul 17, 2017

22

lib/extractAndWritePOTFromMessagesSync.js

@@ -9,3 +9,2 @@ 'use strict';

var _fs = require('fs');

@@ -19,5 +18,5 @@

var _flowRight = require('lodash/flowRight');
var _ramda = require('ramda');
var _flowRight2 = _interopRequireDefault(_flowRight);
var _ramda2 = _interopRequireDefault(_ramda);

@@ -41,15 +40,20 @@ var _readAllMessageAsObjectSync = require('./readAllMessageAsObjectSync');

messageKey = _ref$messageKey === undefined ? 'defaultMessage' : _ref$messageKey,
_ref$messageContext = _ref.messageContext,
messageContext = _ref$messageContext === undefined ? '' : _ref$messageContext,
output = _ref.output,
headerOptions = _ref.headerOptions;
var result = (0, _potHeader2.default)(_extends({
var result = _ramda2.default.pipe(_readAllMessageAsObjectSync2.default,
// 1. Object { messagekey: { messageContext: [[] , []] } }
_potFormater2.default,
// 2. String: pot formated
_ramda2.default.concat((0, _potHeader2.default)(_extends({
potCreationDate: new Date(),
charset: 'UTF-8',
encoding: '8bit'
}, headerOptions));
}, headerOptions)))
// 3. String: with pot head
)(srcPatterns, messageKey, messageContext);
result += (0, _flowRight2.default)(_potFormater2.default, // 2. return formated string
_readAllMessageAsObjectSync2.default // 1. return messages object
)(srcPatterns, messageKey);
// Output
_fs2.default.writeFileSync(output, result);

@@ -56,0 +60,0 @@ console.log(_chalk2.default.green('> [react-intl-po] write file -> ' + output + ' \u2714\uFE0F\n'));

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

var _ramda = require('ramda');
var _ramda2 = _interopRequireDefault(_ramda);
var _chalk = require('chalk');

@@ -24,18 +28,2 @@

var _values = require('lodash/values');
var _values2 = _interopRequireDefault(_values);
var _flattenDeep = require('lodash/flattenDeep');
var _flattenDeep2 = _interopRequireDefault(_flattenDeep);
var _flowRight = require('lodash/flowRight');
var _flowRight2 = _interopRequireDefault(_flowRight);
var _toObjectBy = require('to-object-by');
var _toObjectBy2 = _interopRequireDefault(_toObjectBy);
var _readAllMessageAsObjectSync = require('./readAllMessageAsObjectSync');

@@ -53,3 +41,2 @@

var isAJSONFile = function isAJSONFile(string) {

@@ -60,4 +47,6 @@ return (/.json/.test(string)

var getTranslationTableContext = function getTranslationTableContext(messageContext, message) {
return messageContext ? message[messageContext] + '\x04' : '';
var getContext = function getContext(messageContext) {
return function (message) {
return messageContext ? message[messageContext] + '\x04' : '';
};
};

@@ -73,20 +62,31 @@

var translationTable = (0, _readAllPOAsObjectSync2.default)(srcPatterns);
var messageList = (0, _flowRight2.default)(_flattenDeep2.default, // 4. return flattened values
function (objects) {
return objects.map(function (o) {
return (0, // 3. return values
_values2.default)(o);
});
}, _values2.default, // 2. return context objects
_readAllMessageAsObjectSync2.default // 1. return message object
var placeholder = _ramda2.default.pipe(_readAllMessageAsObjectSync2.default,
// 1. Object { messagekey: { messageContext: [[] , []] } }
_ramda2.default.values,
// 2. Array [{ messageContext: [[], []] }]
_ramda2.default.map(_ramda2.default.values),
// 3. Array [[], []]
_ramda2.default.flatten,
// 4. Array []
_ramda2.default.indexBy(_ramda2.default.prop('id')),
// 5. Object { id: [] }
_ramda2.default.mapObjIndexed(_ramda2.default.converge(_ramda2.default.concat, [getContext(messageContext), _ramda2.default.prop(messageKey)]))
// 6. Object { id: key }, key = (messageContext + messagekey)
)(messagesPattern, messageKey, messageContext);
var locales = Object.keys(translationTable);
var result = (0, _toObjectBy2.default)(locales, function (locale) {
return _defineProperty({}, locale, (0, _toObjectBy2.default)(messageList, function (message) {
return _defineProperty({}, message.id, translationTable[locale]['' + getTranslationTableContext(messageContext, message) + message[messageKey]]);
}));
});
var result = _ramda2.default.pipe(_readAllPOAsObjectSync2.default,
// 1. Object { locale: { key: '' } }
function (translation) {
return Object.keys(translation).map(function (locale) {
return _defineProperty({}, locale, _ramda2.default.mapObjIndexed(function (k) {
return translation[locale][k] || '';
})(placeholder));
});
},
// 2. Array [{ locale: { id: '' } }], replace key to translated string
_ramda2.default.mergeAll
// 3. Object { locale: { id: '' } }
)(srcPatterns);
// Output
if (isAJSONFile(output)) {

@@ -99,6 +99,5 @@ _mkdirp2.default.sync(_path2.default.dirname(output)); // ensure the output folder exists

Object.keys(result).map(function (lang) {
Object.keys(result).forEach(function (lang) {
_fs2.default.writeFileSync(_path2.default.join(output, lang + '.json'), JSON.stringify(result[lang], null, 0));
console.log(_chalk2.default.green('> [react-intl-po] write file -> ' + _path2.default.join(output, lang + '.json') + ' \u2714\uFE0F'));
return null;
});

@@ -105,0 +104,0 @@ }

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

});
var _ramda = require('ramda');
var _ramda2 = _interopRequireDefault(_ramda);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**

@@ -26,34 +33,21 @@ * Create a POT header string

var header = '';
if (options.comments) {
var comments = options.comments;
if (!Array.isArray(options.comments)) {
comments = [options.comments];
var o = _ramda2.default.evolve({
comments: _ramda2.default.pipe(_ramda2.default.cond([[_ramda2.default.is(Array), _ramda2.default.identity], [_ramda2.default.is(String), _ramda2.default.of]]), _ramda2.default.map(_ramda2.default.split('\n')), _ramda2.default.flatten, _ramda2.default.map(function (e) {
return '# ' + e;
}), _ramda2.default.join('\n')),
projectIdVersion: function projectIdVersion(e) {
return '"Project-Id-Version: ' + e + '\\n"';
},
potCreationDate: function potCreationDate(e) {
return '"POT-Creation-Date: ' + e.toISOString() + '\\n"';
},
charset: function charset(e) {
return '"Content-Type: text/plain; charset=' + e + '\\n"';
},
encoding: function encoding(e) {
return '"Content-Transfer-Encoding: ' + e + '\\n"';
}
comments = comments.reduce(function (o, n) {
return o.concat(n.split('\n'));
}, []);
header += comments.map(function (comment) {
return '# ' + comment;
}).join('\n') + '\n';
}
header += 'msgid ""\nmsgstr ""\n';
})(options);
if (options.projectIdVersion) {
header += '"Project-Id-Version: ' + options.projectIdVersion + '\\n"\n';
}
if (options.potCreationDate) {
header += '"POT-Creation-Date: ' + options.potCreationDate.toISOString() + '\\n"\n';
}
if (options.charset) {
header += '"Content-Type: text/plain; charset=' + options.charset + '\\n"\n';
}
if (options.encoding) {
header += '"Content-Transfer-Encoding: ' + options.encoding + '\\n"\n';
}
header += '"MIME-Version: 1.0\\n"\n';
header += '"X-Generator: react-intl-po\\n"\n';
header += '\n\n';
return header;
return (o.comments + '\nmsgid ""\nmsgstr ""\n' + o.projectIdVersion + '\n' + o.potCreationDate + '\n' + o.charset + '\n' + o.encoding + '\n"MIME-Version: 1.0\\n"\n"X-Generator: react-intl-po\\n"\n\n\n').replace(/undefined\r?\n|\r/g, '');
};

@@ -60,0 +54,0 @@

@@ -15,35 +15,8 @@ 'use strict';

var _mergeWith2 = require('lodash/mergeWith');
var _ramda = require('ramda');
var _mergeWith3 = _interopRequireDefault(_mergeWith2);
var _ramda2 = _interopRequireDefault(_ramda);
var _isArray = require('lodash/isArray');
var _isArray2 = _interopRequireDefault(_isArray);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
var concatCustomizer = function concatCustomizer(accValue, objectValue) {
if (!(0, _isArray2.default)(accValue)) return objectValue;
return accValue.concat(objectValue);
};
var mergeCustomizer = function mergeCustomizer(accValue, objectValue) {
return (0, _mergeWith3.default)(accValue, objectValue, concatCustomizer);
};
// hint: Use defaultMessage as key by default
var indexBy = function indexBy(messageKey, messageContext) {
return function (_ref) {
var messages = _ref.messages,
filename = _ref.filename;
return messages.reduce(function (acc, message) {
return _extends({}, acc, _defineProperty({}, message[messageKey], (0, _mergeWith3.default)(acc[message[messageKey]], _defineProperty({}, messageContext ? message[messageContext] : '', [_extends({}, message, { filename: filename })]), concatCustomizer)));
}, {});
};
};
/**

@@ -55,2 +28,3 @@ * Read extracted .json file synchronized and

* @param {String} messageKey - [defaultMessage]
* @param {String} messageContext - [''] empty string
* @return {Object} messages - return aggregates object

@@ -61,20 +35,24 @@ *

function readAllMessageAsObjectSync(srcPatterns) {
var readAllMessageAsObjectSync = function readAllMessageAsObjectSync(srcPatterns) {
var messageKey = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'defaultMessage';
var messageContext = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';
return _ramda2.default.pipe(_glob.sync,
// 1. Array [filename, ...]
_ramda2.default.map(function (filename) {
return JSON.parse(_fs2.default.readFileSync(filename, 'utf8')).map(function (e) {
return _extends({}, e, {
filename: filename
});
});
}), _ramda2.default.flatten,
// 2. Array [{ ...messages, filename }, ... ]
_ramda2.default.groupBy(_ramda2.default.prop(messageKey)),
// 3. Object { messageKey: { }, ... }
_ramda2.default.mapObjIndexed(_ramda2.default.groupBy(_ramda2.default.propOr(messageContext, messageContext)))
// 4. Object { messagekey: { messageContext: { } } }
// 4. groupBy context (nested for -c argument)
)(srcPatterns);
};
return (0, _glob.sync)(srcPatterns)
// 1. read messages
.map(function (filename) {
return { filename: filename, messages: JSON.parse(_fs2.default.readFileSync(filename, 'utf8')) };
})
// 2. convert message list to nested objects by messageKey and messageContext
.map(indexBy(messageKey, messageContext))
// 3. aggregate objects (merge and concat)
.reduce(function (acc, object) {
return (0, _mergeWith3.default)(acc, object, mergeCustomizer);
}, {});
}
exports.default = readAllMessageAsObjectSync;
module.exports = exports['default'];

@@ -14,18 +14,12 @@ 'use strict';

var _po2json = require('po2json');
var _ramda = require('ramda');
var _po2json2 = _interopRequireDefault(_po2json);
var _ramda2 = _interopRequireDefault(_ramda);
var _mapValues = require('lodash/mapValues');
var _po2jsonHelper = require('./utils/po2jsonHelper');
var _mapValues2 = _interopRequireDefault(_mapValues);
var _po2jsonHelper2 = _interopRequireDefault(_po2jsonHelper);
var _toObjectBy = require('to-object-by');
var _toObjectBy2 = _interopRequireDefault(_toObjectBy);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
var DEFAULT_MAPPER = exports.DEFAULT_MAPPER = function DEFAULT_MAPPER(filepath) {

@@ -38,25 +32,17 @@ return _path2.default.basename(filepath).match(/([^.]*\.)*([^.]+)\.po$/)[2];

* aggregates translated messages object
*
* @param {String} srcPatterns - path to translated .po file
* @return {Object} po - return aggregates object
*
* @author Michael Hsu
*/
function readAllPOAsObjectSync(srcPatterns) {
var readAllPOAsObjectSync = function readAllPOAsObjectSync(srcPatterns) {
var localeMapper = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : DEFAULT_MAPPER;
return _ramda2.default.pipe(_glob.sync,
// 1. Array [filename, ...]
_ramda2.default.map(_ramda2.default.converge(_ramda2.default.objOf, [localeMapper, _po2jsonHelper2.default.parseFileSync])),
// 2. Array [{ locale: json }, ...]
_ramda2.default.mergeAll
// 3. Object { locale: json }
)(srcPatterns);
};
var filepaths = (0, _glob.sync)(srcPatterns);
return (0, _toObjectBy2.default)(filepaths, function (filepath) {
var json = _po2json2.default.parseFileSync(filepath);
var translated = (0, _mapValues2.default)(json, function (o) {
return o[1];
}); // omit plural
var locale = localeMapper(filepath); // parse locale name
return _defineProperty({}, locale, translated);
});
}
exports.default = readAllPOAsObjectSync;
{
"name": "react-intl-po",
"version": "2.1.0",
"version": "2.1.1",
"description": "Extract POT from react-intl and convert back to json.",

@@ -39,22 +39,24 @@ "author": "Michael Hsu",

"codecov": "codecov",
"lint:js": "eslint --ignore-path .gitignore .",
"lint": "npm run lint:js",
"prepublish": "npm run build"
"prepublish": "npm run build",
"eslint": "eslint --ignore-path .gitignore .",
"format": "prettier --trailing-comma all --single-quote --write '{src,test,config}/**/*.js'"
},
"devDependencies": {
"babel-cli": "^6.18.0",
"babel-cli": "^6.24.1",
"babel-eslint": "^7.2.3",
"babel-plugin-add-module-exports": "^0.2.1",
"babel-preset-es2015": "^6.18.0",
"babel-preset-react": "^6.16.0",
"babel-preset-stage-0": "^6.16.0",
"babel-register": "^6.18.0",
"codecov": "^2.1.0",
"eslint": "^3.13.0",
"jest": "^19.0.2",
"lint-config-m": "^3.1.0",
"stylelint": "^7.7.1"
"babel-preset-es2015": "^6.24.1",
"babel-preset-stage-0": "^6.24.1",
"codecov": "^2.2.0",
"eslint": "^3.19.0",
"eslint-config-airbnb-base": "^11.2.0",
"eslint-config-prettier": "^2.3.0",
"eslint-plugin-import": "^2.7.0",
"eslint-plugin-jest": "^20.0.3",
"eslint-plugin-prettier": "^2.1.2",
"jest": "^20.0.4",
"prettier": "^1.5.3"
},
"babel": {
"presets": [
"react",
"es2015",

@@ -74,19 +76,41 @@ "stage-0"

"snapshotSerializers": [
"./config/stringSerializer.js"
"./config/stringSerializer.js",
"./config/jsonSerializer.js"
]
},
"eslintConfig": {
"parser": "babel-eslint",
"extends": [
"./node_modules/lint-config-m/eslint.js"
]
"eslint-config-airbnb-base",
"eslint-config-airbnb-base/rules/strict",
"prettier",
"prettier/flowtype",
"plugin:jest/recommended"
],
"plugins": [
"prettier",
"jest"
],
"env": {
"jest/globals": true
},
"rules": {
"import/no-extraneous-dependencies": 0,
"prettier/prettier": [
"error",
{
"singleQuote": true,
"trailingComma": "all"
}
]
}
},
"dependencies": {
"chalk": "^1.1.3",
"commander": "^2.9.0",
"glob": "^7.1.1",
"lodash": "^4.17.4",
"chalk": "^2.0.1",
"commander": "^2.11.0",
"glob": "^7.1.2",
"mkdirp": "^0.5.1",
"po2json": "^0.4.5",
"to-object-by": "^1.1.0"
"ramda": "^0.24.1"
}
}

@@ -11,2 +11,4 @@ # react-intl-po

[![prettier](https://img.shields.io/badge/styled_with-prettier-ff69b4.svg)](https://github.com/prettier/prettier)
[build-badge]: https://img.shields.io/travis/evenchange4/react-intl-po/master.svg?style=flat-square

@@ -41,2 +43,4 @@ [build]: https://travis-ci.org/evenchange4/react-intl-po

```console
$ yarn add react-intl-po
# or
$ npm install react-intl-po --save

@@ -100,8 +104,2 @@ ```

## API
```
```
## Property

@@ -145,9 +143,34 @@

## Test
## Development
```console
$ yarn install --pure-lockfile
```
$ npm run lint
$ npm run test:watch
### Ramda.js
You can use `R.tap()` for developing.
```diff
R.pipe(
R.concat(...),
+ R.tap(e => console.log(e)),
R.mergeAll,
);
```
### Requirements
- node >= 8.1.4
- npm >= 5.0.3
- yarn >= 0.27.5
### Test
```
$ yarn run format
$ yarn run eslint
$ yarn run test:watch
```
---

@@ -159,3 +182,3 @@

* For bugs and feature requests, please create an issue.
* Pull requests must be accompanied by passing automated tests (`$ npm test`).
* Pull requests must be accompanied by passing automated tests (`$ yarn run test`).

@@ -162,0 +185,0 @@ ## [CHANGELOG](CHANGELOG.md)

@@ -7,5 +7,14 @@ #!/usr/bin/env node

.command('json2pot <srcPatterns>')
.option('-o, --output <path>', 'The output pathname of `.pot` file to be translated')
.option('-k, --message-key [key]', 'Translation message key (default key is `defaultMessage`)')
.option('-c, --message-context [context]', 'Translation message context (defaults to no context)')
.option(
'-o, --output <path>',
'The output pathname of `.pot` file to be translated',
)
.option(
'-k, --message-key [key]',
'Translation message key (default key is `defaultMessage`)',
)
.option(
'-c, --message-context [context]',
'Translation message context (defaults to no context)',
)
.action(require('./extractAndWritePOTFromMessagesSync'));

@@ -20,6 +29,12 @@

.option('-o, --output <path>', 'The output pathname of a file / directory')
.option('-k, --message-key [key]', 'Translation message key (default key is `defaultMessage`)')
.option('-c, --message-context [context]', 'Translation message context (defaults to no context)')
.option(
'-k, --message-key [key]',
'Translation message key (default key is `defaultMessage`)',
)
.option(
'-c, --message-context [context]',
'Translation message context (defaults to no context)',
)
.action(require('./filterPOAndWriteTranslateSync'));
program.parse(process.argv);
/* eslint-disable no-console */
import fs from 'fs';
import chalk from 'chalk';
import flowRight from 'lodash/flowRight';
import R from 'ramda';
import readAllMessageAsObjectSync from './readAllMessageAsObjectSync';

@@ -9,16 +10,23 @@ import potFormater from './potFormater';

function extractAndWritePOTFromMessagesSync(srcPatterns,
{ messageKey = 'defaultMessage', output, headerOptions }) {
let result = potHeader({
potCreationDate: new Date(),
charset: 'UTF-8',
encoding: '8bit',
...headerOptions,
});
function extractAndWritePOTFromMessagesSync(
srcPatterns,
{ messageKey = 'defaultMessage', messageContext = '', output, headerOptions },
) {
const result = R.pipe(
readAllMessageAsObjectSync,
// 1. Object { messagekey: { messageContext: [[] , []] } }
potFormater,
// 2. String: pot formated
R.concat(
potHeader({
potCreationDate: new Date(),
charset: 'UTF-8',
encoding: '8bit',
...headerOptions,
}),
),
// 3. String: with pot head
)(srcPatterns, messageKey, messageContext);
result += flowRight(
potFormater, // 2. return formated string
readAllMessageAsObjectSync, // 1. return messages object
)(srcPatterns, messageKey);
// Output
fs.writeFileSync(output, result);

@@ -25,0 +33,0 @@ console.log(chalk.green(`> [react-intl-po] write file -> ${output} ✔️\n`));

/* eslint-disable no-console */
import fs from 'fs';
import path from 'path';
import mkdirp from 'mkdirp';
import R from 'ramda';
import chalk from 'chalk';
import values from 'lodash/values';
import flattenDeep from 'lodash/flattenDeep';
import flowRight from 'lodash/flowRight';
import toObjectBy from 'to-object-by';
import readAllMessageAsObjectSync from './readAllMessageAsObjectSync';

@@ -15,22 +13,46 @@ import readAllPOAsObjectSync from './readAllPOAsObjectSync';

const getTranslationTableContext = (messageContext, message) =>
(messageContext ? `${message[messageContext]}\u0004` : '');
const getContext = messageContext => message =>
messageContext ? `${message[messageContext]}\u0004` : '';
function filterPOAndWriteTranslateSync(srcPatterns,
{ messageKey = 'defaultMessage', messageContext = '', messagesPattern, output }) {
const translationTable = readAllPOAsObjectSync(srcPatterns);
const messageList = flowRight(
flattenDeep, // 4. return flattened values
objects => objects.map(o => values(o)), // 3. return values
values, // 2. return context objects
readAllMessageAsObjectSync, // 1. return message object
function filterPOAndWriteTranslateSync(
srcPatterns,
{
messageKey = 'defaultMessage',
messageContext = '',
messagesPattern,
output,
},
) {
const placeholder = R.pipe(
readAllMessageAsObjectSync,
// 1. Object { messagekey: { messageContext: [[] , []] } }
R.values,
// 2. Array [{ messageContext: [[], []] }]
R.map(R.values),
// 3. Array [[], []]
R.flatten,
// 4. Array []
R.indexBy(R.prop('id')),
// 5. Object { id: [] }
R.mapObjIndexed(
R.converge(R.concat, [getContext(messageContext), R.prop(messageKey)]),
),
// 6. Object { id: key }, key = (messageContext + messagekey)
)(messagesPattern, messageKey, messageContext);
const locales = Object.keys(translationTable);
const result = toObjectBy(locales, locale => ({
[locale]: toObjectBy(messageList, message => ({
[message.id]: translationTable[locale][`${getTranslationTableContext(messageContext, message)}${message[messageKey]}`],
})),
}));
const result = R.pipe(
readAllPOAsObjectSync,
// 1. Object { locale: { key: '' } }
translation =>
Object.keys(translation).map(locale => ({
[locale]: R.mapObjIndexed(k => translation[locale][k] || '')(
placeholder,
),
})),
// 2. Array [{ locale: { id: '' } }], replace key to translated string
R.mergeAll,
// 3. Object { locale: { id: '' } }
)(srcPatterns);
// Output
if (isAJSONFile(output)) {

@@ -43,7 +65,15 @@ mkdirp.sync(path.dirname(output)); // ensure the output folder exists

Object.keys(result).map((lang) => {
fs.writeFileSync(path.join(output, `${lang}.json`), JSON.stringify(result[lang], null, 0));
console.log(chalk.green(
`> [react-intl-po] write file -> ${path.join(output, `${lang}.json`)} ✔️`));
return null;
Object.keys(result).forEach(lang => {
fs.writeFileSync(
path.join(output, `${lang}.json`),
JSON.stringify(result[lang], null, 0),
);
console.log(
chalk.green(
`> [react-intl-po] write file -> ${path.join(
output,
`${lang}.json`,
)} ✔️`,
),
);
});

@@ -50,0 +80,0 @@ }

@@ -23,3 +23,2 @@ /**

/**

@@ -44,3 +43,6 @@ * Formatting POT comments

}
out += potCommentMultiLineWrapper('#.', `defaultMessage is:\n${defaultMessage}`);
out += potCommentMultiLineWrapper(
'#.',
`defaultMessage is:\n${defaultMessage}`,
);

@@ -58,3 +60,3 @@ return out;

const potContextsFormater = messageContext =>
(messageContext ? `msgctxt ${JSON.stringify(messageContext)}\n` : '');
messageContext ? `msgctxt ${JSON.stringify(messageContext)}\n` : '';

@@ -76,4 +78,11 @@ /**

Object.keys(messageObject[id])
.map(context => `${potCommentsFormater(messageObject[id][context])}${potContextsFormater(context)}msgid ${JSON.stringify(id)}\nmsgstr ""\n`)
.join('\n'),
.map(
context =>
`${potCommentsFormater(
messageObject[id][context],
)}${potContextsFormater(context)}msgid ${JSON.stringify(
id,
)}\nmsgstr ""\n`,
)
.join('\n'),
)

@@ -80,0 +89,0 @@ .join('\n');

@@ -0,1 +1,3 @@

import R from 'ramda';
/**

@@ -18,32 +20,30 @@ * Create a POT header string

const potHeader = (options = {}) => {
let header = '';
const o = R.evolve({
comments: R.pipe(
R.cond([[R.is(Array), R.identity], [R.is(String), R.of]]),
R.map(R.split('\n')),
R.flatten,
R.map(e => `# ${e}`),
R.join('\n'),
),
projectIdVersion: e => `"Project-Id-Version: ${e}\\n"`,
potCreationDate: e => `"POT-Creation-Date: ${e.toISOString()}\\n"`,
charset: e => `"Content-Type: text/plain; charset=${e}\\n"`,
encoding: e => `"Content-Transfer-Encoding: ${e}\\n"`,
})(options);
if (options.comments) {
let comments = options.comments;
if (!Array.isArray(options.comments)) {
comments = [options.comments];
}
comments = comments.reduce((o, n) => o.concat(n.split('\n')), []);
header += `${comments.map(comment => `# ${comment}`).join('\n')}\n`;
}
header += 'msgid ""\nmsgstr ""\n';
return `${o.comments}
msgid ""
msgstr ""
${o.projectIdVersion}
${o.potCreationDate}
${o.charset}
${o.encoding}
"MIME-Version: 1.0\\n"
"X-Generator: react-intl-po\\n"
if (options.projectIdVersion) {
header += `"Project-Id-Version: ${options.projectIdVersion}\\n"\n`;
}
if (options.potCreationDate) {
header += `"POT-Creation-Date: ${options.potCreationDate.toISOString()}\\n"\n`;
}
if (options.charset) {
header += `"Content-Type: text/plain; charset=${options.charset}\\n"\n`;
}
if (options.encoding) {
header += `"Content-Transfer-Encoding: ${options.encoding}\\n"\n`;
}
header += '"MIME-Version: 1.0\\n"\n';
header += '"X-Generator: react-intl-po\\n"\n';
header += '\n\n';
return header;
`.replace(/undefined\r?\n|\r/g, '');
};
export default potHeader;
import fs from 'fs';
import { sync as globSync } from 'glob';
import mergeWith from 'lodash/mergeWith';
import isArray from 'lodash/isArray';
import R from 'ramda';
const concatCustomizer = (accValue, objectValue) => {
if (!isArray(accValue)) return objectValue;
return accValue.concat(objectValue);
};
const mergeCustomizer = (accValue, objectValue) =>
mergeWith(accValue, objectValue, concatCustomizer);
// hint: Use defaultMessage as key by default
const indexBy = (messageKey, messageContext) => ({ messages, filename }) =>
messages.reduce((acc, message) => ({
...acc,
[message[messageKey]]: mergeWith(
acc[message[messageKey]],
{ [messageContext ? message[messageContext] : '']: [{ ...message, filename }]},
concatCustomizer,
),
}), {});
/**

@@ -32,2 +11,3 @@ * Read extracted .json file synchronized and

* @param {String} messageKey - [defaultMessage]
* @param {String} messageContext - [''] empty string
* @return {Object} messages - return aggregates object

@@ -38,12 +18,25 @@ *

function readAllMessageAsObjectSync(srcPatterns, messageKey = 'defaultMessage', messageContext = '') {
return globSync(srcPatterns)
// 1. read messages
.map(filename => ({ filename, messages: JSON.parse(fs.readFileSync(filename, 'utf8')) }))
// 2. convert message list to nested objects by messageKey and messageContext
.map(indexBy(messageKey, messageContext))
// 3. aggregate objects (merge and concat)
.reduce((acc, object) => mergeWith(acc, object, mergeCustomizer), {});
}
const readAllMessageAsObjectSync = (
srcPatterns,
messageKey = 'defaultMessage',
messageContext = '',
) =>
R.pipe(
globSync,
// 1. Array [filename, ...]
R.map(filename =>
JSON.parse(fs.readFileSync(filename, 'utf8')).map(e => ({
...e,
filename,
})),
),
R.flatten,
// 2. Array [{ ...messages, filename }, ... ]
R.groupBy(R.prop(messageKey)),
// 3. Object { messageKey: { }, ... }
R.mapObjIndexed(R.groupBy(R.propOr(messageContext, messageContext))),
// 4. Object { messagekey: { messageContext: { } } }
// 4. groupBy context (nested for -c argument)
)(srcPatterns);
export default readAllMessageAsObjectSync;
import { sync as globSync } from 'glob';
import path from 'path';
import po2json from 'po2json';
import mapValues from 'lodash/mapValues';
import toObjectBy from 'to-object-by';
import R from 'ramda';
import po2jsonHelper from './utils/po2jsonHelper';

@@ -13,23 +12,16 @@ export const DEFAULT_MAPPER = filepath =>

* aggregates translated messages object
*
* @param {String} srcPatterns - path to translated .po file
* @return {Object} po - return aggregates object
*
* @author Michael Hsu
*/
function readAllPOAsObjectSync(srcPatterns, localeMapper = DEFAULT_MAPPER) {
const filepaths = globSync(srcPatterns);
const readAllPOAsObjectSync = (srcPatterns, localeMapper = DEFAULT_MAPPER) =>
R.pipe(
globSync,
// 1. Array [filename, ...]
R.map(R.converge(R.objOf, [localeMapper, po2jsonHelper.parseFileSync])),
// 2. Array [{ locale: json }, ...]
R.mergeAll,
// 3. Object { locale: json }
)(srcPatterns);
return toObjectBy(filepaths, (filepath) => {
const json = po2json.parseFileSync(filepath);
const translated = mapValues(json, o => o[1]); // omit plural
const locale = localeMapper(filepath); // parse locale name
return {
[locale]: translated,
};
});
}
export default readAllPOAsObjectSync;

@@ -10,5 +10,10 @@ import fs from 'fs';

const output = './test/temp/extract-defaultMessage.pot';
const headerOptions = { potCreationDate: new Date(Date.UTC(2017, 1, 1, 11, 23, 12)) };
const headerOptions = {
potCreationDate: new Date(Date.UTC(2017, 1, 1, 11, 23, 12)),
};
extractAndWritePOTFromMessagesSync('./test/messages/**/*.json', { output, headerOptions });
extractAndWritePOTFromMessagesSync('./test/messages/**/*.json', {
output,
headerOptions,
});
expect(fs.readFileSync(output, 'utf8')).toMatchSnapshot();

@@ -19,6 +24,26 @@ });

const output = './test/temp/extract-id.pot';
const headerOptions = { potCreationDate: new Date(Date.UTC(2017, 1, 1, 11, 23, 12)) };
const headerOptions = {
potCreationDate: new Date(Date.UTC(2017, 1, 1, 11, 23, 12)),
};
extractAndWritePOTFromMessagesSync('./test/messages/**/*.json', { messageKey: 'id', output, headerOptions });
extractAndWritePOTFromMessagesSync('./test/messages/**/*.json', {
messageKey: 'id',
output,
headerOptions,
});
expect(fs.readFileSync(output, 'utf8')).toMatchSnapshot();
});
it('should return messages object with messageContext', () => {
const output = './test/temp/extract-messageContext.pot';
const headerOptions = {
potCreationDate: new Date(Date.UTC(2017, 1, 1, 11, 23, 12)),
};
extractAndWritePOTFromMessagesSync('./test/messages/**/*.json', {
output,
headerOptions,
messageContext: 'id',
});
expect(fs.readFileSync(output, 'utf8')).toMatchSnapshot();
});

@@ -12,3 +12,6 @@ import fs from 'fs';

filterPOAndWriteTranslateSync('./test/po/mcs-public.*.po', { messagesPattern, output });
filterPOAndWriteTranslateSync('./test/po/mcs-public.*.po', {
messagesPattern,
output,
});
expect(JSON.parse(fs.readFileSync(output, 'utf8'))).toMatchSnapshot();

@@ -21,5 +24,12 @@ });

filterPOAndWriteTranslateSync('./test/po/mcs-public.*.po', { messagesPattern, output });
expect(JSON.parse(fs.readFileSync(`${output}/zh-CN.json`, 'utf8'))).toMatchSnapshot();
expect(JSON.parse(fs.readFileSync(`${output}/zh-TW.json`, 'utf8'))).toMatchSnapshot();
filterPOAndWriteTranslateSync('./test/po/mcs-public.*.po', {
messagesPattern,
output,
});
expect(
JSON.parse(fs.readFileSync(`${output}/zh-CN.json`, 'utf8')),
).toMatchSnapshot();
expect(
JSON.parse(fs.readFileSync(`${output}/zh-TW.json`, 'utf8')),
).toMatchSnapshot();
});

@@ -31,3 +41,7 @@

filterPOAndWriteTranslateSync('./test/po/mcs-id.*.po', { messageKey: 'id', messagesPattern, output });
filterPOAndWriteTranslateSync('./test/po/mcs-id.*.po', {
messageKey: 'id',
messagesPattern,
output,
});
expect(JSON.parse(fs.readFileSync(output, 'utf8'))).toMatchSnapshot();

@@ -40,4 +54,8 @@ });

filterPOAndWriteTranslateSync('./test/po/mcs-ctxt.*.po', { messageContext: 'id', messagesPattern, output });
filterPOAndWriteTranslateSync('./test/po/mcs-ctxt.*.po', {
messageContext: 'id',
messagesPattern,
output,
});
expect(JSON.parse(fs.readFileSync(output, 'utf8'))).toMatchSnapshot();
});

@@ -8,11 +8,7 @@ import potHeader from '../src/potHeader';

it('should return pot header, without any parameter', () => {
expect(
potHeader(),
).toMatchSnapshot();
expect(potHeader()).toMatchSnapshot();
});
it('should return pot header, without empty options', () => {
expect(
potHeader({}),
).toMatchSnapshot();
expect(potHeader({})).toMatchSnapshot();
});

@@ -44,3 +40,2 @@

it('should return pot header, with all options', () => {

@@ -47,0 +42,0 @@ expect(

@@ -15,6 +15,3 @@ import readAllMessageAsObjectSync from '../src/readAllMessageAsObjectSync';

expect(
readAllMessageAsObjectSync(
'./test/messages/**/App.json',
'description',
),
readAllMessageAsObjectSync('./test/messages/**/App.json', 'description'),
).toMatchSnapshot();

@@ -25,6 +22,3 @@ });

expect(
readAllMessageAsObjectSync(
'./test/messages/**/*.json',
'id',
),
readAllMessageAsObjectSync('./test/messages/**/*.json', 'id'),
).toMatchSnapshot();

@@ -35,8 +29,4 @@ });

expect(
readAllMessageAsObjectSync(
'./test/messages/**/*.json',
undefined,
'id',
),
readAllMessageAsObjectSync('./test/messages/**/*.json', undefined, 'id'),
).toMatchSnapshot();
});

@@ -14,8 +14,18 @@ import readAllPOAsObjectSync, {

expect(defaultMapper('./node_modules/mcs-translation/po/mcs-public.zh-cn.po')).toBe('zh-cn');
expect(defaultMapper('./node_modules/mcs-translation/po/mcs-public.zh-tw.po')).toBe('zh-tw');
expect(defaultMapper('./node_modules/mcs-translation/po/mcs-public.en.po')).toBe('en');
expect(
defaultMapper('./node_modules/mcs-translation/po/mcs-public.zh-cn.po'),
).toBe('zh-cn');
expect(
defaultMapper('./node_modules/mcs-translation/po/mcs-public.zh-tw.po'),
).toBe('zh-tw');
expect(
defaultMapper('./node_modules/mcs-translation/po/mcs-public.en.po'),
).toBe('en');
expect(defaultMapper('./node_modules/mcs-translation/po/zh-CN.po')).toBe('zh-CN');
expect(defaultMapper('./node_modules/mcs-translation/po/zh-TW.po')).toBe('zh-TW');
expect(defaultMapper('./node_modules/mcs-translation/po/zh-CN.po')).toBe(
'zh-CN',
);
expect(defaultMapper('./node_modules/mcs-translation/po/zh-TW.po')).toBe(
'zh-TW',
);
expect(defaultMapper('./node_modules/mcs-translation/po/en.po')).toBe('en');

@@ -29,5 +39,3 @@

it('should return po object with default localeMapper', () => {
expect(
readAllPOAsObjectSync('./test/po/mcs-public.*.po'),
).toMatchSnapshot();
expect(readAllPOAsObjectSync('./test/po/mcs-public.*.po')).toMatchSnapshot();
});

@@ -34,0 +42,0 @@

@@ -1,1 +0,1 @@

{"zh-CN":{"App.Creator 1":"建立者(簡中1)","App.Creator 2":"建立者(簡中2)"},"zh-TW":{"App.Creator 1":"建立者(繁中1)","App.Creator 2":"建立者(繁中2)"}}
{"zh-CN":{"App.errorMessage":"","App.errorButton":"","NotFound.errorButton":"","App.Creator 1":"建立者(簡中1)","App.Creator 2":"建立者(簡中2)","NotFound.Creator":""},"zh-TW":{"App.errorMessage":"","App.errorButton":"","NotFound.errorButton":"","App.Creator 1":"建立者(繁中1)","App.Creator 2":"建立者(繁中2)","NotFound.Creator":""}}

@@ -1,1 +0,1 @@

{"zh-CN":{"App.Creator 1":"建立者(簡中)","App.Creator 2":"建立者(簡中)","NotFound.Creator":"建立者(簡中)"},"zh-TW":{"App.Creator 1":"建立者","App.Creator 2":"建立者","NotFound.Creator":"建立者"}}
{"zh-CN":{"App.errorMessage":"","App.errorButton":"","NotFound.errorButton":"","App.Creator 1":"建立者(簡中)","App.Creator 2":"建立者(簡中)","NotFound.Creator":"建立者(簡中)"},"zh-TW":{"App.errorMessage":"","App.errorButton":"","NotFound.errorButton":"","App.Creator 1":"建立者","App.Creator 2":"建立者","NotFound.Creator":"建立者"}}

@@ -1,1 +0,1 @@

{"zh-CN":{"App.Creator 1":"建立者(簡中1)","App.Creator 2":"建立者(簡中2)"},"zh-TW":{"App.Creator 1":"建立者(繁中1)","App.Creator 2":"建立者(繁中2)"}}
{"zh-CN":{"App.errorMessage":"","App.errorButton":"","App.Creator 1":"建立者(簡中1)","App.Creator 2":"建立者(簡中2)","NotFound.errorButton":"","NotFound.Creator":""},"zh-TW":{"App.errorMessage":"","App.errorButton":"","App.Creator 1":"建立者(繁中1)","App.Creator 2":"建立者(繁中2)","NotFound.errorButton":"","NotFound.Creator":""}}

@@ -1,1 +0,1 @@

{"App.Creator 1":"建立者(簡中)","App.Creator 2":"建立者(簡中)","NotFound.Creator":"建立者(簡中)"}
{"App.errorMessage":"","App.errorButton":"","NotFound.errorButton":"","App.Creator 1":"建立者(簡中)","App.Creator 2":"建立者(簡中)","NotFound.Creator":"建立者(簡中)"}

@@ -1,1 +0,1 @@

{"App.Creator 1":"建立者","App.Creator 2":"建立者","NotFound.Creator":"建立者"}
{"App.errorMessage":"","App.errorButton":"","NotFound.errorButton":"","App.Creator 1":"建立者","App.Creator 2":"建立者","NotFound.Creator":"建立者"}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

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