MSIBuild/PO.js
Simon Rozman 969c217511 Copyright: Bump year
Signed-off-by: Simon Rozman <simon@rozman.si>
2021-03-25 08:32:22 +01:00

283 lines
6.9 KiB
JavaScript

/*
Copyright © 1991-2021 Amebis
Copyright © 2016 GÉANT
This file is part of MSIBuild.
MSIBuild is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
MSIBuild is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with MSIBuild. If not, see <http://www.gnu.org/licenses/>.
*/
/*@cc_on @*/
/*@if (! @_escapePO_JS__) @*/
/*@set @_escapePO_JS__ = true @*/
var escapePO_stat = null;
function escapePO(str)
{
if (!escapePO_stat) {
escapePO_stat = {
"re_bslash": new RegExp("\\\\", "g"),
"re_bs": new RegExp("\b", "g"),
"re_ff": new RegExp("\f", "g"),
"re_lf": new RegExp("\n", "g"),
"re_cr": new RegExp("\r", "g"),
"re_tab": new RegExp("\t", "g"),
"re_quot": new RegExp("\"", "g")
};
}
if (str == null) return null;
switch (typeof(str)) {
case "string": break;
case "undefined": return null;
default: try { str = str.toString(); } catch (err) { return null; }
}
return str.replace(escapePO_stat.re_bslash, "\\\\").replace(escapePO_stat.re_bs, "\\b").replace(escapePO_stat.re_ff, "\\f").replace(escapePO_stat.re_lf, "\\n").replace(escapePO_stat.re_cr, "\\r").replace(escapePO_stat.re_tab, "\\t").replace(escapePO_stat.re_quot, "\\\"");
}
var unescapePO_stat = null;
function unescapePO(str)
{
if (!unescapePO_stat) {
unescapePO_stat = {
"re_esc": new RegExp("\\\\(.)", "g"),
"fn_esc": function($0, $1) {
switch ($1) {
case "\\": return "\\";
case "b" : return "\b";
case "f" : return "\f";
case "n" : return "\n";
case "r" : return "\r";
case "t" : return "\t";
case "\'": return "\'";
case "\"": return "\"";
default : return $0;
}
}
};
}
if (str == null) return null;
switch (typeof(str)) {
case "string": break;
case "undefined": return null;
default: try { str = str.toString(); } catch (err) { return null; }
}
return str.replace(unescapePO_stat.re_esc, unescapePO_stat.fn_esc);
}
function POCatalog()
{
this.charset = "utf-8";
this.data = new Array();
if (arguments.length) {
var
path = arguments[0];
// Open file.
var dat = new ActiveXObject("ADODB.Stream");
dat.Open();
try {
// PO catalogue is text file, uses Unix line breaks and UTF-8.
dat.Type = adTypeText;
dat.LineSeparator = adLF;
dat.Charset = this.charset;
// Load file.
dat.LoadFromFile(path);
// Prepare regular expressions for catalogue parsing.
var regexp = {
"fuzzy": new RegExp("^\\s*#,\\s*fuzzy", "i"),
"comment": new RegExp("^\\s*#", ""),
"record": new RegExp("^\\s*(\\w*)\\s*\"(.*)\"\\s*$", "")
};
var getNext = function() {
var
id = null,
rec = new Array();
while (!dat.EOS) {
var
s = Trim(dat.ReadText(adReadLine)),
m;
// The line is empty => end of record.
if (s == "" && "msgid" in rec)
break;
// The record is marked as "fuzzy".
if (s.search(regexp.fuzzy) != -1) {
rec["fuzzy"] = true;
continue;
}
// Concatenate comments.
if (s.search(regexp.comment) != -1) {
if ("#" in rec)
rec["#"] += s + "\n";
else
rec["#"] = s + "\n";
continue;
}
m = s.match(regexp.record);
if (m) {
// Record found.
if (m[1] != "")
id = new String(m[1]);
if (id in rec)
rec[id] += new String(m[2]);
else
rec[id] = new String(m[2]);
continue;
}
}
// Unescape messages now that they are concatenated.
for (id in rec)
rec[id] = unescapePO(rec[id]);
return "msgid" in rec ? rec : null;
}
// Read header record.
var rec = getNext();
if (rec == null)
return;
if (rec.msgid == "") {
// Parse charset.
m = rec.msgstr.match(new RegExp("^\\s*Content-Type\\s*:\\s*([-\\w]+/[-\\w]+)\\s*(;\\s*charset\\s*=\\s*([-\\w]+))?$", "im"));
if (m && m.length >= 4) {
this.charset = m[3];
// Rewind and reconfigure code page.
dat.Position = 0;
dat.Charset = this.charset;
// Re-read header.
rec = getNext();
}
}
// Load header and all the records.
this.push(rec.msgid, rec.msgstr, rec.fuzzy, "#" in rec ? rec["#"] : null);
while ((rec = getNext()) != null)
this.push(rec.msgid, rec.msgstr, rec.fuzzy, "#" in rec ? rec["#"] : null);
} finally {
dat.Close();
}
}
}
POCatalog.prototype.push = function(key, trans, fuzzy, comment)
{
var rec = {
"msgstr" : trans,
"fuzzy" : fuzzy ? true : false
};
if (comment)
rec["#"] = comment;
this.data[key] = rec;
}
POCatalog.prototype.search = function(key)
{
return (key in this.data) ? this.data[key] : null;
}
POCatalog.prototype.translate = function(key)
{
if (!(key in this.data)) {
// No translation found.
return key;
}
var rec = this.data[key];
if (rec.msgstr == "" || rec.fuzzy) {
// Translation is blank (untranslated) or fuzzy.
return key;
}
return rec.msgstr;
}
POCatalog.prototype.save = function(path)
{
// Open PO file in memory.
var dat = new ActiveXObject("ADODB.Stream");
dat.Open();
try {
// PO is text file, uses Unix line breaks and given encoding.
dat.Type = adTypeText;
dat.LineSeparator = adLF;
dat.Charset = this.charset;
var writeRec = function(key, rec) {
if (rec.fuzzy)
dat.WriteText("#, fuzzy", adWriteLine);
if ("#" in rec)
dat.WriteText(rec["#"], adWriteLine);
dat.WriteText("msgid \"" + escapePO(key ) + "\"", adWriteLine);
dat.WriteText("msgstr \"" + escapePO(rec.msgstr) + "\"", adWriteLine);
dat.WriteText("", adWriteLine);
}
// Write header first.
if ("" in this.data)
writeRec("", this.data[""]);
// Write records, skip header.
for (var key in this.data) {
if (key == "") continue;
writeRec(key, this.data[key]);
}
if (this.charset.toLowerCase() == "utf-8") {
// Write to file without UTF-8 BOM.
var dat_nobom = new ActiveXObject("ADODB.Stream");
dat_nobom.Type = adTypeBinary;
dat_nobom.Mode = adModeReadWrite;
dat_nobom.Open();
try {
// Skip BOM (first three bytes) and copy the rest.
dat.Position = 3;
dat.CopyTo(dat_nobom);
dat_nobom.SaveToFile(path, adSaveCreateOverWrite);
} finally {
dat_nobom.Close();
}
} else {
dat.SaveToFile(path, adSaveCreateOverWrite);
}
} finally {
dat.Close();
}
}
/*@end @*/