aboutsummaryrefslogtreecommitdiff
path: root/node_modules/gettext-parser/lib/mocompiler.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/gettext-parser/lib/mocompiler.js')
-rw-r--r--node_modules/gettext-parser/lib/mocompiler.js237
1 files changed, 237 insertions, 0 deletions
diff --git a/node_modules/gettext-parser/lib/mocompiler.js b/node_modules/gettext-parser/lib/mocompiler.js
new file mode 100644
index 000000000..0e848c7fd
--- /dev/null
+++ b/node_modules/gettext-parser/lib/mocompiler.js
@@ -0,0 +1,237 @@
+'use strict';
+
+var encoding = require('encoding');
+var sharedFuncs = require('./shared');
+
+/**
+ * Exposes general compiler function. Takes a translation
+ * object as a parameter and returns binary MO object
+ *
+ * @param {Object} table Translation object
+ * @return {Buffer} Compiled binary MO object
+ */
+module.exports = function(table) {
+ var compiler = new Compiler(table);
+ return compiler.compile();
+};
+
+/**
+ * Creates a MO compiler object.
+ *
+ * @constructor
+ * @param {Object} table Translation table as defined in the README
+ */
+function Compiler(table) {
+ this._table = table || {};
+ this._table.headers = this._table.headers || {};
+ this._table.translations = this._table.translations || {};
+
+ this._translations = [];
+
+ this._writeFunc = 'writeUInt32LE';
+
+ this._handleCharset();
+}
+
+/**
+ * Magic bytes for the generated binary data
+ */
+Compiler.prototype.MAGIC = 0x950412de;
+
+/**
+ * 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(';'),
+ contentType = parts.shift(),
+ charset = sharedFuncs.formatCharset(this._table.charset),
+ 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;
+};
+
+/**
+ * Generates an array of translation strings
+ * in the form of [{msgid:... , msgstr:...}]
+ *
+ * @return {Array} Translation strings array
+ */
+Compiler.prototype._generateList = function() {
+ var list = [];
+
+ list.push({
+ msgid: new Buffer(0),
+ msgstr: encoding.convert(sharedFuncs.generateHeader(this._table.headers), this._charset)
+ });
+
+ 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;
+ }
+
+ var msgid_plural = this._table.translations[msgctxt][msgid].msgid_plural,
+ key = msgid,
+ value;
+
+ if (msgctxt) {
+ key = msgctxt + '\u0004' + key;
+ }
+
+ if (msgid_plural) {
+ key += '\u0000' + msgid_plural;
+ }
+
+ value = [].concat(this._table.translations[msgctxt][msgid].msgstr || []).join('\u0000');
+
+ list.push({
+ msgid: encoding.convert(key, this._charset),
+ msgstr: encoding.convert(value, this._charset)
+ });
+ }).bind(this));
+ }).bind(this));
+
+ return list;
+};
+
+/**
+ * Calculate buffer size for the final binary object
+ *
+ * @param {Array} list An array of translation strings from _generateList
+ * @return {Object} Size data of {msgid, msgstr, total}
+ */
+Compiler.prototype._calculateSize = function(list) {
+ var msgidLength = 0,
+ msgstrLength = 0,
+ totalLength = 0;
+
+ list.forEach(function(translation) {
+ msgidLength += translation.msgid.length + 1; // + extra 0x00
+ msgstrLength += translation.msgstr.length + 1; // + extra 0x00
+ });
+
+ totalLength = 4 + // magic number
+ 4 + // revision
+ 4 + // string count
+ 4 + // original string table offset
+ 4 + // translation string table offset
+ 4 + // hash table size
+ 4 + // hash table offset
+ (4 + 4) * list.length + // original string table
+ (4 + 4) * list.length + // translations string table
+ msgidLength + // originals
+ msgstrLength; // translations
+
+ return {
+ msgid: msgidLength,
+ msgstr: msgstrLength,
+ total: totalLength
+ };
+};
+
+/**
+ * Generates the binary MO object from the translation list
+ *
+ * @param {Array} list translation list
+ * @param {Object} size Byte size information
+ * @return {Buffer} Compiled MO object
+ */
+Compiler.prototype._build = function(list, size) {
+ var returnBuffer = new Buffer(size.total),
+ curPosition = 0,
+ i, len;
+
+ // magic
+ returnBuffer[this._writeFunc](this.MAGIC, 0);
+
+ // revision
+ returnBuffer[this._writeFunc](0, 4);
+
+ // string count
+ returnBuffer[this._writeFunc](list.length, 8);
+
+ // original string table offset
+ returnBuffer[this._writeFunc](28, 12);
+
+ // translation string table offset
+ returnBuffer[this._writeFunc](28 + (4 + 4) * list.length, 16);
+
+ // hash table size
+ returnBuffer[this._writeFunc](0, 20);
+
+ // hash table offset
+ returnBuffer[this._writeFunc](28 + (4 + 4) * list.length, 24);
+
+ // build originals table
+ curPosition = 28 + 2 * (4 + 4) * list.length;
+ for (i = 0, len = list.length; i < len; i++) {
+ list[i].msgid.copy(returnBuffer, curPosition);
+ returnBuffer[this._writeFunc](list[i].msgid.length, 28 + i * 8);
+ returnBuffer[this._writeFunc](curPosition, 28 + i * 8 + 4);
+ returnBuffer[curPosition + list[i].msgid.length] = 0x00;
+ curPosition += list[i].msgid.length + 1;
+ }
+
+ // build translations table
+ for (i = 0, len = list.length; i < len; i++) {
+ list[i].msgstr.copy(returnBuffer, curPosition);
+ returnBuffer[this._writeFunc](list[i].msgstr.length, 28 + (4 + 4) * list.length + i * 8);
+ returnBuffer[this._writeFunc](curPosition, 28 + (4 + 4) * list.length + i * 8 + 4);
+ returnBuffer[curPosition + list[i].msgstr.length] = 0x00;
+ curPosition += list[i].msgstr.length + 1;
+ }
+
+ return returnBuffer;
+};
+
+/**
+ * Compiles translation object into a binary MO object
+ *
+ * @return {Buffer} Compiled MO object
+ */
+Compiler.prototype.compile = function() {
+ var list = this._generateList(),
+ size = this._calculateSize(list);
+
+ // sort by msgid
+ list.sort(function(a, b) {
+ if (a.msgid > b.msgid) {
+ return 1;
+ }
+ if (a.msgid < b.msgid) {
+ return -1;
+ }
+ return 0;
+ });
+
+ return this._build(list, size);
+}; \ No newline at end of file