UNPKG

rucken

Version:

Console tools and scripts for nx and not only that I (EndyKaufman) use to automate the workflow and speed up the development process

153 lines (150 loc) 5.13 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.parsePo = exports.parseMo = void 0; const gettext_parser_1 = require("gettext-parser"); /* Examples from https://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html Note: true == 1, false == 0 Plural-Forms: nplurals=1; plural=0; Plural-Forms: nplurals=2; plural=n != 1; Plural-Forms: nplurals=2; plural=n>1; Plural-Forms: nplurals=2; plural=n == 1 ? 0 : 1; Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2; Plural-Forms: nplurals=3; plural=n==1 ? 0 : n==2 ? 1 : 2; Plural-Forms: nplurals=3; plural=n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < 20)) ? 1 : 2; Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2; Plural-Forms: nplurals=4; plural=n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3; Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 ? 4 : 5; */ const validPlural = (plural) => { const words = plural.match(/\b\w+\b/g); if (!words) return null; for (let i = 0; i < words.length; ++i) { const word = words[i]; if (word !== 'n' && isNaN(Number(word))) return null; } return plural.trim(); }; const getPluralFunction = (pluralForms) => { if (!pluralForms) return null; let nplurals; let plural; pluralForms.split(';').forEach((part) => { const m = part.match(/^\s*(\w+)\s*=(.*)/); switch (m && m[1]) { case 'nplurals': nplurals = Number(m[2]); break; case 'plural': plural = validPlural(m[2]); break; } }); if (!nplurals || !plural) throw new Error('Invalid plural-forms: ' + pluralForms); const pluralFunc = new Function('n', `return 'p' + Number(${plural})`); pluralFunc.cardinal = new Array(nplurals) .fill(' ') .map((_, i) => 'p' + i); return pluralFunc; }; const defaultOptions = { defaultCharset: null, forceContext: false, pluralFunction: null, pluralVariablePattern: /%(?:\((\w+)\))?\w/, replacements: [ // { // pattern: /[\\{}#]/g, // replacement: '\\$&', // }, { pattern: /%(\d+)(?:\$\w)?/g, replacement: (_, n) => `{${n - 1}}`, }, { pattern: /%\((\w+)\)\w/g, replacement: '{$1}', }, { pattern: /%\w/g, replacement: function () { return `{${this.n++}}`; }, state: { n: 0 }, }, { pattern: /%%/g, replacement: '%', }, ], verbose: false, }; const getMessageFormat = ({ pluralFunction, pluralVariablePattern, replacements, verbose }, { msgid, msgid_plural, msgstr }) => { if (!msgid || !msgstr) return null; if (!msgstr[0]) { if (verbose) console.warn('Translation not found:', msgid); msgstr[0] = msgid; } if (msgid_plural) { if (!pluralFunction) throw new Error('Plural-Forms not defined'); for (let i = 1; i < pluralFunction.cardinal.length; ++i) { if (!msgstr[i]) { if (verbose) console.warn('Plural translation not found:', msgid, i); msgstr[i] = msgid_plural; } } } msgstr = msgstr.map((str) => replacements.reduce((str, { pattern, replacement, state }) => { if (state) replacement = replacement.bind(Object.assign({}, state)); return str.replace(pattern, replacement); }, str)); if (msgid_plural) { const m = msgid_plural.match(pluralVariablePattern); const pv = (m && m[1]) || '0'; const pc = pluralFunction.cardinal.map((c, i) => `${c}{${msgstr[i]}}`); return `{${pv}, plural, ${pc.join(' ')}}`; } return msgstr[0]; }; const convert = (parse, input, options) => { options = Object.assign({}, defaultOptions, options); const { headers, translations } = parse(input, options); if (!options.pluralFunction) { options.pluralFunction = getPluralFunction(headers['Plural-Forms']); } let hasContext = false; for (const context in translations) { if (context) hasContext = true; const data = translations[context]; for (const id in data) { const mf = getMessageFormat(options, data[id]); if (mf) data[id] = mf; else delete data[id]; } } return { headers, pluralFunction: options.pluralFunction, translations: hasContext || options.forceContext ? translations : translations[''], }; }; function parseMo(input, options) { return convert(gettext_parser_1.mo.parse, input, options || {}); } exports.parseMo = parseMo; function parsePo(input, options) { return convert(gettext_parser_1.po.parse, input, options || {}); } exports.parsePo = parsePo;