1 /**************************************************************************** |
1 /**************************************************************************** |
2 ** |
2 ** |
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
4 ** All rights reserved. |
4 ** All rights reserved. |
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
6 ** |
6 ** |
7 ** This file is part of the Qt Linguist of the Qt Toolkit. |
7 ** This file is part of the Qt Linguist of the Qt Toolkit. |
8 ** |
8 ** |
48 #include <QtCore/QMap> |
48 #include <QtCore/QMap> |
49 #include <QtCore/QStringList> |
49 #include <QtCore/QStringList> |
50 #include <QtCore/QTextCodec> |
50 #include <QtCore/QTextCodec> |
51 #include <QtCore/QVector> |
51 #include <QtCore/QVector> |
52 |
52 |
53 typedef QList<TranslatorMessage> TML; |
|
54 typedef QMap<QString, TranslatorMessage> TMM; |
|
55 |
|
56 |
53 |
57 QT_BEGIN_NAMESPACE |
54 QT_BEGIN_NAMESPACE |
58 |
55 |
59 static bool isDigitFriendly(QChar c) |
56 static bool isDigitFriendly(QChar c) |
60 { |
57 { |
61 return c.isPunct() || c.isSpace(); |
58 return c.isPunct() || c.isSpace(); |
62 } |
59 } |
63 |
60 |
64 static int numberLength(const QString &s, int i) |
61 static int numberLength(const QString &s, int i) |
65 { |
62 { |
66 if (i < s.size() || !s.at(i).isDigit()) |
63 if (i >= s.size() || !s.at(i).isDigit()) |
67 return 0; |
64 return 0; |
68 |
65 |
69 int pos = i; |
66 int pos = i; |
70 do { |
67 do { |
71 ++i; |
68 ++i; |
88 static QString zeroKey(const QString &key) |
85 static QString zeroKey(const QString &key) |
89 { |
86 { |
90 QString zeroed; |
87 QString zeroed; |
91 bool metSomething = false; |
88 bool metSomething = false; |
92 |
89 |
93 for (int i = 0; i != key.size(); ++i) { |
90 for (int i = 0; i < key.size(); ++i) { |
94 int len = numberLength(key, i); |
91 int len = numberLength(key, i); |
95 if (len > 0) { |
92 if (len > 0) { |
96 i += len; |
93 i += len; |
97 zeroed.append(QLatin1Char('0')); |
94 zeroed.append(QLatin1Char('0')); |
98 metSomething = true; |
95 metSomething = true; |
223 |
220 |
224 Returns the number of additional messages that this heuristic translated. |
221 Returns the number of additional messages that this heuristic translated. |
225 */ |
222 */ |
226 int applyNumberHeuristic(Translator &tor) |
223 int applyNumberHeuristic(Translator &tor) |
227 { |
224 { |
228 TMM translated, untranslated; |
225 QMap<QString, QPair<QString, QString> > translated; |
229 TMM::Iterator t, u; |
226 QVector<bool> untranslated(tor.messageCount()); |
230 TML all = tor.messages(); |
|
231 TML::Iterator it; |
|
232 int inserted = 0; |
227 int inserted = 0; |
233 |
228 |
234 for (it = all.begin(); it != all.end(); ++it) { |
229 for (int i = 0; i < tor.messageCount(); ++i) { |
235 bool hasTranslation = it->isTranslated(); |
230 const TranslatorMessage &msg = tor.message(i); |
236 if (it->type() == TranslatorMessage::Unfinished) { |
231 bool hasTranslation = msg.isTranslated(); |
|
232 if (msg.type() == TranslatorMessage::Unfinished) { |
237 if (!hasTranslation) |
233 if (!hasTranslation) |
238 untranslated.insert(it->context() + QLatin1Char('\n') |
234 untranslated[i] = true; |
239 + it->sourceText() + QLatin1Char('\n') |
235 } else if (hasTranslation && msg.translations().count() == 1) { |
240 + it->comment(), *it); |
236 const QString &key = zeroKey(msg.sourceText()); |
241 } else if (hasTranslation && it->translations().count() == 1) { |
237 if (!key.isEmpty()) |
242 translated.insert(zeroKey(it->sourceText()), *it); |
238 translated.insert(key, qMakePair(msg.sourceText(), msg.translation())); |
243 } |
239 } |
244 } |
240 } |
245 |
241 |
246 for (u = untranslated.begin(); u != untranslated.end(); ++u) { |
242 for (int i = 0; i < tor.messageCount(); ++i) { |
247 t = translated.find(zeroKey((*u).sourceText())); |
243 if (untranslated[i]) { |
248 if (t != translated.end() && !t.key().isEmpty() |
244 TranslatorMessage &msg = tor.message(i); |
249 && t->sourceText() != u->sourceText()) { |
245 const QString &key = zeroKey(msg.sourceText()); |
250 u->setTranslation(translationAttempt(t->translation(), t->sourceText(), |
246 if (!key.isEmpty()) { |
251 u->sourceText())); |
247 QMap<QString, QPair<QString, QString> >::ConstIterator t = |
252 inserted++; |
248 translated.constFind(key); |
|
249 if (t != translated.constEnd() && t->first != msg.sourceText()) { |
|
250 msg.setTranslation(translationAttempt(t->second, t->first, |
|
251 msg.sourceText())); |
|
252 inserted++; |
|
253 } |
|
254 } |
253 } |
255 } |
254 } |
256 } |
255 return inserted; |
257 return inserted; |
256 } |
258 } |
257 |
259 |
266 Returns the number of additional messages that this heuristic translated. |
268 Returns the number of additional messages that this heuristic translated. |
267 */ |
269 */ |
268 |
270 |
269 int applySameTextHeuristic(Translator &tor) |
271 int applySameTextHeuristic(Translator &tor) |
270 { |
272 { |
271 TMM translated; |
273 QMap<QString, QStringList> translated; |
272 TMM avoid; |
274 QMap<QString, bool> avoid; // Want a QTreeSet, in fact |
273 TMM::Iterator t; |
275 QVector<bool> untranslated(tor.messageCount()); |
274 TML untranslated; |
|
275 TML::Iterator u; |
|
276 TML all = tor.messages(); |
|
277 TML::Iterator it; |
|
278 int inserted = 0; |
276 int inserted = 0; |
279 |
277 |
280 for (it = all.begin(); it != all.end(); ++it) { |
278 for (int i = 0; i < tor.messageCount(); ++i) { |
281 if (!it->isTranslated()) { |
279 const TranslatorMessage &msg = tor.message(i); |
282 if (it->type() == TranslatorMessage::Unfinished) |
280 if (!msg.isTranslated()) { |
283 untranslated.append(*it); |
281 if (msg.type() == TranslatorMessage::Unfinished) |
|
282 untranslated[i] = true; |
284 } else { |
283 } else { |
285 QString key = it->sourceText(); |
284 const QString &key = msg.sourceText(); |
286 t = translated.find(key); |
285 QMap<QString, QStringList>::ConstIterator t = translated.constFind(key); |
287 if (t != translated.end()) { |
286 if (t != translated.constEnd()) { |
288 /* |
287 /* |
289 The same source text is translated at least two |
288 The same source text is translated at least two |
290 different ways. Do nothing then. |
289 different ways. Do nothing then. |
291 */ |
290 */ |
292 if (t->translations() != it->translations()) { |
291 if (*t != msg.translations()) { |
293 translated.remove(key); |
292 translated.remove(key); |
294 avoid.insert(key, *it); |
293 avoid.insert(key, true); |
295 } |
294 } |
296 } else if (!avoid.contains(key)) { |
295 } else if (!avoid.contains(key)) { |
297 translated.insert(key, *it); |
296 translated.insert(key, msg.translations()); |
298 } |
297 } |
299 } |
298 } |
300 } |
299 } |
301 |
300 |
302 for (u = untranslated.begin(); u != untranslated.end(); ++u) { |
301 for (int i = 0; i < tor.messageCount(); ++i) { |
303 QString key = u->sourceText(); |
302 if (untranslated[i]) { |
304 t = translated.find(key); |
303 TranslatorMessage &msg = tor.message(i); |
305 if (t != translated.end()) { |
304 QMap<QString, QStringList>::ConstIterator t = translated.constFind(msg.sourceText()); |
306 u->setTranslations(t->translations()); |
305 if (t != translated.constEnd()) { |
307 ++inserted; |
306 msg.setTranslations(*t); |
|
307 ++inserted; |
|
308 } |
308 } |
309 } |
309 } |
310 } |
310 return inserted; |
311 return inserted; |
311 } |
312 } |
312 |
313 |