%PDF- %PDF-
Direktori : /var/www/projetos/stb.ind.br/wp-content/themes/stb/node_modules/gettext-parser/lib/ |
Current File : /var/www/projetos/stb.ind.br/wp-content/themes/stb/node_modules/gettext-parser/lib/mocompiler.js |
const { Buffer } = require('safe-buffer'); const encoding = require('encoding'); const 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) { const 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 () { const parts = (this._table.headers['content-type'] || 'text/plain').split(';'); const contentType = parts.shift(); let charset = sharedFuncs.formatCharset(this._table.charset); const params = parts.map(part => { const parts = part.split('='); const key = parts.shift().trim(); const 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 () { const list = []; list.push({ msgid: Buffer.alloc(0), msgstr: encoding.convert(sharedFuncs.generateHeader(this._table.headers), this._charset) }); Object.keys(this._table.translations).forEach(msgctxt => { if (typeof this._table.translations[msgctxt] !== 'object') { return; } Object.keys(this._table.translations[msgctxt]).forEach(msgid => { if (typeof this._table.translations[msgctxt][msgid] !== 'object') { return; } if (msgctxt === '' && msgid === '') { return; } const msgidPlural = this._table.translations[msgctxt][msgid].msgid_plural; let key = msgid; if (msgctxt) { key = msgctxt + '\u0004' + key; } if (msgidPlural) { key += '\u0000' + msgidPlural; } let value = [].concat(this._table.translations[msgctxt][msgid].msgstr || []).join('\u0000'); list.push({ msgid: encoding.convert(key, this._charset), msgstr: encoding.convert(value, this._charset) }); }); }); 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) { let msgidLength = 0; let msgstrLength = 0; let totalLength = 0; list.forEach(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) { const returnBuffer = Buffer.alloc(size.total); let curPosition = 0; let i; let 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 * 2, 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 () { const list = this._generateList(); const size = this._calculateSize(list); // sort by msgid list.sort((left, right) => { if (left.msgid > right.msgid) { return 1; } if (left.msgid < right.msgid) { return -1; } return 0; }); return this._build(list, size); };