static void writeMessage(QTextStream *t, const TranslatorMessage &msg, int indent, const QString &languageCode) { static int msgid = 1; if (msg.isPlural()) { writeIndent(t, indent); (*t) << "<group restype=\"" << restypePlurals << "\">\n"; indent+=2; writeLineNumber(t, msg, indent); writeComment(t, msg, indent); QLocale::Language l; QLocale::Country c; MetaTranslator::languageAndCountry(languageCode, &l, &c); QStringList translns = MetaTranslator::normalizedTranslations(msg, l, c); for (int j = 0; j < qMax(1, translns.count()); ++j) { writeTransUnit(t, msg, msgid, indent, translns.at(j)); } indent-=2; writeIndent(t, indent); (*t) << "</group>\n"; } else { writeTransUnit(t, msg, msgid, indent); } ++msgid; }
static void writeTransUnit(QTextStream *t, const TranslatorMessage &msg, int msgid, int indent, const QString &translation = QString()) { static int plural = 0; static int prevMsgId = -1; writeIndent(t, indent); (*t) << "<trans-unit id=\"msg"; QString strid; QByteArray transl; if (msg.isPlural()) { if (prevMsgId != msgid) plural = 0; strid = QString::fromAscii("%1[%2]").arg(msgid).arg(plural); ++plural; transl = translation.toUtf8(); } else { strid = QString::fromAscii("%1").arg(msgid); plural = 0; transl = msg.translation().toUtf8(); } prevMsgId = msgid; (*t) << strid << "\""; QString state; indent+=2; if (msg.type() == TranslatorMessage::Obsolete) { (*t) << " translate=\"no\""; } else { state = msg.type() == TranslatorMessage::Finished ? QLatin1String("final") : QLatin1String("new"); state = QString::fromAscii(" state=\"%1\"").arg(state); } (*t) << ">\n"; writeIndent(t, indent); (*t) << "<source xml:space=\"preserve\">" << evilBytes(msg.sourceText(), msg.utf8()) << "</source>\n"; writeIndent(t, indent); (*t) << "<target xml:space=\"preserve\"" << state << ">" << evilBytes2(transl, msg.utf8()) << "</target>\n"; // ### In XLIFF 1.1, name is marked as required, and it must be unique // This is questionable behaviour, and was brought up at the xliff-comments mailinglist. if (!msg.isPlural()) { writeLineNumber(t, msg, indent); writeComment(t, msg, indent); } indent-=2; writeIndent(t, indent); (*t) << "</trans-unit>\n"; }
static void writeMessage(QTextStream &ts, const TranslatorMessage &msg, const QRegExp &drops, int indent) { if (msg.isPlural()) { writeIndent(ts, indent); ts << "<group restype=\"" << restypePlurals << "\""; if (!msg.id().isEmpty()) ts << " id=\"" << msg.id() << "\""; if (msg.type() == TranslatorMessage::Obsolete) ts << " translate=\"no\""; ts << ">\n"; ++indent; writeLineNumber(ts, msg, indent); writeComment(ts, msg, drops, indent); writeTransUnits(ts, msg, drops, indent); --indent; writeIndent(ts, indent); ts << "</group>\n"; } else { writeTransUnits(ts, msg, drops, indent); } }
bool TSReader::read(Translator &translator) { STRING(both); STRING(byte); STRING(comment); STRING(context); STRING(defaultcodec); STRING(encoding); STRING(extracomment); STRING(filename); STRING(id); STRING(language); STRING(line); STRING(location); STRING(message); STRING(name); STRING(numerus); STRING(numerusform); STRING(obsolete); STRING(oldcomment); STRING(oldsource); STRING(source); STRING(sourcelanguage); STRING(translation); STRING(translatorcomment); STRING(true); STRING(TS); STRING(type); STRING(unfinished); STRING(userdata); STRING(utf8); STRING(value); //STRING(version); STRING(yes); static const QString strextrans(QLatin1String("extra-")); static const QString strUtf8(QLatin1String("UTF-8")); while (!atEnd()) { readNext(); if (isStartDocument()) { // <!DOCTYPE TS> //qDebug() << attributes(); } else if (isEndDocument()) { // <!DOCTYPE TS> //qDebug() << attributes(); } else if (isDTD()) { // <!DOCTYPE TS> //qDebug() << tokenString(); } else if (elementStarts(strTS)) { // <TS> //qDebug() << "TS " << attributes(); QHash<QString, int> currentLine; QString currentFile; QXmlStreamAttributes atts = attributes(); //QString version = atts.value(strversion).toString(); translator.setLanguageCode(atts.value(strlanguage).toString()); translator.setSourceLanguageCode(atts.value(strsourcelanguage).toString()); while (!atEnd()) { readNext(); if (isEndElement()) { // </TS> found, finish local loop break; } else if (isWhiteSpace()) { // ignore these, just whitespace } else if (elementStarts(strdefaultcodec)) { // <defaultcodec> const QString &codec = readElementText(); if (!codec.isEmpty()) translator.setCodecName(codec.toLatin1()); // </defaultcodec> } else if (isStartElement() && name().toString().startsWith(strextrans)) { // <extra-...> QString tag = name().toString(); translator.setExtra(tag.mid(6), readContents()); // </extra-...> } else if (elementStarts(strcontext)) { // <context> QString context; while (!atEnd()) { readNext(); if (isEndElement()) { // </context> found, finish local loop break; } else if (isWhiteSpace()) { // ignore these, just whitespace } else if (elementStarts(strname)) { // <name> context = readElementText(); // </name> } else if (elementStarts(strmessage)) { // <message> TranslatorMessage::References refs; QString currentMsgFile = currentFile; TranslatorMessage msg; msg.setId(attributes().value(strid).toString()); msg.setContext(context); msg.setType(TranslatorMessage::Finished); msg.setPlural(attributes().value(strnumerus) == stryes); const QStringRef &utf8Attr = attributes().value(strutf8); msg.setNonUtf8(utf8Attr == strboth); msg.setUtf8(msg.isNonUtf8() || utf8Attr == strtrue || attributes().value(strencoding) == strUtf8); while (!atEnd()) { readNext(); if (isEndElement()) { // </message> found, finish local loop msg.setReferences(refs); translator.append(msg); break; } else if (isWhiteSpace()) { // ignore these, just whitespace } else if (elementStarts(strsource)) { // <source>...</source> msg.setSourceText(readContents()); } else if (elementStarts(stroldsource)) { // <oldsource>...</oldsource> msg.setOldSourceText(readContents()); } else if (elementStarts(stroldcomment)) { // <oldcomment>...</oldcomment> msg.setOldComment(readContents()); } else if (elementStarts(strextracomment)) { // <extracomment>...</extracomment> msg.setExtraComment(readContents()); } else if (elementStarts(strtranslatorcomment)) { // <translatorcomment>...</translatorcomment> msg.setTranslatorComment(readContents()); } else if (elementStarts(strlocation)) { // <location/> QXmlStreamAttributes atts = attributes(); QString fileName = atts.value(strfilename).toString(); if (fileName.isEmpty()) { fileName = currentMsgFile; } else { if (refs.isEmpty()) currentFile = fileName; currentMsgFile = fileName; } const QString lin = atts.value(strline).toString(); if (lin.isEmpty()) { translator.setLocationsType(Translator::RelativeLocations); refs.append(TranslatorMessage::Reference(fileName, -1)); } else { bool bOK; int lineNo = lin.toInt(&bOK); if (bOK) { if (lin.startsWith(QLatin1Char('+')) || lin.startsWith(QLatin1Char('-'))) { lineNo = (currentLine[fileName] += lineNo); translator.setLocationsType(Translator::RelativeLocations); } else { translator.setLocationsType(Translator::AbsoluteLocations); } refs.append(TranslatorMessage::Reference(fileName, lineNo)); } } readContents(); } else if (elementStarts(strcomment)) { // <comment>...</comment> msg.setComment(readContents()); } else if (elementStarts(struserdata)) { // <userdata>...</userdata> msg.setUserData(readContents()); } else if (elementStarts(strtranslation)) { // <translation> QXmlStreamAttributes atts = attributes(); QStringRef type = atts.value(strtype); if (type == strunfinished) msg.setType(TranslatorMessage::Unfinished); else if (type == strobsolete) msg.setType(TranslatorMessage::Obsolete); if (msg.isPlural()) { QStringList translations; while (!atEnd()) { readNext(); if (isEndElement()) { break; } else if (isWhiteSpace()) { // ignore these, just whitespace } else if (elementStarts(strnumerusform)) { translations.append(readTransContents()); } else { handleError(); break; } } msg.setTranslations(translations); } else { msg.setTranslation(readTransContents()); } // </translation> } else if (isStartElement() && name().toString().startsWith(strextrans)) { // <extra-...> QString tag = name().toString(); msg.setExtra(tag.mid(6), readContents()); // </extra-...> } else { handleError(); } } // </message> } else { handleError(); } } // </context> } else { handleError(); } } // </TS> } else { handleError(); } } if (hasError()) { m_cd.appendError(errorString()); return false; } return true; }
static void writeTransUnits(QTextStream &ts, const TranslatorMessage &msg, const QRegExp &drops, int indent) { static int msgid; QString msgidstr = !msg.id().isEmpty() ? msg.id() : QString::fromAscii("_msg%1").arg(++msgid); QStringList translns = msg.translations(); QHash<QString, QString>::const_iterator it; QString pluralStr; QStringList sources(msg.sourceText()); if ((it = msg.extras().find(QString::fromLatin1("po-msgid_plural"))) != msg.extras().end()) sources.append(*it); QStringList oldsources; if (!msg.oldSourceText().isEmpty()) oldsources.append(msg.oldSourceText()); if ((it = msg.extras().find(QString::fromLatin1("po-old_msgid_plural"))) != msg.extras().end()) { if (oldsources.isEmpty()) { if (sources.count() == 2) oldsources.append(QString()); else pluralStr = QLatin1Char(' ') + QLatin1String(attribPlural) + QLatin1String("=\"yes\""); } oldsources.append(*it); } QStringList::const_iterator srcit = sources.begin(), srcend = sources.end(), oldsrcit = oldsources.begin(), oldsrcend = oldsources.end(), transit = translns.begin(), transend = translns.end(); int plural = 0; QString source; while (srcit != srcend || oldsrcit != oldsrcend || transit != transend) { QByteArray attribs; QByteArray state; if (msg.type() == TranslatorMessage::Obsolete) { if (!msg.isPlural()) attribs = " translate=\"no\""; } else if (msg.type() == TranslatorMessage::Finished) { attribs = " approved=\"yes\""; } else if (transit != transend && !transit->isEmpty()) { state = " state=\"needs-review-translation\""; } writeIndent(ts, indent); ts << "<trans-unit id=\"" << msgidstr; if (msg.isPlural()) ts << "[" << plural++ << "]"; ts << "\"" << attribs << ">\n"; ++indent; writeIndent(ts, indent); if (srcit != srcend) { source = *srcit; ++srcit; } // else just repeat last element ts << "<source xml:space=\"preserve\">" << protect(source) << "</source>\n"; bool puttrans = false; QString translation; if (transit != transend) { translation = *transit; translation.replace(QChar(Translator::BinaryVariantSeparator), QChar(Translator::TextVariantSeparator)); ++transit; puttrans = true; } do { if (oldsrcit != oldsrcend && !oldsrcit->isEmpty()) { writeIndent(ts, indent); ts << "<alt-trans>\n"; ++indent; writeIndent(ts, indent); ts << "<source xml:space=\"preserve\"" << pluralStr << '>' << protect(*oldsrcit) << "</source>\n"; if (!puttrans) { writeIndent(ts, indent); ts << "<target restype=\"" << restypeDummy << "\"/>\n"; } } if (puttrans) { writeIndent(ts, indent); ts << "<target xml:space=\"preserve\"" << state << ">" << protect(translation) << "</target>\n"; } if (oldsrcit != oldsrcend) { if (!oldsrcit->isEmpty()) { --indent; writeIndent(ts, indent); ts << "</alt-trans>\n"; } ++oldsrcit; } puttrans = false; } while (srcit == srcend && oldsrcit != oldsrcend); if (!msg.isPlural()) { writeLineNumber(ts, msg, indent); writeComment(ts, msg, drops, indent); } --indent; writeIndent(ts, indent); ts << "</trans-unit>\n"; } }