From 97a96b51f1fdd0fe4356de8da38da5910e4f20a5 Mon Sep 17 00:00:00 2001 From: maxim Date: Sat, 5 Jan 2013 17:15:40 +0000 Subject: [PATCH] PoChecker: * don't skip formatting errors check even if translated string has no formatting arguments at all; * rewrite formatting arguments comparison function in order to make it more robust and detect invalid formatting arguments; * report formatting error even if arguments match, but some of them are invalid (only skip the case when original and translated strings exactly match, to not report e.g. '{%Region}' string); * regenerated translations, updated Russian translation. git-svn-id: trunk@39771 - --- .../pochecker/languages/pocheckerconsts.ar.po | 15 ++-- .../pochecker/languages/pocheckerconsts.cs.po | 4 +- .../pochecker/languages/pocheckerconsts.de.po | 2 +- .../pochecker/languages/pocheckerconsts.es.po | 10 +-- .../pochecker/languages/pocheckerconsts.lt.po | 10 +-- .../pochecker/languages/pocheckerconsts.po | 2 +- .../languages/pocheckerconsts.pt_BR.po | 10 +-- .../pochecker/languages/pocheckerconsts.ru.po | 5 +- .../pochecker/languages/pocheckerconsts.uk.po | 12 ++-- components/pochecker/pocheckerconsts.pas | 2 +- components/pochecker/pofamilies.pp | 68 +++++++++++-------- 11 files changed, 81 insertions(+), 59 deletions(-) diff --git a/components/pochecker/languages/pocheckerconsts.ar.po b/components/pochecker/languages/pocheckerconsts.ar.po index 1d4a03e1cf..2d32efd9c6 100644 --- a/components/pochecker/languages/pocheckerconsts.ar.po +++ b/components/pochecker/languages/pocheckerconsts.ar.po @@ -1,7 +1,7 @@ -# Arabic translation of Free Pascal Lazarus Project. -# Copyright (C) 2012 Lazarus Project -# This file is distributed under the same license as the Lazarus package. -# Khaled Shagrouni , 2012. + Arabic translation of Free Pascal Lazarus Project. + Copyright (C) 2012 Lazarus Project + This file is distributed under the same license as the Lazarus package. + Khaled Shagrouni , 2012. msgid "" msgstr "" "Project-Id-Version: Free Pascal Lazarus Project.\n" @@ -108,7 +108,9 @@ msgid "Identifier [%s] not found in %s" msgstr "المعرّف [%s] لم يتّم إيجاده في %s" #: pocheckerconsts.sincompatibleformatargs -msgid "[Line: %d] Incompatible format() arguments for:" +#, fuzzy +#| msgid "[Line: %d] Incompatible format() arguments for:" +msgid "[Line: %d] Incompatible and/or invalid format() arguments for:" msgstr "[السطر: %d] معطيات format() غير متوافقة ل:" #: pocheckerconsts.slineinfilename @@ -207,4 +209,5 @@ msgstr "الترجمة" #: pocheckerconsts.sunselectalltests msgid "Unselect all tests" -msgstr "إزالة اختيار كل الإختبارات" \ No newline at end of file +msgstr "إزالة اختيار كل الإختبارات" + diff --git a/components/pochecker/languages/pocheckerconsts.cs.po b/components/pochecker/languages/pocheckerconsts.cs.po index e924c42afc..b2a61df4d1 100644 --- a/components/pochecker/languages/pocheckerconsts.cs.po +++ b/components/pochecker/languages/pocheckerconsts.cs.po @@ -101,7 +101,9 @@ msgid "Identifier [%s] not found in %s" msgstr "Identifikátor [%s] nenalezen v %s" #: pocheckerconsts.sincompatibleformatargs -msgid "[Line: %d] Incompatible format() arguments for:" +#, fuzzy +#| msgid "[Line: %d] Incompatible format() arguments for:" +msgid "[Line: %d] Incompatible and/or invalid format() arguments for:" msgstr "[Řádek %d] Nekompatibilní argumenty fce format() pro:" #: pocheckerconsts.slineinfilename diff --git a/components/pochecker/languages/pocheckerconsts.de.po b/components/pochecker/languages/pocheckerconsts.de.po index fc7116058c..bdcded64d7 100644 --- a/components/pochecker/languages/pocheckerconsts.de.po +++ b/components/pochecker/languages/pocheckerconsts.de.po @@ -91,7 +91,7 @@ msgid "Identifier [%s] not found in %s" msgstr "Bezeichner [%s] nicht gefunden in %s" #: pocheckerconsts.sincompatibleformatargs -msgid "[Line: %d] Incompatible format() arguments for:" +msgid "[Line: %d] Incompatible and/or invalid format() arguments for:" msgstr "" #: pocheckerconsts.slineinfilename diff --git a/components/pochecker/languages/pocheckerconsts.es.po b/components/pochecker/languages/pocheckerconsts.es.po index 00a0ff4609..d1f94414b6 100644 --- a/components/pochecker/languages/pocheckerconsts.es.po +++ b/components/pochecker/languages/pocheckerconsts.es.po @@ -63,7 +63,7 @@ msgstr "[Línea %d] %s" #: pocheckerconsts.sduplicateoriginals msgid "The (untranslated) value \"%s\" is used for more than 1 entry:" -msgstr "El valor (sin traducir) \"%s\ " se utiliza para más de 1 entrada:" +msgstr "El valor (sin traducir) \"%s \" se utiliza para más de 1 entrada:" #: pocheckerconsts.serroroncleanup msgid "" @@ -71,8 +71,8 @@ msgid "" "%s\n" "Please close the program\n" msgstr "" -"A ocurrido\n un error irrecuperable" -"%s\n" +"A ocurrido\n" +" un error irrecuperable%s\n" "Por favor, cierre la program\n" #: pocheckerconsts.serroroncreate @@ -100,7 +100,9 @@ msgid "Identifier [%s] not found in %s" msgstr "Identificador [%s] no se encuentra en %s" #: pocheckerconsts.sincompatibleformatargs -msgid "[Line: %d] Incompatible format() arguments for:" +#, fuzzy +#| msgid "[Line: %d] Incompatible format() arguments for:" +msgid "[Line: %d] Incompatible and/or invalid format() arguments for:" msgstr "[Línea: %d] format() argumentos incompatibles para:" #: pocheckerconsts.slineinfilename diff --git a/components/pochecker/languages/pocheckerconsts.lt.po b/components/pochecker/languages/pocheckerconsts.lt.po index aab1794fae..76c9ae1360 100644 --- a/components/pochecker/languages/pocheckerconsts.lt.po +++ b/components/pochecker/languages/pocheckerconsts.lt.po @@ -1,4 +1,4 @@ -# Valdas Jankunas , 2012. + Valdas Jankunas , 2012. msgid "" msgstr "" "Content-Type: text/plain; charset=UTF-8\n" @@ -9,8 +9,7 @@ msgstr "" "Language: lt\n" "Content-Transfer-Encoding: 8bit\n" "MIME-Version: 1.0\n" -"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%" -"100<10 || n%100>=20) ? 1 : 2);\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2);\n" "X-Generator: Lokalize 1.5\n" #: pocheckerconsts.rspochecker @@ -104,7 +103,9 @@ msgid "Identifier [%s] not found in %s" msgstr "Ieškota identifikatoriaus [%s], tačiau %s jo neturi" #: pocheckerconsts.sincompatibleformatargs -msgid "[Line: %d] Incompatible format() arguments for:" +#, fuzzy +#| msgid "[Line: %d] Incompatible format() arguments for:" +msgid "[Line: %d] Incompatible and/or invalid format() arguments for:" msgstr "[Eilutė: %d] Nesuderinamų „format()“ argumentų turi:" #: pocheckerconsts.slineinfilename @@ -205,4 +206,3 @@ msgstr "Vertimas" msgid "Unselect all tests" msgstr "Naikinti testavimų žymėjimą" - diff --git a/components/pochecker/languages/pocheckerconsts.po b/components/pochecker/languages/pocheckerconsts.po index 636036763d..a98999923f 100644 --- a/components/pochecker/languages/pocheckerconsts.po +++ b/components/pochecker/languages/pocheckerconsts.po @@ -83,7 +83,7 @@ msgid "Identifier [%s] not found in %s" msgstr "" #: pocheckerconsts.sincompatibleformatargs -msgid "[Line: %d] Incompatible format() arguments for:" +msgid "[Line: %d] Incompatible and/or invalid format() arguments for:" msgstr "" #: pocheckerconsts.slineinfilename diff --git a/components/pochecker/languages/pocheckerconsts.pt_BR.po b/components/pochecker/languages/pocheckerconsts.pt_BR.po index 042ea4b65d..319d9f429e 100644 --- a/components/pochecker/languages/pocheckerconsts.pt_BR.po +++ b/components/pochecker/languages/pocheckerconsts.pt_BR.po @@ -19,7 +19,7 @@ msgid "" "%s\n" "for selected file\n" "%s\n" -msgstr "Impossível localizar o arquivo po mestre:\n" +msgstr "Impossível localizar o arquivo po mestre:" #: pocheckerconsts.scheckforduplicateuntranslatedvalues msgid "Check for duplicate untranslated values" @@ -66,13 +66,13 @@ msgid "" "An unrecoverable error occurred\n" "%s\n" "Please close the program\n" -msgstr "Ocorreu um erro irrecuperável\n" +msgstr "Ocorreu um erro irrecuperável" #: pocheckerconsts.serroroncreate msgid "" "Error creating an instance of TPoFamily:\n" "%s\n" -msgstr "Erro ao criar uma instância de TPoFamily:\n" +msgstr "Erro ao criar uma instância de TPoFamily:" #: pocheckerconsts.serrorsbytest msgid "Errors / warnings reported by %s for:" @@ -91,7 +91,9 @@ msgid "Identifier [%s] not found in %s" msgstr "Identificador [%s] não encontrado em %s" #: pocheckerconsts.sincompatibleformatargs -msgid "[Line: %d] Incompatible format() arguments for:" +#, fuzzy +#| msgid "[Line: %d] Incompatible format() arguments for:" +msgid "[Line: %d] Incompatible and/or invalid format() arguments for:" msgstr "[Linha: %d] formato() incompatível de argumentos para:" #: pocheckerconsts.slineinfilename diff --git a/components/pochecker/languages/pocheckerconsts.ru.po b/components/pochecker/languages/pocheckerconsts.ru.po index be173202b5..c3015bdcbf 100644 --- a/components/pochecker/languages/pocheckerconsts.ru.po +++ b/components/pochecker/languages/pocheckerconsts.ru.po @@ -100,8 +100,9 @@ msgid "Identifier [%s] not found in %s" msgstr "Идентификатор [%s] не найден в %s" #: pocheckerconsts.sincompatibleformatargs -msgid "[Line: %d] Incompatible format() arguments for:" -msgstr "[Строка: %d] Несовместимые аргументы для Format() в:" +#| msgid "[Line: %d] Incompatible format() arguments for:" +msgid "[Line: %d] Incompatible and/or invalid format() arguments for:" +msgstr "[Строка: %d] Несовместимые и/или неверные аргументы для Format() в:" #: pocheckerconsts.slineinfilename msgid "[Line %d] in %s:" diff --git a/components/pochecker/languages/pocheckerconsts.uk.po b/components/pochecker/languages/pocheckerconsts.uk.po index 29a2343600..fbf570a301 100644 --- a/components/pochecker/languages/pocheckerconsts.uk.po +++ b/components/pochecker/languages/pocheckerconsts.uk.po @@ -1,4 +1,4 @@ -# Igor Paliychuk , 2012. + Igor Paliychuk , 2012. msgid "" msgstr "" "PO-Revision-Date: 2012-04-23 11:40+0300\n" @@ -6,8 +6,7 @@ msgstr "" "Language: uk\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%" -"10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" "X-Generator: Virtaal 0.7.1\n" #: pocheckerconsts.rspochecker @@ -24,7 +23,7 @@ msgstr "" "Не можу знайти основний po файл:\n" "%s\n" "для вибраного файлу\n" -"%s" +"%s\n" #: pocheckerconsts.scheckforduplicateuntranslatedvalues msgid "Check for duplicate untranslated values" @@ -101,7 +100,9 @@ msgid "Identifier [%s] not found in %s" msgstr "Ідентифікатор [%s] не знайдений в %s" #: pocheckerconsts.sincompatibleformatargs -msgid "[Line: %d] Incompatible format() arguments for:" +#, fuzzy +#| msgid "[Line: %d] Incompatible format() arguments for:" +msgid "[Line: %d] Incompatible and/or invalid format() arguments for:" msgstr "[Рядок: %d] Несумісні аргументи format() для:" #: pocheckerconsts.slineinfilename @@ -201,3 +202,4 @@ msgstr "Переклад" #: pocheckerconsts.sunselectalltests msgid "Unselect all tests" msgstr "Зняти вибір з всіх тестів" + diff --git a/components/pochecker/pocheckerconsts.pas b/components/pochecker/pocheckerconsts.pas index 3aaf3e0ab5..a74a945f16 100644 --- a/components/pochecker/pocheckerconsts.pas +++ b/components/pochecker/pocheckerconsts.pas @@ -44,7 +44,7 @@ resourcestring sCheckForDuplicateUntranslatedValues = 'Check for duplicate untranslated ' +'values'; sFindAllTranslatedPoFiles = 'Find all translated po-files'; - sIncompatibleFormatArgs = '[Line: %d] Incompatible format() arguments for:' ; + sIncompatibleFormatArgs = '[Line: %d] Incompatible and/or invalid format() arguments for:' ; sNrErrorsFound = 'Found %d errors.'; sNrWarningsFound = 'Found %d warnings.'; diff --git a/components/pochecker/pofamilies.pp b/components/pochecker/pofamilies.pp index 17e74d63c1..460cf11d28 100644 --- a/components/pochecker/pofamilies.pp +++ b/components/pochecker/pofamilies.pp @@ -78,7 +78,7 @@ Type property OnTestEnd: TTestEndEvent read FOnTestEnd write FOnTestEnd; end; -function ExtractFormatArgs(S: String): String; +function ExtractFormatArgs(S: String; out ArgumentError: boolean): String; function IsMasterPoName(const Fn: String): Boolean; function ExtractMasterNameFromChildName(const AChildName: String): String; function FindAllTranslatedPoFiles(const Filename: string): TStringList; @@ -114,42 +114,42 @@ const //Helper functions -function ExtractFormatArgs(S: String): String; +function ExtractFormatArgs(S: String; out ArgumentError: boolean): String; const - FormatSpecs = ['D','E','F','G','M','N','P','S','U','X']; + FormatArgs = 'DEFGMNPSUX'; + FormatChar = '%'; + FormatSpecs = ':-.0123456789'; var - i,p: Integer; - InFormat: Boolean; - NewStr: String; - c: Char; + p: PtrInt; + NewStr, Symb: String; begin - SetLength(NewStr, Length(S)); - InFormat := False; - p := 0; - for i := 1 to length(S) do + NewStr := ''; + ArgumentError := false; + p := UTF8Pos(FormatChar, S); + while (Length(S)>0) and (p>0) do begin - c := S[i]; - if (c = '%') then InFormat := not InFormat; - //debugln('i = ',dbgs(i),' c = ',c,' InFormat = ',dbgs(informat)); - if InFormat and (UpCase(c) in (FormatSpecs+['%'])) then + UTF8Delete(S, 1, p); + if Length(S)>0 then begin + Symb := UTF8UpperCase(UTF8Copy(S, 1, 1)); + while (Length(S)>1) and (UTF8Pos(Symb, FormatSpecs)>0) do begin - Inc(p); - NewStr[p] := c; + //weak syntax check for formatting options, skip them if found + UTF8Delete(S, 1, 1); + Symb := UTF8UpperCase(UTF8Copy(S, 1, 1)); end; - end - else - begin - if (c = '%') and (i > 1) and (S[i-1] = '%') and (p > 0) and (NewStr[p] = '%') then - begin//2 consecutive % means a literal % and is not a format specifier - //debugln('p = ',dbgs(p), 'i = ',dbgs(i)); - NewStr[p] := '#'; - Dec(p); + if Symb <> FormatChar then + begin + NewStr := NewStr+Symb; + if UTF8Pos(Symb, FormatArgs)=0 then + ArgumentError := true; end; end; - if InFormat and (Upcase(c) in FormatSpecs) then InFormat := False; + //removing processed symbol + UTF8Delete(S, 1, 1); + //searching for next argument + p := UTF8Pos(FormatChar, S); end; - SetLength(NewStr, p); Result := NewStr; end; @@ -226,8 +226,18 @@ end; function CompareFormatArgs(S1, S2: String): Boolean; +var + ArgErr1, ArgErr2: boolean; begin - Result := CompareText(ExtractFormatArgs(S1), ExtractFormatArgs(S2)) = 0; + Result := true; + //do not check arguments if strings are equal to save time and avoid some + //false positives, e.g. for '{%Region}' string in lazarusidestrconsts + if S1 <> S2 then + begin + Result := CompareText(ExtractFormatArgs(S1, ArgErr1), ExtractFormatArgs(S2, ArgErr2)) = 0; + //setting result to false if invalid arguments were found even if the match + Result := Result and not ArgErr1 and not ArgErr2; + end; end; { TPoFamily } @@ -347,7 +357,7 @@ begin //CPoItem := FChild.FindPoItem(MPoItem.Identifier); if Assigned(CPoItem) then begin - if (Pos('%', CPoItem.Translation) > 0) and not CompareFormatArgs(CPoItem.Original, CPoItem.Translation) then + if CompareFormatArgs(CPoItem.Original, CPoItem.Translation) = false then begin if (ErrorCount = 0) then begin