Changeset View
Changeset View
Standalone View
Standalone View
src/catalog/gettext/gettextexport.cpp
Context not available. | |||||
45 | #include <QTextCodec> | 45 | #include <QTextCodec> | ||
---|---|---|---|---|---|
46 | #include <QList> | 46 | #include <QList> | ||
47 | #include <QTextStream> | 47 | #include <QTextStream> | ||
48 | #include <QEventLoop> | | |||
49 | #include <QStringBuilder> | 48 | #include <QStringBuilder> | ||
49 | #include <QTextBoundaryFinder> | ||||
50 | 50 | | |||
51 | 51 | | |||
52 | using namespace GettextCatalog; | 52 | using namespace GettextCatalog; | ||
Context not available. | |||||
102 | if (! msgctxt.isEmpty() || catalogItem.keepEmptyMsgCtxt()) | 102 | if (! msgctxt.isEmpty() || catalogItem.keepEmptyMsgCtxt()) | ||
103 | writeKeyword(stream, QStringLiteral("msgctxt"), msgctxt); | 103 | writeKeyword(stream, QStringLiteral("msgctxt"), msgctxt); | ||
104 | 104 | | |||
105 | writeKeyword(stream, QStringLiteral("msgid"), catalogItem.msgid(), true, catalogItem.prependEmptyForMsgid()); | 105 | writeKeyword(stream, QStringLiteral("msgid"), catalogItem.msgid(), catalogItem.prependEmptyForMsgid()); | ||
106 | if (catalogItem.isPlural()) | 106 | if (catalogItem.isPlural()) | ||
107 | writeKeyword(stream, QStringLiteral("msgid_plural"), catalogItem.msgid(1), true, catalogItem.prependEmptyForMsgid()); | 107 | writeKeyword(stream, QStringLiteral("msgid_plural"), catalogItem.msgid(1), catalogItem.prependEmptyForMsgid()); | ||
108 | 108 | | |||
109 | if (!catalogItem.isPlural()) | 109 | if (!catalogItem.isPlural()) | ||
110 | writeKeyword(stream, QStringLiteral("msgstr"), catalogItem.msgstr(), true, catalogItem.prependEmptyForMsgstr()); | 110 | writeKeyword(stream, QStringLiteral("msgstr"), catalogItem.msgstr(), catalogItem.prependEmptyForMsgstr()); | ||
111 | else { | 111 | else { | ||
112 | qCDebug(LOKALIZE_LOG) << "Saving gettext plural form"; | 112 | qCDebug(LOKALIZE_LOG) << "Saving gettext plural form"; | ||
113 | //TODO check len of the actual stringlist?? | 113 | //TODO check len of the actual stringlist?? | ||
114 | const int forms = catalog->numberOfPluralForms(); | 114 | const int forms = catalog->numberOfPluralForms(); | ||
115 | for (int i = 0; i < forms; ++i) { | 115 | for (int i = 0; i < forms; ++i) { | ||
116 | QString keyword = QStringLiteral("msgstr[") + QString::number(i) + ']'; | 116 | QString keyword = QStringLiteral("msgstr[") + QString::number(i) + ']'; | ||
117 | writeKeyword(stream, keyword, catalogItem.msgstr(i), true, catalogItem.prependEmptyForMsgstr()); | 117 | writeKeyword(stream, keyword, catalogItem.msgstr(i), catalogItem.prependEmptyForMsgstr()); | ||
118 | } | 118 | } | ||
119 | } | 119 | } | ||
120 | } | 120 | } | ||
Context not available. | |||||
142 | return OK; | 142 | return OK; | ||
143 | } | 143 | } | ||
144 | 144 | | |||
145 | QStringList GettextExportPlugin::tokenize(const QString &text) { | ||||
146 | QStringList tokens; | ||||
147 | int lastpos = 0; | ||||
148 | | ||||
149 | auto finder = new QTextBoundaryFinder(QTextBoundaryFinder::Line, text); | ||||
150 | while (finder->toNextBoundary() != -1) { | ||||
151 | QString token = text.mid(lastpos, finder->position() - lastpos); | ||||
152 | // Hack to mocking gettext's write-po.c wrapping algorithm: | ||||
153 | // "Don't break immediately before the "\n" at the end." | ||||
154 | if (token.indexOf(QStringLiteral("\\n")) == 0 && !tokens.isEmpty()) { | ||||
155 | token = tokens.takeLast() + token; | ||||
156 | } | ||||
157 | tokens << token; | ||||
158 | lastpos = finder->position(); | ||||
159 | } | ||||
160 | return(tokens); | ||||
161 | } | ||||
162 | | ||||
145 | void GettextExportPlugin::writeComment(QTextStream& stream, const QString& comment) const | 163 | void GettextExportPlugin::writeComment(QTextStream& stream, const QString& comment) const | ||
146 | { | 164 | { | ||
147 | if (!comment.isEmpty()) { | 165 | if (!comment.isEmpty()) { | ||
Context not available. | |||||
182 | } | 200 | } | ||
183 | } | 201 | } | ||
184 | 202 | | |||
185 | void GettextExportPlugin::writeKeyword(QTextStream& stream, const QString& keyword, QString text, bool containsHtml, bool startedWithEmptyLine) const | 203 | void GettextExportPlugin::writeKeyword(QTextStream& stream, const QString& keyword, QString text, bool startedWithEmptyLine) const | ||
186 | { | 204 | { | ||
187 | if (text.isEmpty()) { | 205 | if (text.isEmpty()) { | ||
188 | // Whatever the wrapping mode, an empty line is an empty line | 206 | // Whatever the wrapping mode, an empty line is an empty line | ||
Context not available. | |||||
224 | } else if (m_wrapWidth <= 3) { | 242 | } else if (m_wrapWidth <= 3) { | ||
225 | // No change in wrapping | 243 | // No change in wrapping | ||
226 | QStringList list = text.split('\n'); | 244 | QStringList list = text.split('\n'); | ||
227 | if (list.count() > 1 || startedWithEmptyLine /* || keyword.length()+3+text.length()>=80*/) | 245 | if (list.count() > 1 || startedWithEmptyLine) | ||
228 | list.prepend(QString()); | 246 | list.prepend(QString()); | ||
229 | 247 | | |||
230 | stream << keyword << QStringLiteral(" "); | 248 | stream << keyword << QStringLiteral(" "); | ||
231 | QStringList::const_iterator it; | 249 | for (QString& it : list) | ||
232 | for (it = list.constBegin(); it != list.constEnd(); ++it) | 250 | stream << QStringLiteral("\"") << (it) << QStringLiteral("\"\n"); | ||
233 | stream << QStringLiteral("\"") << (*it) << QStringLiteral("\"\n"); | | |||
234 | 251 | | |||
235 | return; | 252 | return; | ||
236 | } | 253 | } | ||
237 | 254 | | |||
238 | // lazy wrapping | 255 | int max = m_wrapWidth - 2; | ||
239 | QStringList list = text.split('\n', QString::SkipEmptyParts); | | |||
240 | | ||||
241 | if (text.startsWith('\n')) | | |||
242 | list.prepend(QString()); | | |||
243 | | ||||
244 | if (list.isEmpty()) | | |||
245 | list.append(QString()); | | |||
246 | 256 | | |||
247 | //static QRegExp breakStopReForHtml("[ >.%/:,]", Qt::CaseSensitive, QRegExp::Wildcard); | 257 | // Remove newlines and re-add them where they needed | ||
248 | //static QRegExp breakStopReForText("[ .%/:,]", Qt::CaseSensitive, QRegExp::Wildcard); | 258 | text.remove(QStringLiteral("\n")); | ||
249 | static QRegExp breakStopReForHtml(QStringLiteral("[ >%]"), Qt::CaseSensitive, QRegExp::Wildcard); | 259 | text.replace(QStringLiteral("\\n"), QStringLiteral("\\n\n")); | ||
250 | static QRegExp breakStopReForText(QStringLiteral("[ &%]"), Qt::CaseSensitive, QRegExp::Wildcard); | 260 | QStringList list = text.split(QStringLiteral("\n"), QString::KeepEmptyParts); | ||
251 | QRegExp breakStopRe = containsHtml ? breakStopReForHtml : breakStopReForText; | 261 | QStringList wrapped_list; | ||
252 | 262 | | |||
253 | int max = m_wrapWidth - 2; | 263 | // Iterate each newline string | ||
254 | bool prependedEmptyLine = false; | 264 | for (const QString& it : list) { | ||
255 | QStringList::iterator itm; | 265 | QStringList words = tokenize(it); | ||
256 | for (itm = list.begin(); itm != list.end(); ++itm) { | 266 | QString wrapped_string; | ||
257 | if (list.count() == 1 && keyword.length() + 1 + itm->length() >= max) { | | |||
258 | prependedEmptyLine = true; | | |||
259 | itm = list.insert(itm, QString()); | | |||
260 | } | | |||
261 | 267 | | |||
262 | if (itm->length() > max) { | 268 | for (const QString& word : words) { | ||
263 | int pos = itm->lastIndexOf(breakStopRe, max - 1); | 269 | if (wrapped_string.length() + word.length() < max) { | ||
264 | if (pos > (max / 2)) { | 270 | wrapped_string += word; | ||
265 | int pos2 = itm->indexOf(QLatin1Char('<'), pos); | | |||
266 | if (pos2 > 0 && pos2 < max - 1) { | | |||
267 | pos = itm->indexOf(QLatin1Char('<'), pos); | | |||
268 | ++pos; | | |||
269 | } | | |||
270 | } else { | 271 | } else { | ||
271 | if (itm->at(max - 1) == QLatin1Char('\\')) { | 272 | wrapped_list.append(wrapped_string); | ||
272 | do { | 273 | wrapped_string = word; | ||
273 | --max; | | |||
274 | } while (max >= 2 && itm->at(max - 1) == QLatin1Char('\\')); | | |||
275 | } | | |||
276 | pos = max; | | |||
277 | //Restore the max variable to the m_wordWrap - 2 value | | |||
278 | max = m_wrapWidth - 2; | | |||
279 | } | | |||
280 | //itm=list.insert(itm,itm->left(pos)); | | |||
281 | QString t = *itm; | | |||
282 | itm = list.insert(itm, t); | | |||
283 | ++itm; | | |||
284 | if (itm != list.end()) { | | |||
285 | (*itm) = itm->remove(0, pos); | | |||
286 | --itm; | | |||
287 | if (itm != list.end()) | | |||
288 | itm->truncate(pos); | | |||
289 | } | 274 | } | ||
290 | } | 275 | } | ||
276 | if (!wrapped_string.isEmpty()) { | ||||
277 | wrapped_list.append(wrapped_string); | ||||
278 | } | ||||
291 | } | 279 | } | ||
292 | 280 | | |||
293 | if (!prependedEmptyLine && list.count() > 1) | 281 | if (wrapped_list.count() > 1 || keyword.length() + 1 + wrapped_list.first().length() >= max) { | ||
294 | list.prepend(QString()); | 282 | wrapped_list.prepend(QString()); | ||
283 | } | ||||
295 | 284 | | |||
296 | stream << keyword << QStringLiteral(" "); | 285 | stream << keyword << QStringLiteral(" "); | ||
297 | 286 | for (const QString& it : wrapped_list) { | |||
298 | QStringList::const_iterator it; | 287 | stream << QStringLiteral("\"") << (it) << QStringLiteral("\"\n"); | ||
299 | for (it = list.constBegin(); it != list.constEnd(); ++it) | 288 | } | ||
300 | stream << QStringLiteral("\"") << (*it) << QStringLiteral("\"\n"); | | |||
301 | } | 289 | } | ||
Context not available. |