diff options
Diffstat (limited to 'node_modules/gettext-parser/lib/pocompiler.js')
-rw-r--r-- | node_modules/gettext-parser/lib/pocompiler.js | 225 |
1 files changed, 225 insertions, 0 deletions
diff --git a/node_modules/gettext-parser/lib/pocompiler.js b/node_modules/gettext-parser/lib/pocompiler.js new file mode 100644 index 000000000..0f3c1a166 --- /dev/null +++ b/node_modules/gettext-parser/lib/pocompiler.js @@ -0,0 +1,225 @@ +'use strict'; + +var encoding = require('encoding'); +var sharedFuncs = require('./shared'); + +/** + * Exposes general compiler function. Takes a translation + * object as a parameter and returns PO object + * + * @param {Object} table Translation object + * @return {Buffer} Compiled PO object + */ +module.exports = function(table) { + var compiler = new Compiler(table); + return compiler.compile(); +}; + +/** + * Creates a PO compiler object. + * + * @constructor + * @param {Object} table Translation table to be compiled + */ +function Compiler(table) { + this._table = table || {}; + this._table.headers = this._table.headers || {}; + this._table.translations = this._table.translations || {}; + this._translations = []; + this._handleCharset(); +} + +/** + * Converts a comments object to a comment string. The comment object is + * in the form of {translator:'', reference: '', extracted: '', flag: '', previous:''} + * + * @param {Object} comments A comments object + * @return {String} A comment string for the PO file + */ +Compiler.prototype._drawComments = function(comments) { + var lines = []; + var types = [{ + key: 'translator', + prefix: '# ' + }, { + key: 'reference', + prefix: '#: ' + }, { + key: 'extracted', + prefix: '#. ' + }, { + key: 'flag', + prefix: '#, ' + }, { + key: 'previous', + prefix: '#| ' + }]; + + types.forEach(function(type) { + if (!comments[type.key]) { + return; + } + comments[type.key].split(/\r?\n|\r/).forEach(function(line) { + lines.push(type.prefix + line); + }); + }); + + return lines.join('\n'); +}; + +/** + * Builds a PO string for a single translation object + * + * @param {Object} block Translation object + * @param {Object} [override] Properties of this object will override `block` properties + * @return {String} Translation string for a single object + */ +Compiler.prototype._drawBlock = function(block, override) { + + override = override || {}; + + var response = [], + comments = override.comments || block.comments, + msgctxt = override.msgctxt || block.msgctxt, + msgid = override.msgid || block.msgid, + msgid_plural = override.msgid_plural || block.msgid_plural, + msgstr = [].concat(override.msgstr || block.msgstr); + + + // add comments + if (comments && (comments = this._drawComments(comments))) { + response.push(comments); + } + + if (msgctxt) { + response.push(this._addPOString('msgctxt', msgctxt)); + } + + response.push(this._addPOString('msgid', msgid || '')); + + if (msgid_plural) { + response.push(this._addPOString('msgid_plural', msgid_plural)); + } + + if (msgstr.length <= 1) { + response.push(this._addPOString('msgstr', msgstr[0] || '')); + } else { + msgstr.forEach((function(msgstr, i) { + response.push(this._addPOString('msgstr[' + i + ']', msgstr || '')); + }).bind(this)); + } + + return response.join('\n'); +}; + +/** + * Escapes and joins a key and a value for the PO string + * + * @param {String} key Key name + * @param {String} value Key value + * @return {String} Joined and escaped key-value pair + */ +Compiler.prototype._addPOString = function(key, value) { + var line; + + key = (key || '').toString(); + + // escape newlines and quotes + value = (value || '').toString(). + replace(/\\/g, '\\\\'). + replace(/"/g, '\\"'). + replace(/\t/g, '\\t'). + replace(/\r/g, '\\r'). + replace(/\n/g, '\\n'); + + var lines = sharedFuncs.foldLine(value); + + if (lines.length < 2) { + return key + ' "' + (lines.shift() || '') + '"'; + } else { + return key + ' ""\n"' + lines.join('"\n"') + '"'; + } + + if (value.match(/\n/)) { + value = value.replace(/\n/g, '\\n\n').replace(/\n$/, ''); + line = ('\n' + value).split('\n').map(function(l) { + return '"' + l + '"'; + }).join('\n'); + } else { + line = '"' + value + '"'; + } + + return key + ' ' + line; +}; + +/** + * Handles header values, replaces or adds (if needed) a charset property + */ +Compiler.prototype._handleCharset = function() { + var parts = (this._table.headers['content-type'] || 'text/plain').split(';'); + var contentType = parts.shift(); + var charset = sharedFuncs.formatCharset(this._table.charset); + var params = []; + + params = parts.map(function(part) { + var parts = part.split('='), + key = parts.shift().trim(), + value = parts.join('='); + + if (key.toLowerCase() === 'charset') { + if (!charset) { + charset = sharedFuncs.formatCharset(value.trim() || 'utf-8'); + } + return 'charset=' + charset; + } + + return part; + }); + + if (!charset) { + charset = this._table.charset || 'utf-8'; + params.push('charset=' + charset); + } + + this._table.charset = charset; + this._table.headers['content-type'] = contentType + '; ' + params.join('; '); + + this._charset = charset; +}; + +/** + * Compiles translation object into a PO object + * + * @return {Buffer} Compiled PO object + */ +Compiler.prototype.compile = function() { + + var response = [], + headerBlock = this._table.translations[''] && this._table.translations[''][''] || {}; + + response.push(this._drawBlock(headerBlock, { + msgstr: sharedFuncs.generateHeader(this._table.headers) + })); + + Object.keys(this._table.translations).forEach((function(msgctxt) { + if (typeof this._table.translations[msgctxt] !== 'object') { + return; + } + Object.keys(this._table.translations[msgctxt]).forEach((function(msgid) { + if (typeof this._table.translations[msgctxt][msgid] !== 'object') { + return; + } + if (msgctxt === '' && msgid === '') { + return; + } + + response.push(this._drawBlock(this._table.translations[msgctxt][msgid])); + }).bind(this)); + }).bind(this)); + + if (this._charset === 'utf-8' || this._charset === 'ascii') { + return new Buffer(response.join('\n\n'), 'utf-8'); + } else { + return encoding.convert(response.join('\n\n'), this._charset); + } +};
\ No newline at end of file |