aboutsummaryrefslogtreecommitdiff
path: root/node_modules/gettext-parser/lib/pocompiler.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/gettext-parser/lib/pocompiler.js')
-rw-r--r--node_modules/gettext-parser/lib/pocompiler.js225
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