00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include <QFile>
00014 #include <QDomDocument>
00015 #include <QTextStream>
00016 #include <QTextCodec>
00017 #include <stdlib.h>
00018
00019 #define WXL_NAMESPACE "http://schemas.microsoft.com/wix/2006/localization"
00020 #define WXL_ELEMENT_ROOT "WixLocalization"
00021 #define WXL_ELEMENT_MESSAGE "String"
00022 #define WXL_ATTR_MESSAGE_ID "Id"
00023 #define WXL_ATTR_LANGUAGE "LCID"
00024 #define WXL_ATTR_TRANSLATION_TYPE "Culture"
00025 #define WXL_ATTR_OVERRIDABLE "Overridable"
00026
00027
00028
00029 QString
00030 culture_lcid(const QString &culture)
00031 {
00032
00033 QString lcid = "0";
00034 if(!culture.compare("en", Qt::CaseInsensitive))
00035 lcid = "1033";
00036 else if(!culture.compare("cs", Qt::CaseInsensitive))
00037 lcid = "1029";
00038 else if(!culture.compare("de", Qt::CaseInsensitive))
00039 lcid = "1031";
00040 else if(!culture.compare("es", Qt::CaseInsensitive))
00041 lcid = "1034";
00042 else if(!culture.compare("fa", Qt::CaseInsensitive))
00043 lcid = "1065";
00044 else if(!culture.compare("fi", Qt::CaseInsensitive))
00045 lcid = "1035";
00046 else if(!culture.compare("fr", Qt::CaseInsensitive))
00047 lcid = "1036";
00048 else if(!culture.compare("he", Qt::CaseInsensitive))
00049 lcid = "1037";
00050 else if(!culture.compare("it", Qt::CaseInsensitive))
00051 lcid = "1040";
00052 else if(!culture.compare("nl", Qt::CaseInsensitive))
00053 lcid = "1043";
00054 else if(!culture.compare("pl", Qt::CaseInsensitive))
00055 lcid = "1045";
00056 else if(!culture.compare("pt", Qt::CaseInsensitive))
00057 lcid = "1046";
00058 else if(!culture.compare("ro", Qt::CaseInsensitive))
00059 lcid = "1048";
00060 else if(!culture.compare("ru", Qt::CaseInsensitive))
00061 lcid = "1049";
00062 else if(!culture.compare("sv", Qt::CaseInsensitive))
00063 lcid = "1053";
00064 return lcid;
00065 }
00066
00067
00068
00069 QDomElement
00070 new_message_element(QDomDocument *wxl, const QString &strid,
00071 const QString &msgid, const QString &msgstr)
00072 {
00073 QDomElement message;
00074
00075 message = wxl->createElement(WXL_ELEMENT_MESSAGE);
00076 message.setAttribute(WXL_ATTR_MESSAGE_ID, strid);
00077
00078
00079
00080
00081 message.setAttribute(WXL_ATTR_OVERRIDABLE, "yes");
00082 if (!msgstr.isEmpty())
00083 message.appendChild(wxl->createTextNode(msgstr));
00084 else
00085 message.appendChild(wxl->createTextNode(msgid));
00086
00087 return message;
00088 }
00089
00090
00091
00092 QDomDocument
00093 new_wxl_document(const QString &culture)
00094 {
00095 QDomDocument wxl;
00096
00097 QDomElement root = wxl.createElementNS(WXL_NAMESPACE, WXL_ELEMENT_ROOT);
00098 root.setAttribute(WXL_ATTR_TRANSLATION_TYPE, culture);
00099 wxl.appendChild(root);
00100
00101 return wxl;
00102 }
00103
00104
00105
00106 QString
00107 parse_message_context(const QString &str)
00108 {
00109 QString out = str.trimmed();
00110 out = out.replace("\"", "");
00111 return out;
00112 }
00113
00114
00115
00116 QString
00117 parse_message_context_lame(const QString &str)
00118 {
00119 if (str.contains("#"))
00120 return str.section("#", 0, 0);
00121 return QString();
00122 }
00123
00124
00125
00126
00127 QString
00128 parse_message_string(const QString &msg)
00129 {
00130 QString out = msg.trimmed();
00131
00132 out.replace("\"\n\"", "\n");
00133 if (out.startsWith("\""))
00134 out = out.remove(0, 1);
00135 if (out.endsWith("\""))
00136 out.chop(1);
00137 out.replace("\\\"", "\"");
00138
00139
00140 int lind, rind;
00141 while ( ((lind = out.indexOf("${")) >= 0) &&
00142 ((rind = out.indexOf("}", lind)) > lind) ) {
00143 out.replace(lind, 2, "[");
00144 out.replace(--rind, 1, "]");
00145 }
00146 return out;
00147 }
00148
00149
00150 QString
00151 read_next_line(QTextStream *stream)
00152 {
00153 stream->skipWhiteSpace();
00154 return stream->readLine().append("\n");
00155 }
00156
00157
00158
00159
00160 void
00161 skip_po_header(QTextStream *po)
00162 {
00163 QString line;
00164
00165 po->skipWhiteSpace();
00166
00167 line = po->readLine();
00168 while (!po->atEnd() && !line.isEmpty())
00169 line = po->readLine();
00170 }
00171
00172
00173
00174
00175
00176 int
00177 po2wxl(const QString& culture, QTextStream *po, QDomDocument *wxl,
00178 QString *errorMessage)
00179 {
00180 QString line;
00181 QString msgctxt, msgid, msgstr;
00182 QDomElement msgElement;
00183 int n_strings = 0;
00184
00185 Q_ASSERT(po);
00186 Q_ASSERT(wxl);
00187 Q_ASSERT(errorMessage);
00188
00189 *wxl = new_wxl_document(culture);
00190
00191
00192 QString lcid = culture_lcid(culture);
00193 wxl->documentElement().appendChild(
00194 new_message_element(wxl, WXL_ATTR_LANGUAGE, lcid, lcid));
00195
00196 skip_po_header(po);
00197 line = read_next_line(po);
00198 while (!po->atEnd()) {
00199
00200 while (line.startsWith("#")) {
00201 if (line.startsWith("#:")) {
00202
00203 msgctxt = line.section(" ", 1);
00204 msgctxt = parse_message_context_lame(msgctxt);
00205 }
00206 line = read_next_line(po);
00207 }
00208
00209
00210
00211 if (line.startsWith("msgctxt ")) {
00212 msgctxt = line.section(" ", 1);
00213 msgctxt = parse_message_context(msgctxt);
00214 line = read_next_line(po);
00215 }
00216
00217
00218 if (!line.startsWith("msgid ")) {
00219 *errorMessage = "expected 'msgid' line";
00220 return -1;
00221 }
00222 msgid = line.section(" ", 1);
00223
00224 line = read_next_line(po);
00225 while (line.startsWith("\"")) {
00226 msgid.append(line);
00227 line = read_next_line(po);
00228 }
00229 msgid = parse_message_string(msgid);
00230
00231
00232 if (!line.startsWith("msgstr ")) {
00233 *errorMessage = "expected 'msgstr' line";
00234 return -1;
00235 }
00236 msgstr = line.section(" ", 1);
00237
00238 line = read_next_line(po);
00239 while (line.startsWith("\"")) {
00240 msgstr.append(line);
00241 line = read_next_line(po);
00242 }
00243 msgstr = parse_message_string(msgstr);
00244
00245
00246 wxl->documentElement().appendChild(
00247 new_message_element(wxl, msgctxt, msgid, msgstr));
00248
00249 n_strings++;
00250 }
00251 return n_strings;
00252 }
00253
00254
00255 void
00256 print_usage_and_exit()
00257 {
00258 QTextStream error(stderr);
00259 error << "usage: po2wxl [-q] -n <culture name> -i <infile.po> -o <outfile.wxl> "
00260 "[-c <encoding>]\n";
00261 error << " -q (optional) Quiet mode (errors are still displayed)\n";
00262 error << " -n <culture> Culture name for translation\n";
00263 error << " -i <infile.po> Input .po file\n";
00264 error << " -o <outfile.wxl> Output .wxl file\n";
00265 error << " -c <encoding> Text encoding (default: utf-8)\n";
00266 error.flush();
00267 exit(1);
00268 }
00269
00270 int
00271 main(int argc, char *argv[])
00272 {
00273 QTextStream error(stderr);
00274 QString culture, errorMessage;
00275 char *infile, *outfile;
00276 QTextCodec *codec = QTextCodec::codecForName("utf-8");
00277 bool quiet = false;
00278
00279
00280 if (argc < 5 || argc > 9)
00281 print_usage_and_exit();
00282 for (int i = 1; i < argc; i++) {
00283 QString arg(argv[i]);
00284 if (!arg.compare("-q", Qt::CaseInsensitive))
00285 quiet = true;
00286 else if (!arg.compare("-n", Qt::CaseInsensitive) && ++i < argc)
00287 culture = argv[i];
00288 else if (!arg.compare("-i", Qt::CaseInsensitive) && ++i < argc)
00289 infile = argv[i];
00290 else if (!arg.compare("-o", Qt::CaseInsensitive) && ++i < argc)
00291 outfile = argv[i];
00292 else if (!arg.compare("-c", Qt::CaseInsensitive) && ++i < argc) {
00293 codec = QTextCodec::codecForName(argv[i]);
00294 if (!codec) {
00295 error << "Invalid text encoding specified\n";
00296 return 1;
00297 }
00298 } else
00299 print_usage_and_exit();
00300 }
00301
00302
00303 QFile poFile(infile);
00304 if (!poFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
00305 error << QString("Unable to open '%1' for reading: %2\n").arg(infile)
00306 .arg(poFile.errorString());
00307 return 2;
00308 }
00309
00310 QDomDocument wxl;
00311 QTextStream po(&poFile);
00312 po.setCodec(codec);
00313 int n_strings = po2wxl(culture, &po, &wxl, &errorMessage);
00314 if (n_strings < 0) {
00315 error << QString("Unable to convert '%1': %2\n").arg(infile)
00316 .arg(errorMessage);
00317 return 3;
00318 }
00319
00320
00321 QFile wxlFile(outfile);
00322 if (!wxlFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
00323 error << QString("Unable to open '%1' for writing: %2\n").arg(outfile)
00324 .arg(wxlFile.errorString());
00325 return 4;
00326 }
00327
00328
00329 QTextStream out(&wxlFile);
00330 out.setCodec(codec);
00331 out << QString("<?xml version=\"1.0\" encoding=\"%1\"?>\n")
00332 .arg(QString(codec->name()));
00333 out << wxl.toString(4);
00334
00335 if (!quiet) {
00336 QTextStream results(stdout);
00337 results << QString("Converted %1 strings from %2 to %3.\n").arg(n_strings)
00338 .arg(infile)
00339 .arg(outfile);
00340 }
00341 return 0;
00342 }
00343