UNPKG

vvc

Version:

Vivocha Command Line Tools

212 lines 7.99 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const eredita_1 = require("eredita"); const fs_1 = require("fs"); const _ = require("lodash"); const util_1 = require("util"); const ws_1 = require("./ws"); const PO = require('pofile'); const poload = util_1.promisify(PO.load); const VVC_STRING_ID = 'vivocha-string-id'; function reducer(o, i) { o[i.id] = { id: i.id, values: i.values }; if (i.description) { o[i.id].description = i.description; } return o; } function getPaths(strings) { let data = strings.map(s => s.id).reduce((o, i) => { eredita_1.Eredita.dot(o, i, true); return o; }, {}); function _getPaths(data, curr_path, curr_depth) { const keys = Object.keys(data); if (keys.length > 1) { if (curr_depth > 1 || keys.length > 2) { return curr_path; } else { return keys.map(k => _getPaths(data[k], `${curr_path}${curr_path ? '.' : ''}${k}`, curr_depth + 1)).join(','); } } else if (typeof data[keys[0]] === 'boolean') { return curr_path; } else { return _getPaths(data[keys[0]], `${curr_path}${curr_path ? '.' : ''}${keys[0]}`, curr_depth + 1); } } return _getPaths(data, '', 0); } function fetchStrings(path, global) { return ws_1.ws(`strings${global ? '?global=true' : ''}`, { qs: { path } }); } exports.fetchStrings = fetchStrings; async function uploadString(str, global) { return ws_1.ws(`strings/${str.id}${global ? '?global=true' : ''}`, { method: 'PUT', body: str }); } exports.uploadString = uploadString; async function fetchWidgetStrings(widgetId, global) { const prefix = `WIDGET.${widgetId}.`; const prefix_re = new RegExp(`^${prefix}`); return (await fetchStrings(prefix, global)).map(i => { i.id = i.id.replace(prefix_re, ''); return i; }); } exports.fetchWidgetStrings = fetchWidgetStrings; async function uploadWidgetString(widgetId, str, global) { let wstr = Object.assign({}, str, { id: `WIDGET.${widgetId}.${str.id}` }); return uploadString(wstr, global).then(() => str.id); } exports.uploadWidgetString = uploadWidgetString; async function uploadWidgetStringChanges(widgetId, newStrings, global) { const o = (await fetchWidgetStrings(widgetId, global)).reduce(reducer, {}); const n = newStrings.reduce(reducer, {}); const stringIds = Object.keys(n); for (let k of stringIds) { if (!o[k] || !_.isEqual(o[k], n[k])) { console.log(`string ${k} changed, uploading`); await uploadWidgetString(widgetId, n[k], global); } } return stringIds; } exports.uploadWidgetStringChanges = uploadWidgetStringChanges; async function uploadStringChanges(newStrings, global) { let paths = getPaths(newStrings); const o = (await fetchStrings(paths, global)).reduce(reducer, {}); const n = newStrings.reduce(reducer, {}); const stringIds = Object.keys(n); for (let k of stringIds) { if (!o[k] || !_.isEqual(o[k], n[k])) { console.log(`string ${k} changed, uploading`); await uploadString(n[k], global); } } return stringIds; } exports.uploadStringChanges = uploadStringChanges; async function importPOFiles(files, mergeTo, filter) { const out = mergeTo ? mergeTo.reduce(reducer, {}) : {}; const pofiles = {}; for (let f of files) { const data = await poload(f); if (!data || !data.headers || !data.headers.Language) { throw new Error('bad_file'); } pofiles[data.headers.Language] = data; } const languages = Object.keys(pofiles).sort(); for (let l of languages) { const data = pofiles[l]; for (let i of (data.items || [])) { /* A po file can have multiple comments that reference different ids for the same translation, so for each comment we should check if it's a vvc_string_id reference */ for (let comment of (i.comments || [])) { if (comment.startsWith(VVC_STRING_ID)) { const stringId = comment.split(':')[1].trim(); if (filter && stringId.indexOf(filter) !== 0) { continue; } if (!out[stringId]) { out[stringId] = { id: stringId, values: {} }; } if (i.msgstr[0]) { out[stringId].values[l] = { value: i.msgstr[0], state: (i.flags && i.flags.fuzzy ? 'needs-review' : 'final') }; } if (i.msgctxt) { out[stringId].description = i.msgctxt; } } } } } return Object.values(out); } exports.importPOFiles = importPOFiles; async function exportPOFiles(source_language, files, project, language, prefix, basename, referenceLanguage) { const out = {}; function newPO(lang) { const po = new PO(); po.headers = { 'MIME-Version': '1.0', 'Content-Type': 'text/plain; charset=UTF-8', 'Content-Transfer-Encoding': '8bit', 'X-Generator': 'vvc', 'Project-Id-Version': project, 'Language': lang }; po.headerOrder = ['MIME-Version', 'Content-Type', 'Content-Transfer-Encoding', 'X-Generator', 'Project-Id-Version', 'Language']; return po; } const _languages = new Set(); const data = []; for (let f of files) { const file = JSON.parse(fs_1.readFileSync(f, 'utf8')); data.push(file); for (let i of file) { for (let l in (i.values || {})) { _languages.add(l); } } } const languages = [..._languages].sort(); for (let file of data) { for (let i of file) { const values = i.values || {}; for (let l of languages) { const value = values[l] || {}; if (!out[l]) { out[l] = newPO(l); } const item = new PO.Item(); const stringId = i.id; item.msgid = (values[source_language] || {}).value || ''; item.msgstr = value.value || ''; if (i.description) { item.extractedComments.push(i.description); } if (referenceLanguage && l !== referenceLanguage && values[referenceLanguage] && values[referenceLanguage].value) { if (item.extractedComments.length) { item.extractedComments.push(""); } item.extractedComments.push(`REFERENCE ${referenceLanguage.toLocaleUpperCase()} TRANSLATION:`); values[referenceLanguage].value.split('\n').forEach(r => item.extractedComments.push(r)); } if (value.value && (value.state === 'needs-review' || value.state === 'new')) { item.flags = { fuzzy: true }; } if (!item.comments) { item.comments = []; } item.comments.push(`${VVC_STRING_ID}: ${stringId}`); out[l].items.push(item); } } } for (let l in out) { if (!language || language === l) { const filename = `${basename}_${source_language}_${l}.po`; console.log(`Writing ${filename}`); await util_1.promisify(out[l].save.bind(out[l]))(filename); } } } exports.exportPOFiles = exportPOFiles; //# sourceMappingURL=strings.js.map