summaryrefslogtreecommitdiffstats
path: root/tools/linguist/shared
diff options
context:
space:
mode:
authorOswald Buddenhagen <oswald.buddenhagen@nokia.com>2010-06-02 13:39:40 (GMT)
committerOswald Buddenhagen <oswald.buddenhagen@nokia.com>2010-06-02 13:46:34 (GMT)
commita1c8fc04c17cfbf0060c81d442ffa2440a796112 (patch)
tree48cadc9599b325589541ea29229c52ce536edb47 /tools/linguist/shared
parentfbce5c6d20571717d67c2b8934f047af035e5b06 (diff)
downloadQt-a1c8fc04c17cfbf0060c81d442ffa2440a796112.zip
Qt-a1c8fc04c17cfbf0060c81d442ffa2440a796112.tar.gz
Qt-a1c8fc04c17cfbf0060c81d442ffa2440a796112.tar.bz2
write PO files without duplicated message ids
encoding the qt context as a magic comment was no particularly good idea, as it provided no disambiguation as far as gettext is concerned. so instead encode the context into msgctxt. Task-number: QTBUG-10307
Diffstat (limited to 'tools/linguist/shared')
-rw-r--r--tools/linguist/shared/po.cpp67
1 files changed, 60 insertions, 7 deletions
diff --git a/tools/linguist/shared/po.cpp b/tools/linguist/shared/po.cpp
index 99a8751..6a1d426 100644
--- a/tools/linguist/shared/po.cpp
+++ b/tools/linguist/shared/po.cpp
@@ -353,6 +353,29 @@ static void slurpComment(QByteArray &msg, const QList<QByteArray> &lines, int &
--l;
}
+static void splitContext(QByteArray *comment, QByteArray *context)
+{
+ char *data = comment->data();
+ int len = comment->size();
+ int sep = -1, j = 0;
+
+ for (int i = 0; i < len; i++, j++) {
+ if (data[i] == '~' && i + 1 < len)
+ i++;
+ else if (data[i] == '|')
+ sep = j;
+ data[j] = data[i];
+ }
+ if (sep >= 0) {
+ QByteArray tmp = comment->mid(sep + 1, j - sep - 1);
+ comment->truncate(sep);
+ *context = *comment;
+ *comment = tmp;
+ } else {
+ comment->truncate(j);
+ }
+}
+
static QString makePoHeader(const QString &str)
{
return QLatin1String("po-header-") + str.toLower().replace(QLatin1Char('-'), QLatin1Char('_'));
@@ -411,6 +434,7 @@ bool loadPO(Translator &translator, QIODevice &dev, ConversionData &cd)
lines.append(QByteArray());
int l = 0, lastCmtLine = -1;
+ bool qtContexts = false;
PoItem item;
for (; l != lines.size(); ++l) {
QByteArray line = lines.at(l);
@@ -449,6 +473,8 @@ bool loadPO(Translator &translator, QIODevice &dev, ConversionData &cd)
translator.setLanguageCode(QString::fromLatin1(hdrValue));
} else if (hdrName == "X-Source-Language") {
translator.setSourceLanguageCode(QString::fromLatin1(hdrValue));
+ } else if (hdrName == "X-Qt-Contexts") {
+ qtContexts = (hdrValue == "true");
} else if (hdrName == "Plural-Forms") {
pluralForms = hdrValue;
} else if (hdrName == "MIME-Version") {
@@ -498,7 +524,7 @@ bool loadPO(Translator &translator, QIODevice &dev, ConversionData &cd)
// Keep in sync with savePO
static const char * const dfltHdrs[] = {
"MIME-Version", "Content-Type", "Content-Transfer-Encoding",
- "Plural-Forms", "X-Language", "X-Source-Language"
+ "Plural-Forms", "X-Language", "X-Source-Language", "X-Qt-Contexts"
};
uint cdh = 0;
for (int cho = 0; cho < hdrOrder.length(); cho++) {
@@ -596,7 +622,7 @@ bool loadPO(Translator &translator, QIODevice &dev, ConversionData &cd)
slurpComment(item.translatorComments, lines, l);
break;
case '.':
- if (line.startsWith("#. ts-context ")) {
+ if (line.startsWith("#. ts-context ")) { // legacy
item.context = line.mid(14);
} else if (line.startsWith("#. ts-id ")) {
item.id = line.mid(9);
@@ -615,6 +641,8 @@ bool loadPO(Translator &translator, QIODevice &dev, ConversionData &cd)
codec->toUnicode(extra);
} else if (line.startsWith("#| msgctxt ")) {
item.oldTscomment = slurpEscapedString(lines, l, 11, "#| ", cd);
+ if (qtContexts)
+ splitContext(&item.oldTscomment, &item.context);
} else {
cd.appendError(QString(QLatin1String("PO-format parse error in line %1: '%2'\n"))
.arg(l + 1).arg(codec->toUnicode(lines[l])));
@@ -647,6 +675,8 @@ bool loadPO(Translator &translator, QIODevice &dev, ConversionData &cd)
lastCmtLine = l;
} else if (line.startsWith("msgctxt ")) {
item.tscomment = slurpEscapedString(lines, l, 8, QByteArray(), cd);
+ if (qtContexts)
+ splitContext(&item.tscomment, &item.context);
} else if (line.startsWith("msgid ")) {
item.msgId = slurpEscapedString(lines, l, 6, QByteArray(), cd);
} else if (line.startsWith("msgid_plural ")) {
@@ -672,6 +702,16 @@ static void addPoHeader(Translator::ExtraData &headers, QStringList &hdrOrder,
headers[makePoHeader(qName)] = value;
}
+static QString escapeComment(const QString &in, bool escape)
+{
+ QString out = in;
+ if (escape) {
+ out.replace(QLatin1Char('~'), QLatin1String("~~"));
+ out.replace(QLatin1Char('|'), QLatin1String("~|"));
+ }
+ return out;
+}
+
bool savePO(const Translator &translator, QIODevice &dev, ConversionData &cd)
{
QString str_format = QLatin1String("-format");
@@ -680,6 +720,13 @@ bool savePO(const Translator &translator, QIODevice &dev, ConversionData &cd)
QTextStream out(&dev);
out.setCodec(cd.m_outputCodec.isEmpty() ? QByteArray("UTF-8") : cd.m_outputCodec);
+ bool qtContexts = false;
+ foreach (const TranslatorMessage &msg, translator.messages())
+ if (!msg.context().isEmpty()) {
+ qtContexts = true;
+ break;
+ }
+
QString cmt = translator.extra(QLatin1String("po-header_comment"));
if (!cmt.isEmpty())
out << cmt << '\n';
@@ -703,6 +750,8 @@ bool savePO(const Translator &translator, QIODevice &dev, ConversionData &cd)
}
if (!translator.sourceLanguageCode().isEmpty())
addPoHeader(headers, hdrOrder, "X-Source-Language", translator.sourceLanguageCode());
+ if (qtContexts)
+ addPoHeader(headers, hdrOrder, "X-Qt-Contexts", QLatin1String("true"));
QString hdrStr;
foreach (const QString &hdr, hdrOrder) {
hdrStr += hdr;
@@ -721,8 +770,6 @@ bool savePO(const Translator &translator, QIODevice &dev, ConversionData &cd)
if (!msg.extraComment().isEmpty())
out << poEscapedLines(QLatin1String("#."), true, msg.extraComment());
- if (!msg.context().isEmpty())
- out << QLatin1String("#. ts-context ") << msg.context() << '\n';
if (!msg.id().isEmpty())
out << QLatin1String("#. ts-id ") << msg.id() << '\n';
@@ -770,15 +817,21 @@ bool savePO(const Translator &translator, QIODevice &dev, ConversionData &cd)
QString prefix = QLatin1String("#| ");
if (!msg.oldComment().isEmpty())
- out << poEscapedString(prefix, QLatin1String("msgctxt"), noWrap, msg.oldComment());
+ out << poEscapedString(prefix, QLatin1String("msgctxt"), noWrap,
+ escapeComment(msg.oldComment(), qtContexts));
if (!msg.oldSourceText().isEmpty())
out << poEscapedString(prefix, QLatin1String("msgid"), noWrap, msg.oldSourceText());
QString plural = msg.extra(QLatin1String("po-old_msgid_plural"));
if (!plural.isEmpty())
out << poEscapedString(prefix, QLatin1String("msgid_plural"), noWrap, plural);
prefix = QLatin1String((msg.type() == TranslatorMessage::Obsolete) ? "#~ " : "");
- if (!msg.comment().isEmpty())
- out << poEscapedString(prefix, QLatin1String("msgctxt"), noWrap, msg.comment());
+ if (!msg.context().isEmpty())
+ out << poEscapedString(prefix, QLatin1String("msgctxt"), noWrap,
+ escapeComment(msg.context(), true) + QLatin1Char('|')
+ + escapeComment(msg.comment(), true));
+ else if (!msg.comment().isEmpty())
+ out << poEscapedString(prefix, QLatin1String("msgctxt"), noWrap,
+ escapeComment(msg.comment(), qtContexts));
out << poEscapedString(prefix, QLatin1String("msgid"), noWrap, msg.sourceText());
if (!msg.isPlural()) {
QString transl = msg.translation();