13 #include <QTextStream> 16 #include <QStringList> 19 #include "nsh2po_config.h" 27 QString out = str.trimmed();
28 out = out.replace(
"\"",
"");
37 if (str.contains(
"#"))
38 return str.section(
"#", 0, 0);
46 QString out = msg.trimmed();
48 if (out.startsWith(
"\""))
49 out = out.remove(0, 1);
50 if (out.endsWith(
"\""))
52 out.replace(
"\\\"",
"\"");
53 out.replace(
"\\r\\n",
"\\n");
61 QString out = msg.trimmed();
63 if (out.startsWith(
"\""))
64 out = out.remove(0, 1);
65 if (out.endsWith(
"\""))
67 out.replace(
"$\\n",
"\\n");
68 out.replace(
"$\\r",
"");
69 out.replace(
"\\r",
"");
77 QDateTime now = QDateTime::currentDateTime().toUTC();
78 return now.toString(
"yyyy-MM-dd hh:mm+0000");
88 header.append(
"msgid \"\"\n");
89 header.append(
"msgstr \"\"\n");
90 header.append(
"\"Project-Id-Version: "NSH2PO_PROJECT_ID
"\\n\"\n");
91 header.append(
"\"Report-Msgid-Bugs-To: "NSH2PO_CONTACT_ADDR
"\\n\"\n");
92 header.append(QString(
"\"POT-Creation-Date: %1\\n\"\n").arg(tstamp));
93 header.append(
"\"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\\n\"\n");
94 header.append(
"\"Last-Translator: \\n\"\n");
95 header.append(
"\"Language-Team: "NSH2PO_LANGUAGE_TEAM
"\\n\"\n");
96 header.append(
"\"MIME-Version: 1.0\\n\"\n");
97 header.append(QString(
"\"Content-Type: text/plain; " 98 "charset=%1\\n\"\n").arg(charset));
99 header.append(
"\"Content-Transfer-Encoding: 8bit\\n\"\n");
100 header.append(
"\"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\\n\"\n");
101 header.append(
"\"X-Generator: Vidalia nsh2po "NSH2PO_VERSION
"\\n\"\n");
112 stream->skipWhiteSpace();
113 return stream->readLine();
124 pot->skipWhiteSpace();
126 line = pot->readLine();
127 while (!pot->atEnd() && !line.isEmpty())
128 line = pot->readLine();
139 QString line, msgctxt, msgid;
143 while (!pot->atEnd()) {
144 if (!line.startsWith(
"#:") && !line.startsWith(
"msgctxt")) {
150 if (line.startsWith(
"#:")) {
152 msgctxt = line.section(
" ", 1);
158 if (line.startsWith(
"msgctxt ")) {
161 msgctxt = line.section(
" ", 1);
166 if (!line.startsWith(
"msgid ")) {
167 *errmsg =
"expected 'msgid' line";
170 msgid = line.section(
" ", 1);
173 while (line.startsWith(
"\"")) {
180 out->insert(msgctxt, msgid);
191 nsh2po(QTextStream *nsh,
const QString &charset,
192 const QHash<QString,QString> &pot, QString *po, QString *errmsg)
194 QString line, msgctxt, msgid, msgstr;
196 QHash<QString,QString> langStrings;
202 while (!nsh->atEnd()) {
204 if (!line.startsWith(
"LangString "))
207 parts = line.split(
" ");
208 if (parts.size() > 3)
209 msgctxt = parts.at(1);
213 idx = line.indexOf(
"\"");
216 langStrings.insert(msgctxt, msgstr);
221 foreach (QString msgctxt, pot.keys()) {
222 msgid = pot.value(msgctxt);
223 if (langStrings.contains(msgctxt)) {
224 msgstr = langStrings.value(msgctxt);
230 po->append(QString(
"msgctxt \"%1\"\n").arg(msgctxt));
231 po->append(QString(
"msgid \"%1\"\n").arg(msgid));
232 po->append(QString(
"msgstr \"%1\"\n").arg(msgstr));
245 QFile poFile(poFileName);
246 if (!poFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
247 *errmsg = QString(
"Unable to open '%1' for writing.").arg(poFileName);
251 QTextStream out(&poFile);
261 QTextStream
error(stderr);
262 error <<
"usage: nsh2po [-q] -t <template.pot> -i <infile.nsh> " 263 "-o <outfile.po> [-c <encoding>]\n";
264 error <<
" -q (optional) Quiet mode (errors are still displayed)\n";
265 error <<
" -t <template.pot> PO template file\n";
266 error <<
" -i <infile.ts> Input .ts file\n";
267 error <<
" -o <outfile.po> Output .po file\n";
268 error <<
" -c <encoding> Text encoding (default: utf-8)\n";
276 QTextStream
error(stderr);
277 QString po, errorMessage;
279 QFile potFile, nshFile;
280 QTextStream pot, nsh;
281 QTextCodec *codec = QTextCodec::codecForName(
"utf-8");
285 if (argc < 7 || argc > 10)
287 for (
int i = 1;
i < argc;
i++) {
288 QString arg(argv[
i]);
289 if (!arg.compare(
"-q", Qt::CaseInsensitive)) {
291 }
else if (!arg.compare(
"-t", Qt::CaseInsensitive) && ++i < argc) {
293 potFile.setFileName(argv[i]);
294 if (!potFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
295 error << QString(
"Couldn't open '%1' for reading: ").arg(argv[i])
296 << potFile.errorString();
299 pot.setDevice(&potFile);
300 }
else if (!arg.compare(
"-i", Qt::CaseInsensitive) && ++i < argc) {
302 nshFile.setFileName(argv[i]);
303 if (!nshFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
304 error << QString(
"Couldn't open '%1' for reading: ").arg(argv[i])
305 << nshFile.errorString();
308 nsh.setDevice(&nshFile);
309 }
else if (!arg.compare(
"-o", Qt::CaseInsensitive) && ++i < argc) {
310 outFileName = argv[
i];
311 }
else if (!arg.compare(
"-c", Qt::CaseInsensitive) && ++i < argc) {
313 codec = QTextCodec::codecForName(argv[i]);
315 error <<
"Invalid text encoding specified.\n";
325 QHash<QString,QString> poTemplate;
327 error << QString(
"Failed to parse PO template: %1\n").arg(errorMessage);
332 int n_strings =
nsh2po(&nsh, QString(codec->name()), poTemplate,
335 error << QString(
"Conversion failed: %1\n").arg(errorMessage);
341 error << QString(
"Failed to write PO output: %1\n").arg(errorMessage);
346 QTextStream out(stdout);
347 out << QString(
"Wrote %1 strings to '%2'.\n").arg(n_strings)
DebugMessage error(const QString &fmt)
bool write_po_output(const char *poFileName, const QString &po, QTextCodec *codec, QString *errmsg)
QString parse_message_context(const QString &str)
bool parse_po_template(QTextStream *pot, QHash< QString, QString > *out, QString *errmsg)
int main(int argc, char *argv[])
QString parse_nsh_langstring(const QString &msg)
QString read_next_line(QTextStream *stream)
QString create_po_timestamp()
QString parse_message_string(const QString &msg)
QString create_po_header(const QString &charset)
void print_usage_and_exit()
QString parse_message_context_lame(const QString &str)
int nsh2po(QTextStream *nsh, const QString &charset, const QHash< QString, QString > &pot, QString *po, QString *errmsg)
void skip_pot_header(QTextStream *pot)