• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdesdk API Reference
  • KDE Home
  • Contact Us
 

lokalize

  • sources
  • kde-4.14
  • kdesdk
  • lokalize
  • src
  • catalog
  • gettext
gettextimport.cpp
Go to the documentation of this file.
1 /* ****************************************************************************
2  This file is part of Lokalize
3  This file is based on the one from KBabel
4 
5  Copyright (C) 1999-2000 by Matthias Kiefer <matthias.kiefer@gmx.de>
6  2001-2003 by Stanislav Visnovsky <visnovsky@kde.org>
7  2006 by Nicolas GOUTTE <nicolasg@snafu.de>
8  2007 by Nick Shaforostoff <shafff@ukr.net>
9 
10  This program is free software; you can redistribute it and/or modify
11  it under the terms of the GNU General Public License as published by
12  the Free Software Foundation; either version 2 of the License, or
13  (at your option) any later version.
14 
15  This program is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  GNU General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with this program; if not, write to the Free Software
22  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 
24  In addition, as a special exception, the copyright holders give
25  permission to link the code of this program with any edition of
26  the Qt library by Trolltech AS, Norway (or with modified versions
27  of Qt that use the same license as Qt), and distribute linked
28  combinations including the two. You must obey the GNU General
29  Public License in all respects for all of the code used other than
30  Qt. If you modify this file, you may extend this exception to
31  your version of the file, but you are not obligated to do so. If
32  you do not wish to do so, delete this exception statement from
33  your version.
34 
35 **************************************************************************** */
36 
37 #define KDE_NO_DEBUG_OUTPUT
38 
39 #include "gettextimport.h"
40 //#include <resources.h>
41 
42 #include <QFile>
43 #include <QTime>
44 #include <QFileInfo>
45 #include <QRegExp>
46 #include <QTextCodec>
47 #include <QList>
48 #include <QTextStream>
49 #include <QEventLoop>
50 
51 #include <kapplication.h>
52 #include <kdebug.h>
53 #include <kgenericfactory.h>
54 #include <klocale.h>
55 
56 #include "catalogitem.h"
57 
58 using namespace GettextCatalog;
59 
60 // GettextImportPlugin::GettextImportPlugin(ExtraDataSaver* extraDataSaver)
61 // : CatalogImportPlugin()
62 // , _extraDataSaver(extraDataSaver)
63 GettextImportPlugin::GettextImportPlugin()
64  : CatalogImportPlugin()
65  , _rxMsgCtxt ("^msgctxt\\s*\".*\"$")
66  , _rxMsgId ("^msgid\\s*\".*\"$")
67  , _rxMsgIdPlural ("^msgid_plural\\s*\".*\"$")
68  , _rxMsgIdPluralBorked("^msgid_plural\\s*\"?.*\"?$")
69  , _rxMsgIdBorked ("^msgid\\s*\"?.*\"?$")
70  , _rxMsgIdRemQuotes ("^msgid\\s*\"")
71  , _rxMsgLineRemEndQuote ("\"$")
72  , _rxMsgLineRemStartQuote ("^\"")
73  , _rxMsgLine ("^\".*\\n?\"$")
74  , _rxMsgLineBorked ("^\"?.+\\n?\"?$")
75  , _rxMsgStr ("^msgstr\\s*\".*\\n?\"$")
76  , _rxMsgStrOther ("^msgstr\\s*\"?.*\\n?\"?$")
77  , _rxMsgStrPluralStart("^msgstr\\[0\\]\\s*\".*\\n?\"$")
78  , _rxMsgStrPluralStartBorked ("^msgstr\\[0\\]\\s*\"?.*\\n?\"?$")
79  , _rxMsgStrPlural ("^msgstr\\[[0-9]+\\]\\s*\".*\\n?\"$")
80  , _rxMsgStrPluralBorked ("^msgstr\\[[0-9]\\]\\s*\"?.*\\n?\"?$")
81  , _rxMsgStrRemQuotes ("^msgstr\\s*\"?")
82 // , _rxMsgId ("^msgid\\s*\"?.*\"?$")
83  , _obsoleteStart("#~")
84  , _msgctxtStart("msgctxt")
85 
86 {
87 }
88 
89 ConversionStatus GettextImportPlugin::load(QIODevice* device)
90 {
91  _testBorked=false;
92  _errorLine=0;
93 
94  // find codec for file
95  // bool hadCodec;
96  QTextCodec* codec=codecForDevice(device/*, &hadCodec*/ );
97  QTextStream stream(device);
98  stream.seek(0);
99  stream.setCodec(codec);
100 
101  //QIODevice *dev = stream.device();
102  //int fileSize = dev->size();
103 
104  // if somethings goes wrong with the parsing, we don't have deleted the old contents
105  CatalogItem tempHeader;
106 
107  kDebug() << "start parsing...";
108  QTime aaa;
109  aaa.start();
110  // first read header
111  const ConversionStatus status = readEntry(stream);
112 
113  bool recoveredErrorInHeader = false;
114  if (KDE_ISUNLIKELY( status == RECOVERED_PARSE_ERROR ))
115  {
116  kDebug() << "Recovered error in header entry";
117  recoveredErrorInHeader = true;
118  }
119  else if (KDE_ISUNLIKELY( status != OK ))
120  {
121  kWarning() << "Parse error in header entry";
122  return status;
123  }
124 
125  bool reconstructedHeader=!_msgid.isEmpty() && !_msgid.first().isEmpty();
126  //kWarning() << "HEADER MSGID: " << _msgid;
127  //kWarning() << "HEADER MSGSTR: " << _msgstr;
128  if (KDE_ISUNLIKELY( reconstructedHeader ))
129  {
130  // The header must have an empty msgid
131  kWarning() << "Header entry has non-empty msgid. Creating a temporary header! " << _msgid;
132  tempHeader.setMsgid( QString() );
133  QString tmp(
134  "Content-Type: text/plain; charset=UTF-8\\n" // Unknown charset
135  "Content-Transfer-Encoding: 8bit\\n"
136  "Mime-Version: 1.0" );
137  tempHeader.setMsgstr( tmp);
138  // We keep the comment of the first entry, as it might really be a header comment (at least partially)
139  const QString comment( "# Header entry was created by Lokalize.\n#\n" + _comment );
140  tempHeader.setComment( comment );
141  recoveredErrorInHeader = true;
142  }
143  else
144  {
145  tempHeader.setMsgid( _msgid );
146  tempHeader.setMsgstr( _msgstr );
147  tempHeader.setComment( _comment );
148  }
149 // if(tempHeader.isFuzzy())
150 // {
151 // tempHeader.removeFuzzy();
152 // }
153 
154  // check if header seems to indicate docbook content generated by xml2pot
155  const bool docbookContent = tempHeader.msgstr().contains( "application/x-xml2pot" );
156 
157 
158 
159 
160 
161 
162 
163  // now parse the rest of the file
164  uint counter=0;
165  QList<int> errorIndex;
166  bool recoveredError=false;
167  bool docbookFile=false;
168 
169  ExtraDataSaver _extraDataSaver;
170  ConversionStatus success=OK;
171  while( !stream.atEnd() )
172  {
173  if (reconstructedHeader)
174  reconstructedHeader=false;
175  else
176  success=readEntry(stream);
177 
178  if(KDE_ISLIKELY(success==OK))
179  {
180  if( _obsolete )
181  _extraDataSaver(_comment);
182  else
183  {
184  CatalogItem tempCatItem;
185  tempCatItem.setPlural(_gettextPluralForm);
186  tempCatItem.setMsgid( _msgid, _msgidMultiline );
187  tempCatItem.setMsgstr( _msgstr, _msgstrMultiline );
188  if (_msgctxtPresent) tempCatItem.setMsgctxt( _msgctxt );
189  tempCatItem.setComment( _comment );
190 
191  // add new entry to the list of entries
192  appendCatalogItem(tempCatItem);
193  // check if first comment seems to indicate a docbook source file
194  if(counter==0)
195  docbookFile = tempCatItem.comment().contains(".docbook" );
196  }
197  }
198  else if(KDE_ISUNLIKELY( success==RECOVERED_PARSE_ERROR ))
199  {
200  kDebug() << "Recovered parse error in entry: " << counter;
201  recoveredError=true;
202  errorIndex.append(counter);
203 
204  CatalogItem tempCatItem;
205  tempCatItem.setPlural(_gettextPluralForm);
206  tempCatItem.setMsgid( _msgid );
207  tempCatItem.setMsgstr( _msgstr );
208  if (_msgctxtPresent) tempCatItem.setMsgctxt( _msgctxt );
209  tempCatItem.setComment( _comment );
210 
211 
212  // add new entry to the list of entries
213  appendCatalogItem(tempCatItem);
214  }
215  else if (success == PARSE_ERROR)
216  {
217  kDebug() << "Parse error in entry: " << counter;
218  return PARSE_ERROR;
219  }
220  else
221  {
222  kDebug() << "Unknown success status, assumig parse error " << success;
223  return PARSE_ERROR;
224  }
225  counter++;
226 
227  }
228 
229  // TODO: can we check that there is no useful entry?
230  if (KDE_ISUNLIKELY( !counter && !recoveredErrorInHeader ))
231  {
232  // Empty file? (Otherwise, there would be a try of getting an entry and the count would be 1 !)
233  kDebug() << " Empty file?";
234  return PARSE_ERROR;
235  }
236 
237  kDebug() << " ready";
238 
239  // We have successfully loaded the file (perhaps with recovered errors)
240 
241 // qWarning() << " done in " << aaa.elapsed() <<_extraDataSaver->extraData.size() << endl;
242 
243  setGeneratedFromDocbook(docbookContent || docbookFile);
244  setHeader(tempHeader);
245  setCatalogExtraData(_extraDataSaver.extraData);
246  setErrorIndex(errorIndex);
247  setCodec(codec);
248  //setMimeTypes( "text/x-gettext-translation" );
249 #if 0
250  if (KDE_ISUNLIKELY( recoveredErrorInHeader ))
251  {
252  kDebug() << " Returning: header error";
253  return RECOVERED_HEADER_ERROR;
254  }
255  else if (KDE_ISUNLIKELY( recoveredError ))
256  {
257  kDebug() << " Returning: recovered parse error";
258  return RECOVERED_PARSE_ERROR;
259  }
260  else
261 #endif
262  {
263  kDebug() << " Returning: OK! :-)";
264  return OK;
265  }
266 }
267 
268 QTextCodec* GettextImportPlugin::codecForDevice(QIODevice* device/*, bool* hadCodec*/)
269 {
270  QTextStream stream( device );
271  stream.seek(0);
272  _errorLine=0;
273  stream.setCodec( "UTF-8" );
274  stream.setAutoDetectUnicode(true); //this way we can
275  QTextCodec* codec=stream.codec(); //detect UTF-16
276 
277  ConversionStatus status = readEntry(stream);
278  if (KDE_ISUNLIKELY( status!=OK && status != RECOVERED_PARSE_ERROR ))
279  {
280  kDebug() << "wasn't able to read header";
281  return codec;
282  }
283 
284  QRegExp regexp("Content-Type:\\s*\\w+/[-\\w]+;?\\s*charset\\s*=\\s*(\\S+)\\s*\\\\n");
285  if ( regexp.indexIn( _msgstr.first() ) == -1 )
286  {
287  kDebug() << "no charset entry found";
288  return codec;
289  }
290 
291  const QString charset = regexp.cap(1);
292  kDebug() << "charset: " << charset;
293 
294  if (charset.isEmpty())
295  {
296  kWarning() << "No charset defined! Assuming UTF-8!";
297  return codec;
298  }
299 
300  // "CHARSET" is the default charset entry in a template (pot).
301  // characters in a template should be either pure ascii or
302  // at least utf8, so utf8-codec can be used for both.
303  if ( charset.contains("CHARSET"))
304  {
305  kDebug() << QString("file seems to be a template: using utf-8 encoding.");
306  return QTextCodec::codecForName("utf8");;
307  }
308 
309  QTextCodec* t=0;
310  t = QTextCodec::codecForName(charset.toLatin1());
311 
312  if (t)
313  return t;
314  else
315  kWarning() << "charset found, but no codec available, using UTF-8 instead";
316 
317  return codec;//UTF-8
318 }
319 
320 ConversionStatus GettextImportPlugin::readEntry(QTextStream& stream)
321 {
322  ConversionStatus result=readEntryRaw(stream);
323  _msgstr.replaceInStrings("\\\"","\"");
324  _msgid.replaceInStrings("\\\"","\"");
325  _msgctxt.replace("\\\"","\"");
326  return result;
327 }
328 
329 ConversionStatus GettextImportPlugin::readEntryRaw(QTextStream& stream)
330 {
331  //kDebug() << " START";
332  enum {Begin,Comment,Msgctxt,Msgid,Msgstr} part=Begin;
333 
334  _trailingNewLines=0;
335  bool error=false;
336  bool recoverableError=false;
337  bool seenMsgctxt=false;
338  _msgstr.clear();
339  _msgstr.append(QString());
340  _msgid.clear();
341  _msgid.append(QString());
342  _msgctxt.clear();
343  _msgctxtPresent=false;
344  _comment.clear();
345  _gettextPluralForm=false;
346  _obsolete=false;
347 
348  QStringList::Iterator msgstrIt=_msgstr.begin();
349  QString line;
350 
351  while( !stream.atEnd() )
352  {
353  _errorLine++;
354  //line=stream.readLine();
355  if (!_bufferedLine.isEmpty())
356  {
357  line=_bufferedLine;
358  _bufferedLine.clear();
359  }
360  else
361  line=stream.readLine();
362 
363  kDebug() << "Parsing line: " << line;
364 
365  static const QString lesslessless="<<<<<<<";
366  static const QString isisis="=======";
367  static const QString moremoremore=">>>>>>>";
368  if (KDE_ISUNLIKELY( line.startsWith( lesslessless ) || line.startsWith( isisis ) || line.startsWith( moremoremore ) ))
369  {
370  // We have found a CVS/SVN conflict marker. Abort.
371  // (It cannot be any useful data of the PO file, as otherwise the line would start with at least a quote)
372  kError() << "CVS/SVN conflict marker found! Aborting!" << endl << line << endl;
373  return PARSE_ERROR;
374  }
375 
376  // remove whitespaces from beginning and end of line
377  line = line.trimmed();
378 
379  // remember wrapping state to save file nicely
380  int len=line.length();
381  if (len)
382  {
383  _trailingNewLines=0;
384  if (_maxLineLength<len && line.at(0)!='#')
385  _maxLineLength=len;
386  }
387  else
388  ++_trailingNewLines;
389 
390 
391  if(part==Begin)
392  {
393  // ignore trailing newlines
394  if(!len)
395  continue;
396 
397  if(line.startsWith(_obsoleteStart))
398  {
399  _obsolete=true;
400  part=Comment;
401  _comment=line;
402  }
403  else if(line.startsWith('#'))
404  {
405  part=Comment;
406  _comment=line;
407  }
408  else if( line.startsWith(_msgctxtStart) && line.contains( _rxMsgCtxt ) )
409  {
410  part=Msgctxt;
411 
412  // remove quotes at beginning and the end of the lines
413  line.remove(QRegExp("^msgctxt\\s*\""));
414  line.remove(_rxMsgLineRemEndQuote);
415  _msgctxt=line;
416  _msgctxtPresent=true;
417  seenMsgctxt=true;
418  }
419  else if( line.contains( _rxMsgId ) )
420  {
421  part=Msgid;
422 
423  // remove quotes at beginning and the end of the lines
424  line.remove(_rxMsgIdRemQuotes);
425  line.remove(_rxMsgLineRemEndQuote);
426 
427  _msgidMultiline=line.isEmpty();
428  (*(_msgid).begin())=line;
429 
430  }
431  // one of the quotation marks is missing
432  else if(KDE_ISUNLIKELY( /*_testBorked&&*/ line.contains( _rxMsgIdBorked ) ))
433  {
434  part=Msgid;
435 
436  // remove quotes at beginning and the end of the lines
437  line.remove(QRegExp("^msgid\\s*\"?"));
438  line.remove(_rxMsgLineRemEndQuote);
439 
440  _msgidMultiline=line.isEmpty();
441  (*(_msgid).begin())=line;
442 
443  if(!line.isEmpty())
444  recoverableError=true;
445  }
446  else
447  {
448  kDebug() << "no comment, msgctxt or msgid found after a comment: " << line;
449  error=true;
450  break;
451  }
452  }
453  else if(part==Comment)
454  {
455  if(!len && _obsolete ) return OK;
456  if(!len) continue;
457  else if(line.startsWith(_obsoleteStart))
458  {
459  _comment+=('\n'+line);
460  _obsolete=true;
461  }
462  else if(line.startsWith('#'))
463  {
464  _comment+=('\n'+line);
465  }
466  else if( line.startsWith(_msgctxtStart) &&line.contains( _rxMsgCtxt ) )
467  {
468  part=Msgctxt;
469 
470  // remove quotes at beginning and the end of the lines
471  line.remove(QRegExp("^msgctxt\\s*\""));
472  line.remove(_rxMsgLineRemEndQuote);
473  _msgctxt=line;
474  _msgctxtPresent=true;
475  seenMsgctxt=true;
476  }
477  else if( line.contains( _rxMsgId ) )
478  {
479  part=Msgid;
480 
481  // remove quotes at beginning and the end of the lines
482  line.remove(_rxMsgIdRemQuotes);
483  line.remove(_rxMsgLineRemEndQuote);
484 
485  _msgidMultiline=line.isEmpty();
486  (*(_msgid).begin())=line;
487  }
488  // one of the quotation marks is missing
489  else if(KDE_ISUNLIKELY( /*_testBorked&&*/line.contains( _rxMsgIdBorked ) ))
490  {
491  part=Msgid;
492 
493  // remove quotes at beginning and the end of the lines
494  line.remove(QRegExp("^msgid\\s*\"?"));
495  line.remove(_rxMsgLineRemEndQuote);
496 
497  _msgidMultiline=line.isEmpty();
498  (*(_msgid).begin())=line;
499 
500  if(!line.isEmpty())
501  recoverableError=true;
502  }
503  else
504  {
505  kDebug() << "no comment or msgid found after a comment while parsing: " << _comment;
506  error=true;
507  break;
508  }
509  }
510  else if(part==Msgctxt)
511  {
512  if(!len)
513  continue;
514  else if( line.contains( _rxMsgLine ) )
515  {
516  // remove quotes at beginning and the end of the lines
517  line.remove(_rxMsgLineRemStartQuote);
518  line.remove(_rxMsgLineRemEndQuote);
519 
520  // add Msgctxt line to item
521  if(_msgctxt.isEmpty())
522  _msgctxt=line;
523  else
524  _msgctxt+=('\n'+line);
525  _msgctxtPresent=true;
526  }
527  else if( line.contains( _rxMsgId ) )
528  {
529  part=Msgid;
530 
531  // remove quotes at beginning and the end of the lines
532  line.remove(_rxMsgIdRemQuotes);
533  line.remove(_rxMsgLineRemEndQuote);
534 
535  _msgidMultiline=line.isEmpty();
536  (*(_msgid).begin())=line;
537  }
538  // one of the quotation marks is missing
539  else if(KDE_ISUNLIKELY(/*_testBorked&&*/ line.contains ( _rxMsgIdBorked ) ))
540  {
541  part=Msgid;
542 
543  // remove quotes at beginning and the end of the lines
544  line.remove(QRegExp("^msgid\\s*\"?"));
545  line.remove(_rxMsgLineRemEndQuote);
546 
547  _msgidMultiline=line.isEmpty();
548  (*(_msgid).begin())=line;
549 
550  if(!line.isEmpty())
551  recoverableError=true;
552  }
553  else
554  {
555  kDebug() << "no msgid found after a msgctxt while parsing: " << _msgctxt;
556  error=true;
557  break;
558  }
559  }
560  else if(part==Msgid)
561  {
562  if(!len)
563  continue;
564  else if( line.contains( _rxMsgLine ) )
565  {
566  // remove quotes at beginning and the end of the lines
567  line.remove(_rxMsgLineRemStartQuote);
568  line.remove(_rxMsgLineRemEndQuote);
569 
570  QStringList::Iterator it;
571  if(_gettextPluralForm)
572  {
573  it=_msgid.end();
574  --it;
575  }
576  else
577  it = _msgid.begin();
578 
579  // add Msgid line to item
580  if(it->isEmpty())
581  (*it)=line;
582  else
583  (*it)+=('\n'+line);
584  }
585  else if( line.contains( _rxMsgIdPlural) )
586  {
587  part=Msgid;
588  _gettextPluralForm = true;
589 
590  // remove quotes at beginning and the end of the lines
591  line.remove(QRegExp("^msgid_plural\\s*\""));
592  line.remove(_rxMsgLineRemEndQuote);
593 
594  _msgid.append(line);
595  }
596  // one of the quotation marks is missing
597  else if(KDE_ISUNLIKELY(/*_testBorked&&*/ line.contains( _rxMsgIdPluralBorked ) ))
598  {
599  part=Msgid;
600  _gettextPluralForm = true;
601 
602  // remove quotes at beginning and the end of the lines
603  line.remove(QRegExp("^msgid_plural\\s*\"?"));
604  line.remove(_rxMsgLineRemEndQuote);
605 
606  _msgid.append(line);
607 
608  if(!line.isEmpty())
609  recoverableError=true;
610  }
611  else if( !_gettextPluralForm && ( line.contains( _rxMsgStr ) ) )
612  {
613  part=Msgstr;
614 
615  // remove quotes at beginning and the end of the lines
616  line.remove(_rxMsgStrRemQuotes);
617  line.remove(_rxMsgLineRemEndQuote);
618 
619  _msgstrMultiline=line.isEmpty();
620  (*msgstrIt)=line;
621  }
622  else if( !_gettextPluralForm && ( line.contains( _rxMsgStrOther )) )
623  {
624  part=Msgstr;
625 
626  // remove quotes at beginning and the end of the lines
627  line.remove(_rxMsgStrRemQuotes);
628  line.remove(_rxMsgLineRemEndQuote);
629 
630  _msgstrMultiline=line.isEmpty();
631  (*msgstrIt)=line;
632 
633  if(!line.isEmpty())
634  recoverableError=true;
635  }
636  else if( _gettextPluralForm && ( line.contains( _rxMsgStrPluralStart ) ) )
637  {
638  part=Msgstr;
639 
640  // remove quotes at beginning and the end of the lines
641  line.remove(QRegExp("^msgstr\\[0\\]\\s*\"?"));
642  line.remove(_rxMsgLineRemEndQuote);
643 
644  _msgstrMultiline=line.isEmpty();
645  (*msgstrIt)=line;
646  }
647  else if(KDE_ISUNLIKELY( /*_testBorked&&*/ _gettextPluralForm && line.contains( _rxMsgStrPluralStartBorked ) ))
648  {
649  part=Msgstr;
650 
651  // remove quotes at beginning and the end of the lines
652  line.remove(QRegExp("^msgstr\\[0\\]\\s*\"?"));
653  line.remove(_rxMsgLineRemEndQuote);
654 
655  _msgstrMultiline=line.isEmpty();
656  (*msgstrIt)=line;
657 
658  if(!line.isEmpty())
659  recoverableError=true;
660  }
661  else if ( line.startsWith( '#' ) )
662  {
663  // ### TODO: could this be considered recoverable?
664  kDebug() << "comment found after a msgid while parsing: " << _msgid.first();
665  error=true;
666  break;
667  }
668  else if ( line.startsWith( "msgid" ) )
669  {
670  kDebug() << "Another msgid found after a msgid while parsing: " << _msgid.first();
671  error=true;
672  break;
673  }
674  // a line of the msgid with a missing quotation mark
675  else if(KDE_ISUNLIKELY( /*_testBorked&&*/line.contains( _rxMsgLineBorked ) ))
676  {
677  recoverableError=true;
678 
679  // remove quotes at beginning and the end of the lines
680  line.remove(_rxMsgLineRemStartQuote);
681  line.remove(_rxMsgLineRemEndQuote);
682 
683  QStringList::Iterator it;
684  if( _gettextPluralForm )
685  {
686  it=_msgid.end();
687  --it;
688  }
689  else
690  it = _msgid.begin();
691 
692  // add Msgid line to item
693  if(it->isEmpty())
694  (*it)=line;
695  else
696  (*it)+=('\n'+line);
697  }
698  else
699  {
700  kDebug() << "no msgstr found after a msgid while parsing: " << _msgid.first();
701  error=true;
702  break;
703  }
704  }
705  else if(part==Msgstr)
706  {
707  if(!len)
708  break;
709  // another line of the msgstr
710  else if( line.contains( _rxMsgLine ) )
711  {
712  // remove quotes at beginning and the end of the lines
713  line.remove(_rxMsgLineRemStartQuote);
714  line.remove(_rxMsgLineRemEndQuote);
715 
716  if(!(*msgstrIt).isEmpty())
717  (*msgstrIt)+='\n';
718  (*msgstrIt)+=line;
719  }
720  else if( _gettextPluralForm && ( line.contains( _rxMsgStrPlural ) ) )
721  {
722  // remove quotes at beginning and the end of the lines
723  line.remove(QRegExp("^msgstr\\[[0-9]+\\]\\s*\"?"));
724  line.remove(_rxMsgLineRemEndQuote);
725 
726  _msgstr.append(line);
727  msgstrIt=_msgstr.end();
728  --msgstrIt;
729  }
730  else if ( line.startsWith( '#' ) || line.startsWith( "msgid" ) )
731  {
732  _errorLine--;
733  _bufferedLine=line;
734  break;
735  }
736  else if(KDE_ISUNLIKELY(/*_testBorked&&*/ _gettextPluralForm && ( line.contains( _rxMsgStrPluralBorked ) ) ))
737  {
738  // remove quotes at beginning and the end of the lines
739  line.remove(QRegExp("^msgstr\\[[0-9]\\]\\s*\"?"));
740  line.remove(_rxMsgLineRemEndQuote);
741 
742  _msgstr.append(line);
743  msgstrIt=_msgstr.end();
744  --msgstrIt;
745 
746  if(!line.isEmpty())
747  recoverableError=true;
748  }
749  else if(line.startsWith("msgstr"))
750  {
751  kDebug() << "Another msgstr found after a msgstr while parsing: " << line << _msgstr.last();
752  error=true;
753  break;
754  }
755  // another line of the msgstr with a missing quotation mark
756  else if(KDE_ISUNLIKELY( /*_testBorked&&*/line.contains( _rxMsgLineBorked ) ))
757  {
758  recoverableError=true;
759 
760  // remove quotes at beginning and the end of the lines
761  line.remove(_rxMsgLineRemStartQuote);
762  line.remove(_rxMsgLineRemEndQuote);
763 
764  if(!(*msgstrIt).isEmpty())
765  (*msgstrIt)+='\n';
766  (*msgstrIt)+=line;
767  }
768  else
769  {
770  kDebug() << "no msgid or comment found after a msgstr while parsing: " << _msgstr.last();
771  error=true;
772  break;
773  }
774  }
775  }
776 
777 /*
778  if(_gettextPluralForm)
779  {
780  kDebug() << "gettext plural form:\n"
781  << "msgid:\n" << _msgid.first() << "\n"
782  << "msgid_plural:\n" << _msgid.last() << "\n" << endl;
783  int counter=0;
784  for(QStringList::Iterator it = _msgstr.begin(); it != _msgstr.end(); ++it)
785  {
786  kDebug() << "msgstr[" << counter << "]:\n"
787  << (*it) << endl;
788  counter++;
789  }
790  }
791  */
792 
793  //kDebug() << " NEAR RETURN";
794  if(KDE_ISUNLIKELY(error))
795  return PARSE_ERROR;
796  else if(KDE_ISUNLIKELY(recoverableError))
797  return RECOVERED_PARSE_ERROR;
798  else
799  return OK;
800 }
801 
802 // kate: space-indent on; indent-width 4; replace-tabs on;
QIODevice
QTextStream::setCodec
void setCodec(QTextCodec *codec)
QList::clear
void clear()
GettextCatalog::CatalogImportPlugin::setCatalogExtraData
void setCatalogExtraData(const QStringList &data)
set extra data for the catalog, which can't be stored in CatalogItem.
Definition: importplugin.cpp:72
GettextCatalog::ExtraDataSaver::extraData
QStringList extraData
Definition: gettextimport.h:54
GettextCatalog::CatalogItem::setMsgid
void setMsgid(const QString &msg, const int form=0)
Definition: catalogitem.cpp:134
QTextStream::readLine
QString readLine(qint64 maxlen)
GettextCatalog::CatalogItem
This class represents an entry in a catalog.
Definition: catalogitem.h:55
catalogitem.h
GettextCatalog::PARSE_ERROR
Definition: catalogfileplugin.h:58
QString::remove
QString & remove(int position, int n)
QTime
GettextCatalog::GettextImportPlugin::GettextImportPlugin
GettextImportPlugin()
Definition: gettextimport.cpp:63
QTextStream
GettextCatalog::RECOVERED_PARSE_ERROR
Definition: catalogfileplugin.h:59
QString::clear
void clear()
QRegExp
GettextCatalog::CatalogItem::setPlural
void setPlural(bool plural=true)
Definition: catalogitem.cpp:197
QList::append
void append(const T &value)
QTextStream::atEnd
bool atEnd() const
GettextCatalog::CatalogItem::setMsgctxt
void setMsgctxt(const QString &msg)
Definition: catalogitem.cpp:122
GettextCatalog::RECOVERED_HEADER_ERROR
Header error that could be recovered.
Definition: catalogfileplugin.h:63
QList::isEmpty
bool isEmpty() const
QString::isEmpty
bool isEmpty() const
GettextCatalog::CatalogImportPlugin::setErrorIndex
void setErrorIndex(const QList< int > &errors)
set the list of parse error indexes
Definition: importplugin.cpp:84
QString::trimmed
QString trimmed() const
QString::startsWith
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const
GettextCatalog::CatalogImportPlugin::appendCatalogItem
void appendCatalogItem(const CatalogItem &item, const bool obsolete=false)
Append a new catalog item, either as normal or as an obsolete one.
Definition: importplugin.cpp:62
QList::Iterator
typedef Iterator
GettextCatalog::ConversionStatus
ConversionStatus
Result of the conversion.
Definition: catalogfileplugin.h:53
QStringList::replaceInStrings
QStringList & replaceInStrings(const QString &before, const QString &after, Qt::CaseSensitivity cs)
QList::first
T & first()
QString
QList< int >
QTextCodec
GettextCatalog::CatalogImportPlugin::setCodec
void setCodec(QTextCodec *codec)
Set the character encoding used in the catalog file.
Definition: importplugin.cpp:96
QList::end
iterator end()
GettextCatalog::CatalogImportPlugin
HISTORY: this was a base class for Catalog import plugins in KBabel, but this architecture isn't not ...
Definition: catalogfileplugin.h:85
QString::contains
bool contains(QChar ch, Qt::CaseSensitivity cs) const
GettextCatalog::GettextImportPlugin::load
ConversionStatus load(QIODevice *)
Reimplement this method to load the local file passed as an argument.
Definition: gettextimport.cpp:89
GettextCatalog::CatalogItem::comment
QString comment() const
Definition: catalogitem.cpp:62
GettextCatalog::CatalogImportPlugin::_errorLine
int _errorLine
Definition: catalogfileplugin.h:142
GettextCatalog::CatalogImportPlugin::_maxLineLength
short _maxLineLength
Definition: catalogfileplugin.h:140
QString::replace
QString & replace(int position, int n, QChar after)
QString::toLatin1
QByteArray toLatin1() const
GettextCatalog::CatalogImportPlugin::setGeneratedFromDocbook
void setGeneratedFromDocbook(const bool fromDocbook)
set flag that the file is generated from DocBook
Definition: importplugin.cpp:78
GettextCatalog::CatalogItem::setComment
void setComment(const QString &com)
Definition: catalogitem.cpp:187
GettextCatalog::CatalogItem::msgstr
const QString & msgstr(const int form=0) const
Definition: catalogitem.cpp:78
QString::at
const QChar at(int position) const
QTextCodec::codecForName
QTextCodec * codecForName(const QByteArray &name)
QList::last
T & last()
GettextCatalog::CatalogImportPlugin::setHeader
void setHeader(const CatalogItem &header)
set the header catalog item
Definition: importplugin.cpp:90
QString::length
int length() const
GettextCatalog::CatalogItem::setMsgstr
void setMsgstr(const QString &msg, const int form=0)
Definition: catalogitem.cpp:163
QTime::start
void start()
GettextCatalog::ExtraDataSaver
Definition: gettextimport.h:48
gettextimport.h
QList::begin
iterator begin()
GettextCatalog::CatalogImportPlugin::_trailingNewLines
short _trailingNewLines
Definition: catalogfileplugin.h:141
QTextStream::seek
bool seek(qint64 pos)
GettextCatalog::OK
Definition: catalogfileplugin.h:54
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:40:07 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

lokalize

Skip menu "lokalize"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members

kdesdk API Reference

Skip menu "kdesdk API Reference"
  • kapptemplate
  • kcachegrind
  • kompare
  • lokalize
  • umbrello
  •   umbrello

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal