33 #include <QStringBuilder>
40 #include <kdatetime.h>
42 #include <kio/netaccess.h>
43 #include <ktemporaryfile.h>
49 #define NUM_LANG_WITH_INFO 40
95 "nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;",
96 "nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;",
97 "nplurals=2; plural=(n != 1);",
98 "nplurals=2; plural=(n != 1);",
99 "nplurals=2; plural=(n != 1);",
100 "nplurals=2; plural=(n != 1);",
101 "nplurals=2; plural=(n != 1);",
102 "nplurals=2; plural=(n != 1);",
103 "nplurals=2; plural=(n != 1);",
104 "nplurals=2; plural=(n != 1);",
105 "nplurals=2; plural=(n != 1);",
106 "nplurals=2; plural=(n != 1);",
107 "nplurals=2; plural=(n != 1);",
108 "nplurals=2; plural=(n > 1);",
109 "nplurals=3; plural=n==1 ? 0 : n==2 ? 1 : 2;",
110 "nplurals=2; plural=(n != 1);",
111 "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);",
112 "nplurals=2; plural=(n != 1);",
113 "nplurals=2; plural=(n != 1);",
114 "nplurals=1; plural=0;",
115 "nplurals=1; plural=0;",
116 "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2);",
117 "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);",
118 "nplurals=2; plural=(n != 1);",
119 "nplurals=2; plural=(n != 1);",
120 "nplurals=2; plural=(n != 1);",
121 "nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);",
122 "nplurals=2; plural=(n != 1);",
123 "nplurals=2; plural=(n > 1);",
124 "nplurals=3; plural=n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < 20)) ? 1 : 2;",
125 "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);",
126 "nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;",
127 "nplurals=4; plural=(n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || n%100==4 ? 3 : 0);",
128 "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);",
129 "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);",
130 "nplurals=2; plural=(n != 1);",
131 "nplurals=1; plural=0;",
132 "nplurals=2; plural=(n > 1);",
133 "nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);",
134 "nplurals=1; plural=0;"
140 QRegExp rxplural(
"Plural-Forms:\\s*nplurals=(.);");
141 if (rxplural.indexIn(header) == -1)
144 int result=rxplural.cap(1).toShort(&ok);
153 QRegExp rxplural(
"nplurals=(.);");
154 if (rxplural.indexIn(expr) == -1)
157 int result=rxplural.cap(1).toShort(&ok);
164 QByteArray l(lang.toUtf8());
169 if (KDE_ISLIKELY( i>=0 ))
170 return QString::fromLatin1(
pInfo[i]);
175 qWarning()<<
"gonna call msginit";
176 QString def=
"nplurals=2; plural=n != 1;";
178 QStringList arguments;
179 arguments <<
"-l" << lang
185 msginit.start(
"msginit", arguments);
187 msginit.waitForStarted(5000);
188 if (KDE_ISUNLIKELY( msginit.state()!=QProcess::Running ))
195 "# SOME DESCRIPTIVE TITLE.\n"
196 "# Copyright (C) YEAR Free Software Foundation, Inc.\n"
197 "# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.\n"
202 "\"Project-Id-Version: PACKAGE VERSION\\n\"\n"
203 "\"POT-Creation-Date: 2002-06-25 03:23+0200\\n\"\n"
204 "\"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\\n\"\n"
205 "\"Last-Translator: FULL NAME <EMAIL@ADDRESS>\\n\"\n"
206 "\"Language-Team: LANGUAGE <LL@li.org>\\n\"\n"
207 "\"Language: LL\\n\"\n"
208 "\"MIME-Version: 1.0\\n\"\n"
209 "\"Content-Type: text/plain; charset=UTF-8\\n\"\n"
210 "\"Content-Transfer-Encoding: ENCODING\\n\"\n"
213 msginit.closeWriteChannel();
215 if (KDE_ISUNLIKELY( !msginit.waitForFinished(5000) ))
217 kWarning()<<
"msginit error";
222 QByteArray result = msginit.readAll();
223 int pos = result.indexOf(
"Plural-Forms: ");
224 if (KDE_ISUNLIKELY( pos==-1 ))
231 int end = result.indexOf(
'"',pos);
232 if (KDE_ISUNLIKELY( pos==-1 ))
238 return QString( result.mid(pos,end-pos-2) );
246 int& numberOfPluralForms,
247 const QString& CatalogProjectId,
248 bool generatedFromDocbook,
249 bool belongsToProject,
253 QStringList headerList(header.split(
'\n',QString::SkipEmptyParts));
254 QStringList commentList(comment.split(
'\n',QString::SkipEmptyParts));
257 QStringList::Iterator it,ait;
259 QString authorNameEmail;
265 temp=
"Last-Translator: "%authorNameEmail%
"\\n";
267 QRegExp lt(
"^ *Last-Translator:.*");
268 for ( it = headerList.begin(),found=
false; it != headerList.end() && !found; ++it )
270 if (it->contains(lt))
272 if (forSaving) *it = temp;
276 if (KDE_ISUNLIKELY( !found ))
277 headerList.append(temp);
279 QString dateTimeString = KDateTime::currentLocalDateTime().toString(
"%Y-%m-%d %H:%M%z");
280 temp=
"PO-Revision-Date: "%dateTimeString%
"\\n";
281 QRegExp poRevDate(
"^ *PO-Revision-Date:.*");
282 for ( it = headerList.begin(),found=
false; it != headerList.end() && !found; ++it )
284 found=it->contains(poRevDate);
285 if (found && forSaving) *it = temp;
287 if (KDE_ISUNLIKELY( !found ))
288 headerList.append(temp);
290 temp=
"Project-Id-Version: "%CatalogProjectId%
"\\n";
292 QRegExp projectIdVer(
"^ *Project-Id-Version:.*");
293 for ( it = headerList.begin(),found=
false; it != headerList.end() && !found; ++it )
295 found=it->contains(projectIdVer);
296 if (found && it->contains(
"PACKAGE VERSION"))
299 if (KDE_ISUNLIKELY( !found ))
300 headerList.append(temp);
309 static KConfig* allLanguagesConfig=0;
310 if (!allLanguagesConfig)
312 allLanguagesConfig =
new KConfig(
"all_languages", KConfig::NoGlobals,
"locale");
313 allLanguagesConfig->setLocale(QString());
315 QRegExp langTeamRegExp(
"^ *Language-Team:.*");
316 for ( it = headerList.begin(),found=
false; it != headerList.end() && !found; ++it )
318 found=it->contains(langTeamRegExp);
322 QMap<QString,QString> map;
323 foreach (
const QString &runningLangCode, KGlobal::locale()->allLanguagesList())
325 KConfigGroup cg(allLanguagesConfig, runningLangCode);
326 map[cg.readEntry(
"Name")]=runningLangCode;
329 kWarning()<<
"seems that all_languages file is missing (usually located under /usr/share/locale)";
331 QRegExp re(
"^ *Language-Team: *(.*) *<([^>]*)>");
332 if (re.indexIn(*it) != -1 )
334 if (map.contains( re.cap(1).trimmed() ))
336 language=re.cap(1).trimmed();
337 mailingList=re.cap(2).trimmed();
338 langCode=map.value(language);
346 if (language.isEmpty())
349 KConfigGroup cg(allLanguagesConfig, langCode);
350 language=cg.readEntry(
"Name");
351 if (language.isEmpty())
355 if (mailingList.isEmpty() || belongsToProject)
365 temp=
"Language-Team: "%language%
" <"%mailingList%
'>';
367 if (KDE_ISLIKELY( found ))
370 headerList.append(temp);
372 QRegExp langCodeRegExp(
"^ *Language: *([^ \\\\]*)");
373 temp=
"Language: "%langCode%
"\\n";
374 for ( it = headerList.begin(),found=
false; it != headerList.end() && !found; ++it )
376 found=(langCodeRegExp.indexIn(*it)!=-1);
377 if (found && langCodeRegExp.cap(1).isEmpty())
381 if (KDE_ISUNLIKELY( !found ))
382 headerList.append(temp);
384 temp=
"Content-Type: text/plain; charset="%codec->name()%
"\\n";
385 for ( it = headerList.begin(),found=
false; it != headerList.end() && !found; ++it )
387 found=it->contains(QRegExp(
"^ *Content-Type:.*"));
390 if (KDE_ISUNLIKELY( !found ))
391 headerList.append(temp);
395 temp=
"Content-Transfer-Encoding: 8bit\\n";
397 for ( it = headerList.begin(),found=
false; it != headerList.end() && !found; ++it )
398 found=it->contains(QRegExp(
"^ *Content-Transfer-Encoding:.*"));
400 headerList.append(temp);
403 temp=
"MIME-Version: 1.0\\n";
404 for ( it = headerList.begin(),found=
false; it != headerList.end()&& !found; ++it )
406 found=it->contains(QRegExp(
"^ *MIME-Version:"));
407 if (found) *it = temp;
409 if (KDE_ISUNLIKELY( !found ))
410 headerList.append(temp);
415 for ( it = headerList.begin(),found=
false; it != headerList.end()&& !found; ++it )
416 found=it->contains(QRegExp(
"^ *Plural-Forms:"));
425 if (generatedFromDocbook)
429 kWarning()<<
"No plural form info in header, using project-defined one"<<langCode;
434 QRegExp pf(
"^ *Plural-Forms:\\s*nplurals.*\\\\n");
436 temp=QString(
"Plural-Forms: %1\\n").arg(t);
437 it->replace(pf,temp);
442 kWarning()<<
"no... smth went wrong :(\ncheck your gettext install";
447 numberOfPluralForms=num;
450 else if ( !generatedFromDocbook)
456 headerList.append(QString(
"Plural-Forms: %1\\n").arg(t));
459 temp=
"X-Generator: Lokalize %1\\n";
462 for ( it = headerList.begin(),found=
false; it != headerList.end()&& !found; ++it )
464 found=it->contains(QRegExp(
"^ *X-Generator:.*"));
465 if (found) *it = temp;
467 if (KDE_ISUNLIKELY( !found ))
468 headerList.append(temp);
471 header=headerList.join(
"\n");
476 QRegExp fsfc(
"^# *Copyright (\\(C\\)|\\x00a9).*Free Software Foundation, Inc");
477 for ( it = commentList.begin(),found=
false; it != commentList.end()&&!found; ++it )
479 found=it->contains( fsfc ) ;
481 it->replace(
"YEAR", QDate::currentDate().toString(
"yyyy"));
501 if ( ( !usePrefs || saveOptions.updateDescription )
502 && ( !saveOptions.descriptionString.isEmpty() ) )
504 temp =
"# "+saveOptions.descriptionString;
505 temp.replace(
"@PACKAGE@", packageName());
506 temp.replace(
"@LANGUAGE@", identityOptions.languageName);
507 temp = temp.trimmed();
510 QString regexpstr =
"^#\\s+" +
QRegExp::escape( saveOptions.descriptionString.trimmed() ) +
"\\s*$";
511 regexpstr.replace(
"@PACKAGE@",
".*" );
512 regexpstr.replace(
"@LANGUAGE@",
".*" );
514 QRegExp regexp ( regexpstr );
517 QRegExp regexpUntranslated (
"^#\\s+translation of .* to .*\\s*$" );
520 kDebug () <<
"Temp is '" << temp <<
"'";
523 bool foundTemplate=
false;
525 it = commentList.begin();
526 while ( it != commentList.end() )
528 kDebug () <<
"testing '" << (*it) <<
"'";
529 bool deleteItem =
false;
533 kDebug () <<
"Match ";
539 else if ( regexp.indexIn( *it ) >= 0 )
544 else if ( regexpUntranslated.indexIn( *it ) >= 0 )
549 else if ( (*it) ==
"# SOME DESCRIPTIVE TITLE." )
556 it = commentList.erase( it );
560 if (!found) commentList.prepend(temp);
570 QStringList foundAuthors;
572 temp=
"# "%authorNameEmail%
", "%QDate::currentDate().toString(
"yyyy")%
'.';
575 QRegExp regexpAuthorYear(
"^#.*(<.+@.+>)?,\\s*([\\d]+[\\d\\-, ]*|YEAR)" );
576 QRegExp regexpYearAlone(
"^# , \\d{4}.?\\s*$" );
577 if (commentList.isEmpty())
579 commentList.append(temp);
580 commentList.append(QString());
584 it = commentList.begin();
585 while ( it != commentList.end() )
587 bool deleteItem =
false;
588 if ( it->indexOf(
"copyright", 0, Qt::CaseInsensitive ) != -1 )
592 else if ( it->contains( QRegExp(
"#, *fuzzy") ) )
594 else if ( it->contains( regexpYearAlone ) )
601 else if ( it->contains(
"# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.") )
603 else if ( it->contains(
"# SOME DESCRIPTIVE TITLE"))
605 else if ( it->contains( regexpAuthorYear ) )
607 if ( !foundAuthors.contains( (*it) ) )
610 foundAuthors.append( (*it) );
617 it = commentList.erase( it );
622 if ( !foundAuthors.isEmpty() )
625 bool foundAuthor =
false;
627 const QString cy = QDate::currentDate().toString(
"yyyy");
629 ait = foundAuthors.end();
630 for ( it = foundAuthors.begin() ; it!=foundAuthors.end(); ++it )
635 if ( it->contains( cy ) )
644 foundAuthors.append(temp);
645 else if ( ait != foundAuthors.end() )
648 const int index = (*ait).lastIndexOf( QRegExp(
"[\\d]+[\\d\\-, ]*") );
652 ait->insert(index+1,
", "%cy);
655 kDebug() <<
"INTERNAL ERROR: author found but iterator dangling!";
660 foundAuthors.append(temp);
663 foreach (QString author, foundAuthors)
666 if ( !author.endsWith(
'.') ) author +=
'.';
667 commentList.append(author);
672 comment=commentList.join(
"\n");
static Project * instance()
QString langCode() const
Get LangCode.
static QString defaultLangCode()
Get DefaultLangCode.
static QString authorEmail()
Get authorEmail.
static QString authorName()
Get authorName.
static QString defaultMailingList()
Get DefaultMailingList.
static QString escape(QString str)
QString mailingList() const
Get MailingList.