lazarus/components/pochecker/pofamilies.pp

810 lines
24 KiB
ObjectPascal

unit PoFamilies;
{ $define DebugSimplePoFiles}
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, ContNrs, Math,
// LCL
LCLProc,
// LazUtils
FileUtil, LazFileUtils, Translations, StringHashList,
// PoChecker
PoCheckerConsts;
Type
TPoTestType = (pttCheckNrOfItems, pttCheckFormatArgs, pttCheckMissingIdentifiers,
pttCheckMismatchedOriginals);
TPoTestTypes = Set of TPoTestType;
const
optRunAllTests: TPoTestTypes = [];
PoTestTypeNames: array[TPoTestType] of String = (
sCheckNumberOfItems,
sCheckForIncompatibleFormatArguments,
sCheckMissingIdentifiers,
sCheckForMismatchesInUntranslatedStrings
);
Type
{ TPoFamily }
TTestStartEvent = procedure(const ATestName, APoFileName: String) of object;
TTestEndEvent = procedure(const ATestName: String; const ErrorCount: Integer) of object;
TPoFamilyStats = class;
TPoFamily = class
private
FLangID: TLangID;
FMaster: TPOFile;
FChild: TPOFile;
FMasterName: String;
FChildName: String;
FOnTestStart: TTestStartEvent;
FOnTestEnd: TTestEndEvent;
FPoFamilyStats: TPoFamilyStats;
FTestTypes: TPoTestTypes;
procedure SetChildName(AValue: String);
procedure SetMasterName(AValue: String);
function GetShortMasterName: String;
function GetShortChildName: String;
protected
procedure DoTestStart(const ATestName, APoFileName: String);
procedure DoTestEnd(const ATestName: String; const ErrorCount: Integer);
public
constructor Create(const AMasterName, AChildName: String; ALangID: TLangID);
destructor Destroy; override;
protected
procedure CheckNrOfItems(out ErrorCount: Integer; ErrorLog: TStrings);
procedure CheckFormatArgs(out ErrorCount, NonFuzzyErrorCount: Integer; ErrorLog: TStrings);
procedure CheckMissingIdentifiers(out ErrorCount: Integer; ErrorLog: TStrings);
procedure CheckMismatchedOriginals(out ErrorCount: Integer; ErrorLog: TStrings);
procedure CheckDuplicateOriginals(out WarningCount: Integer; ErrorLog: TStrings);
procedure CheckStatistics(ErrorCnt: Integer);
public
procedure RunTests(out ErrorCount, NonFuzzyErrorCount, WarningCount,
TranslatedCount, UntranslatedCount, FuzzyCount: Integer; ErrorLog, StatLog, DupLog: TStringList);
property Master: TPOFile read FMaster;
property Child: TPOFile read FChild;
property MasterName: String read FMasterName write SetMasterName;
property ChildName: String read FChildName write SetChildName;
property TestTypes: TPoTestTypes read FTestTypes write FTestTypes;
property PoFamilyStats: TPoFamilyStats read FPoFamilyStats;
property ShortMasterName: String read GetShortMasterName;
property ShortChildName: String read GetShortChildName;
property OnTestStart: TTestStartEvent read FOnTestStart write FOnTestStart;
property OnTestEnd: TTestEndEvent read FOnTestEnd write FOnTestEnd;
end;
{ TPoFamilyStats }
{ TStat }
TStat = class
private
FPoName: String;
FNrTotal: Integer;
FNrTranslated: Integer;
FNrUnTranslated: Integer;
FNrFuzzy: Integer;
FNrErrors: Integer;
public
constructor Create(APoName: String; ANrTranslated, ANrUntranslated, ANrFuzzy, ANrErrors: Integer);
function ShortPoName: String;
property PoName: string read FPoName;
property NrTotal: Integer read FNrTotal;
property NrTranslated: Integer read FNrTranslated;
property NrUnTranslated: Integer read FNrUnTranslated;
property NrFuzzy: Integer read FNrFuzzy;
property NrErrors: Integer read FNrErrors;
function PercTranslated: Double; inline;
function PercUnTranslated: Double; inline;
function PercFuzzy: Double; inline;
function FracTranslated: Double;
function FracUnTranslated: Double;
function FracFuzzy: Double;
end;
TPoFamilyStats = class
private
FList: TFPObjectList;
function GetCount: Integer;
function GetItems(Index: Integer): TStat;
public
procedure Clear;
procedure Add(AName: String; ANrTranslated, ANrUnTranslated, ANrFuzzy, ANrErrors: Integer);
procedure AddItemsTo(APoFamilyStats: TPoFamilyStats);
constructor Create;
destructor Destroy; override;
procedure AddStatisticsToLog(ALog: TStrings);
property Items[Index: Integer]: TStat read GetItems;
property Count: Integer read GetCount;
end;
function ExtractMasterNameFromChildName(const AChildName: String): String;
procedure LocalizePoTestTypeNames;
const
NoError = 0;
implementation
const
sCommentIdentifier = '#: ';
sMsgID = 'msgid "';
sMsgStr = 'msgstr "';
Divider = '-------------------------------------------------------';
sFormatArgsID = '%s %s';
sFormatArgsValues = '%s%s" (= %s)';
sMismatchOriginalsID = '%s';
sMismatchOriginalsM = '%s: %s';
sMismatchOriginalsC = '%s: %s';
sShortCheckFormatArgs = 'CheckFormatArgs';
sShortCheckNrOfItems = 'CheckNrOfItems';
sShortCheckMissingIdentifiers = 'CheckMissingIdentifiers';
sShortCheckMismatchedOriginals = 'CheckMismatchedOriginals';
//Helper functions
function ExtractMasterNameFromChildName(const AChildName: String): String;
{
Input: AChildName is like: somename.some_language_specifier.po
Output: Result = somename.pot
}
var
CurUnitName: String;
CurLang: String;
begin
Result := '';
if GetPOFilenameParts(AChildName, CurUnitName, CurLang) then
Result := CurUnitName + ExtensionSeparator + 'pot';
end;
procedure LocalizePoTestTypeNames;
begin
PoTestTypeNames[pttCheckNrOfItems] := sCheckNumberOfItems;
PoTestTypeNames[pttCheckFormatArgs] := sCheckForIncompatibleFormatArguments;
PoTestTypeNames[pttCheckMissingIdentifiers] := sCheckMissingIdentifiers;
PoTestTypeNames[pttCheckMismatchedOriginals] := sCheckForMismatchesInUntranslatedStrings;
end;
{ TStat }
constructor TStat.Create(APoName: String; ANrTranslated, ANrUntranslated, ANrFuzzy, ANrErrors: Integer);
begin
FPoName := APoName;
FNrTotal := ANrTranslated + ANrUntranslated + ANrFuzzy;
FNrTranslated := ANrTranslated;
FNrUntranslated := ANrUntranslated;
FNrFuzzy := ANrFuzzy;
FNrErrors := ANrErrors;
end;
function TStat.ShortPoName: String;
begin
Result := ExtractFilename(FPoName);
end;
function TStat.PercTranslated: Double;
begin
Result := 100 * FracTranslated;
end;
function TStat.PercUnTranslated: Double;
begin
Result := 100 * FracUnTranslated;
end;
function TStat.PercFuzzy: Double;
begin
Result := 100 * FracFuzzy;
end;
function TStat.FracTranslated: Double;
begin
Result := (FNrTranslated / FNrTotal);
end;
function TStat.FracUnTranslated: Double;
begin
Result := (FNrUnTranslated / FNrTotal);
end;
function TStat.FracFuzzy: Double;
begin
Result := (FNrFuzzy / FNrTotal);
end;
{ TPoFamilyStats }
function TPoFamilyStats.GetCount: Integer;
begin
Result := FList.Count;
end;
function TPoFamilyStats.GetItems(Index: Integer): TStat;
begin
Result := TStat(FList.Items[Index]);
end;
procedure TPoFamilyStats.Clear;
begin
FList.Clear;
end;
procedure TPoFamilyStats.Add(AName: String; ANrTranslated, ANrUnTranslated, ANrFuzzy, ANrErrors: Integer);
begin
FList.Add(TStat.Create(AName, ANrTranslated, ANrUntranslated, ANrFuzzy, ANrErrors));
end;
procedure TPoFamilyStats.AddItemsTo(APoFamilyStats: TPoFamilyStats);
var
i: Integer;
AStat: TStat;
begin
for i := 0 to FList.Count - 1 do
begin
AStat := GetItems(i);
APoFamilyStats.Add(AStat.PoName, AStat.NrTranslated,
AStat.NrUntranslated, AStat.NrFuzzy, AStat.NrErrors);
end;
end;
constructor TPoFamilyStats.Create;
begin
FList := TFPObjectList.Create(True);
end;
destructor TPoFamilyStats.Destroy;
begin
FList.Free;
inherited Destroy;
end;
procedure TPoFamilyStats.AddStatisticsToLog(ALog: TStrings);
var
i: Integer;
Stat: TStat;
function Bar(Nr, Total: Integer; RoundDown: Boolean): String;
const
Max = 50;
var
Count: Integer;
begin
if RoundDown then
Count := Floor(Max * (Nr/Total))
else
Count := Ceil(Max * (Nr/Total));
Result := StringOfChar('x', Count);
Result := Result + StringOfChar(#32, Max - Count);
end;
begin
if (FList.Count = 0) then Exit;
for i := 0 to FList.Count - 1 do
begin
Stat := TStat(FList.Items[i]);
ALog.Add(Stat.PoName);
ALog.Add(Format(sPercTranslated,[Bar(Stat.NrTranslated, Stat.NrTotal, True),Stat.PercTranslated]));
ALog.Add(Format(sPercUntranslated,[Bar(Stat.NrUnTranslated, Stat.NrTotal, False), Stat.PercUnTranslated]));
ALog.Add(Format(sPercFuzzy,[Bar(Stat.NrFuzzy, Stat.NrTotal, False), Stat.PercFuzzy]));
ALog.Add('');
ALog.Add('');
end;
end;
{ TPoFamily }
procedure TPoFamily.SetMasterName(AValue: String);
begin
if FMasterName = AValue then Exit;
FMaster.Free;
FMaster := nil;
FMasterName := '';
if (AValue <> '') then FMaster := TPOFile.Create(AValue, True);
FMasterName := AValue;
end;
function TPoFamily.GetShortMasterName: String;
begin
Result := ExtractFileName(FMasterName);
end;
function TPoFamily.GetShortChildName: String;
begin
Result := ExtractFileName(FChildName);
end;
procedure TPoFamily.DoTestStart(const ATestName, APoFileName: String);
begin
if Assigned(FOnTestStart) then FOnTestStart(ATestName, APoFileName);
end;
procedure TPoFamily.DoTestEnd(const ATestName: String; const ErrorCount: Integer);
begin
if Assigned(FOnTestEnd) then FOnTestEnd(ATestName, ErrorCount);
end;
procedure TPoFamily.SetChildName(AValue: String);
begin
if FChildName = AValue then Exit;
FChild.Free;
FChild := nil;
FChildName := '';
if (AValue <> '') then FChild := TPOFile.Create(AValue, True);
FChildName := AValue;
end;
constructor TPoFamily.Create(const AMasterName, AChildName: String; ALangID: TLangID);
begin
if (AMasterName <> '') then
begin
FMaster := TPOFile.Create(AMasterName, True);
FMasterName := AMasterName;
//debugln('TPoFamily.Create: created ',FMasterName);
end;
if (AChildName <> '') then
begin
FChild := TPOFile.Create(AChildName, True);
FChildName := AChildName;
//debugln('TPoFamily.Create: created ',FChildName);
end;
FLangID := ALangID;
FPoFamilyStats := TPoFamilyStats.Create;
end;
destructor TPoFamily.Destroy;
begin
if Assigned(FMaster) then FMaster.Free;
if Assigned(FChild) then FChild.Free;
FPoFamilyStats.Free;
inherited Destroy;
end;
procedure TPoFamily.CheckNrOfItems(out ErrorCount: Integer; ErrorLog: TStrings);
begin
//debugln('TPoFamily.CheckNrOfItems');
DoTestStart(PoTestTypeNames[pttCheckNrOfItems], ShortChildName);
if (FMaster.Count <> FChild.Count) then
begin
ErrorCount := 1;
ErrorLog.Add(Divider);
ErrorLog.Add(Format(sErrorsByTest,[sShortCheckNrOfItems]));
ErrorLog.Add(ShortChildName);
ErrorLog.Add(Divider);
ErrorLog.Add('');
ErrorLog.Add(sNrOfItemsMismatch);
ErrorLog.Add(Format(sNrOfItemsMismatchD,[ShortMasterName,FMaster.Count]));
ErrorLog.Add(Format(sNrOfItemsMismatchD,[ShortChildName,FChild.Count]));
ErrorLog.Add(Divider);
ErrorLog.Add('');
ErrorLog.Add('');
end
else ErrorCount := NoError;
DoTestEnd(PoTestTypeNames[pttCheckNrOfItems], ErrorCount);
//debugln('TPoFamily.CheckNrOfItemsMismatch: ',Dbgs(ErrorCount),' Errors');
end;
procedure TPoFamily.CheckFormatArgs(out ErrorCount, NonFuzzyErrorCount: Integer
; ErrorLog: TStrings);
var
i: Integer;
CPoItem: TPOFileItem;
IsBadFormat: Boolean;
begin
//debugln('TPoFamily.CheckFormatArgs');
DoTestStart(PoTestTypeNames[pttCheckFormatArgs], ShortChildName);
ErrorCount := NoError;
NonFuzzyErrorCount := NoError;
for i := 0 to FChild.Count - 1 do
begin
CPoItem := FChild.PoItems[i];
if Assigned(CPoItem) then
begin
IsBadFormat := (Pos(sBadFormatFlag, CPoItem.Flags) > 0);
//Check only non-virtual translations.
//Virtual translations can have formatting errors if copied from an item with no-object-pascal-format flag set.
//These translations will not be used anyway (they are fuzzy) and are physically missing in translation file.
if (CPoItem.VirtualTranslation = false) and (Length(CPoItem.Translation) > 0) and IsBadFormat then
begin
if (ErrorCount = 0) then
begin
ErrorLog.Add(Divider);
ErrorLog.Add(Format(sErrorsByTest,[sShortCheckFormatArgs]));
ErrorLog.Add(ShortChildName);
ErrorLog.Add(Divider);
ErrorLog.Add('');
end;
Inc(ErrorCount);
if CPoItem.InitialFuzzyState = false then
Inc(NonFuzzyErrorCount);
ErrorLog.Add(Format(sIncompatibleFormatArgs,[CPoItem.LineNr]));
ErrorLog.Add(Format(sFormatArgsID,[sCommentIdentifier, CPoItem.IdentifierLow]));
ErrorLog.Add(Format(sFormatArgsValues,[sMsgID,CPoItem.Original,sOriginal]));
ErrorLog.Add(Format(sFormatArgsValues,[sMsgStr,CPoItem.Translation,sTranslation]));
if CPoItem.InitialFuzzyState = true then
ErrorLog.Add(sNoteTranslationIsFuzzy);
ErrorLog.Add('');
end;
end;
end;
if (ErrorCount > 0) then
begin
ErrorLog.Add(Format(sNrErrorsFound,[ErrorCount]));
ErrorLog.Add(Divider);
ErrorLog.Add('');
ErrorLog.Add('');
end;
DoTestEnd(PoTestTypeNames[pttCheckFormatArgs], ErrorCount);
//debugln('TPoFamily.CheckIncompatibleFormatArgs: ',Dbgs(ErrorCount),' Errors');
end;
procedure TPoFamily.CheckMissingIdentifiers(out ErrorCount: Integer;
ErrorLog: TStrings);
var
i: Integer;
MPoItem, CPoItem: TPOFileItem;
begin
//debugln('TPoFamily.CheckMissingIdentifiers');
DoTestStart(PoTestTypeNames[pttCheckMissingIdentifiers], ShortChildName);
ErrorCount := NoError;
for i := 0 to FMaster.Count - 1 do
begin
MPoItem := FMaster.PoItems[i];
if Assigned(MPoItem) and (MPoItem.IdentifierLow <> '') then
begin
CPoItem := FChild.FindPoItem(MPoItem.IdentifierLow);
if not Assigned(CPoItem) then
begin
if (ErrorCount = 0) then
begin
ErrorLog.Add(Divider);
ErrorLog.Add(Format(sErrorsByTest,[sShortCheckMissingIdentifiers]));
ErrorLog.Add(ShortChildName);
ErrorLog.Add(Divider);
ErrorLog.Add('');
end;
Inc(ErrorCount);
ErrorLog.Add(Format(sLineInFileName,
[MPoItem.LineNr,ShortMasterName]));
ErrorLog.Add(Format(sIdentifierNotFoundIn,
[MPoItem.IdentifierLow,ShortChildName]));
ErrorLog.Add('');
end;
end;
end;
//Now reverse the search
for i := 0 to FChild.Count - 1 do
begin
CPoItem := FChild.PoItems[i];
if Assigned(CPoItem) and (CPoItem.IdentifierLow <> '') then
begin
MPoItem := FMaster.FindPoItem(CPoItem.IdentifierLow);
if not Assigned(MPoItem) then
begin
if (ErrorCount = 0) then
begin
ErrorLog.Add(Divider);
ErrorLog.Add(Format(sErrorsByTest,[sShortCheckMissingIdentifiers]));
ErrorLog.Add(ShortChildName);
ErrorLog.Add(Divider);
ErrorLog.Add('');
end;
Inc(ErrorCount);
ErrorLog.Add(Format(sLineNr,
[CPoItem.LineNr]));
ErrorLog.Add(Format(sMissingMasterIdentifier,
[CPoItem.IdentifierLow,ShortChildName,ShortMasterName]));
ErrorLog.Add('');
end;
end;
end;
if (ErrorCount > 0) then
begin
ErrorLog.Add(Format(sNrErrorsFound,[ErrorCount]));
ErrorLog.Add(Divider);
ErrorLog.Add('');
ErrorLog.Add('');
end;
DoTestEnd(PoTestTypeNames[pttCheckMissingIdentifiers], ErrorCount);
//debugln('TPoFamily.CheckMissingIdentifiers: ',Dbgs(ErrorCount),' Errors');
end;
procedure TPoFamily.CheckMismatchedOriginals(out ErrorCount: Integer;
ErrorLog: TStrings);
var
i: Integer;
MPoItem, CPoItem: TPOFileItem;
begin
//debugln('TPoFamily.CheckMismatchedOriginals');
DoTestStart(PoTestTypeNames[pttCheckMismatchedOriginals], ShortChildName);
ErrorCount := NoError;
for i := 0 to FMaster.Count - 1 do
begin
MPoItem := FMaster.PoItems[i];
CPoItem := FChild.FindPoItem(MpoItem.IdentifierLow);
if Assigned(CPoItem) then
begin
if (MPoItem.Original <> CPoItem.Original) then
begin
if (ErrorCount = 0) then
begin
ErrorLog.Add(Divider);
ErrorLog.Add(Format(sErrorsByTest,[sShortCheckMismatchedOriginals]));
ErrorLog.Add(ShortChildName);
ErrorLog.Add(Divider);
ErrorLog.Add('');
end;
Inc(ErrorCount);
ErrorLog.Add(Format(sLineInFileName,[CpoItem.LineNr, ShortChildName]));
ErrorLog.Add(Format(sMismatchOriginalsID,[CPoItem.IdentifierLow]));
ErrorLog.Add(Format(sMismatchOriginalsM,[ShortMasterName,MPoItem.Original]));
ErrorLog.Add(Format(sMismatchOriginalsC,[ShortChildName, CPoItem.Original]));
ErrorLog.Add('');
end;
end;
end;
if (ErrorCount > 0) then
begin
ErrorLog.Add(Format(sNrErrorsFound,[ErrorCount]));
ErrorLog.Add(Divider);
ErrorLog.Add('');
ErrorLog.Add('');
end;
DoTestEnd(PoTestTypeNames[pttCheckMismatchedOriginals], ErrorCount);
//debugln('TPoFamily.CheckMismatchedOriginals: ',Dbgs(ErrorCount),' Errors');
end;
procedure TPoFamily.CheckDuplicateOriginals(out WarningCount: Integer;
ErrorLog: TStrings);
var
i: Integer;
PoItem: TPOFileItem;
DupItemsList: TStringHashList;
LastHash, CurHash: Cardinal;
begin
//debugln('TPoFamily.CheckMismatchedOriginals');
WarningCount := 0;
DupItemsList := TStringHashList.Create(true);
for i := 0 to FMaster.Items.Count - 1 do begin
PoItem := TPOFileItem(FMaster.Items[i]);
if PoItem.Duplicate = true then
DupItemsList.Add(PoItem.Original, PoItem);
end;
//debugln('TPoFamily.CehckDuplicateOriginals');
//debugln('DupItemsList.Count = ',DbgS(DupItemsList.Count));
LastHash := 0;
for i := DupItemsList.Count - 1 downto 0 do
begin
PoItem := TPoFileItem(DupItemsList.List[i]^.Data);
if Assigned(PoItem) then
begin
CurHash := DupItemsList.List[i]^.HashValue;
if (WarningCount = 0) then
begin
ErrorLog.Add(Format(sFile, [ShortMasterName]));
ErrorLog.Add('');
end;
if (CurHash <> LastHash) then
begin//new value for PoItem.Original
LastHash := CurHash;
Inc(WarningCount);
if (WarningCount > 1) then ErrorLog.Add('');
ErrorLog.Add(Format(sDuplicateOriginals,[PoItem.Original]));
//debugln(format('The (untranslated) value "%s" is used for more than 1 entry:',[PoItem.Original]));
end;
ErrorLog.Add(format(sDuplicateLineNrWithValue,[PoItem.LineNr,PoItem.IdentifierLow]));
//debugln(format(sDuplicateLineNrWithValue,[PoItem.LineNr,PoItem.IdentifierLow]));
end;
end;
if (WarningCount > 0) then
begin
ErrorLog.Add('');
ErrorLog.Add(Format(sNrWarningsFound,[WarningCount]));
ErrorLog.Add(Divider);
ErrorLog.Add('');
end;
DupItemsList.Free;
//debugln('TPoFamily.CheckDuplicateOriginals: ',Dbgs(WarningCount),' Errors');
end;
procedure TPoFamily.CheckStatistics(ErrorCnt: Integer);
var
NrTranslated, NrUntranslated, NrFuzzy, NrTotal: Integer;
begin
//debugln('TPoFamily.CheckStatistics');
NrTranslated := FChild.Statistics.Translated;
NrUntranslated := FChild.Statistics.Untranslated;
NrFuzzy := FChild.Statistics.Fuzzy;
NrTotal := NrTranslated + NrUntranslated + NrFuzzy;
if (NrTotal > 0) then
begin
FPoFamilyStats.Add(ChildName, NrTranslated, NrUntranslated, NrFuzzy, ErrorCnt);
end;
//debugln('TPoFamily.CheckIncompatibleFormatArgs: ',Dbgs(ErrorCount),' Errors');
end;
{
procedure TPoFamily.RunTests
Pre conditions:
* Master and a matching Child must be assigned at start ot testing
* If a Child is assigned it must be child of Master
}
procedure TPoFamily.RunTests(out ErrorCount, NonFuzzyErrorCount, WarningCount,
TranslatedCount, UntranslatedCount, FuzzyCount: Integer; ErrorLog, StatLog,
DupLog: TStringList);
var
SL: TStringList;
CurrErrCnt, CurrNonFuzzyErrCnt, CurrWarnCnt, ThisErrCnt: Integer;
i: Integer;
CurrChildName: String;
S: String;
begin
SL := nil;
FPoFamilyStats.Clear;
ErrorCount := NoError;
NonFuzzyErrorCount := NoError;
WarningCount := NoError;
TranslatedCount := 0;
UntranslatedCount := 0;
FuzzyCount := 0;
if (not Assigned(FMaster)) and (not Assigned(FChild)) then
begin
{$ifdef DebugSimplePoFiles}
debugln('TPoFamily.RunTests: Both master and child are unassigned.');
{$endif}
Exit;
end;
if not Assigned(FMaster) then
begin
S := ExtractMasterNameFromChildName(FChildName);
if (S <> '') and FileExistsUtf8(S) then
begin
SetMasterName(S);
end
else
begin
{$ifdef DebugSimplePoFiles}
Debugln('TPoFamily.RunTests: Cannot find master for ',ShortChildName);
{$endif}
Exit;
end
end;
if FLangID = lang_all then
begin
SL := FindAllTranslatedPoFiles(FMasterName);
//We want current Child (if currently assigned) at index 0
if Assigned(FChild) then
begin
for i := 0 to SL.Count - 1 do
begin
if (CompareFileNames(Sl.Strings[i], FChildName) = 0) then
begin
if (i <> 0) then SL.Exchange(i,0);
Break;
end;
end;
end;
end
else
begin
SL := TStringList.Create;
if Assigned(FChild) then Sl.Add(FChildName);
end;
// for i := 0 to sl.count - 1 do debugln(extractfilename(sl.strings[i]));
try
//First run checks that are Master-only
CheckDuplicateOriginals(CurrWarnCnt, DupLog);
WarningCount := CurrWarnCnt + WarningCount;
{$ifdef DebugSimplePoFiles}
Debugln('TPoFamily.RunTests: number of childs for testing = ',DbgS(Sl.Count));
{$endif}
if (FTestTypes <> []) and (Sl.Count = 0) then
begin
{$ifdef DebugSimplePoFiles}
Debugln('TPoFamily.RunTests: Warning: No child selected or found for selected tests');
{$endif}
ErrorLog.Add(Divider);
ErrorLog.Add('Warning: No child selected (or found) for selected tests.');
ErrorLog.Add(Divider);
end;
//then iterate all Children
for i := 0 to SL.Count - 1 do
begin
ThisErrCnt:= 0;
CurrChildName := SL.Strings[i];
//debugln('TPoFamily.RunTests: setting ChildName to ',CurrChildName);
SetChildName(CurrChildName);
if (pttCheckNrOfItems in FTestTypes) then
begin
CheckNrOfItems(CurrErrCnt, ErrorLog);
ErrorCount := CurrErrCnt + ErrorCount;
ThisErrCnt := ThisErrCnt + CurrErrCnt;
end;
if (pttCheckFormatArgs in FTestTypes) then
begin
CheckFormatArgs(CurrErrCnt, CurrNonFuzzyErrCnt, ErrorLog);
ErrorCount := CurrErrCnt + ErrorCount;
ThisErrCnt := ThisErrCnt + CurrErrCnt;
NonFuzzyErrorCount := CurrNonFuzzyErrCnt + NonFuzzyErrorCount;
end;
if (pttCheckMissingIdentifiers in FTestTypes) then
begin
CheckMissingIdentifiers(CurrErrCnt, ErrorLog);
ErrorCount := CurrErrCnt + ErrorCount;
ThisErrCnt := ThisErrCnt + CurrErrCnt;
end;
if (pttCheckMismatchedOriginals in FTestTypes) then
begin
CheckMismatchedOriginals(CurrErrCnt, ErrorLog);
ErrorCount := CurrErrCnt + ErrorCount;
ThisErrCnt := ThisErrCnt + CurrErrCnt;
end;
//Always run this as the last test please
TranslatedCount := FChild.Statistics.Translated;
UntranslatedCount := FChild.Statistics.Untranslated;
FuzzyCount := FChild.Statistics.Fuzzy;
CheckStatistics(ThisErrCnt);
{
if (ptt in FTestTypes) then
begin
Check(CurrErrCnt, ErrorLog);
ErrorCount := CurrErrCnt + ErrorCount;
end;
}
end;
//Generate statistics
if FPoFamilyStats.Count > 0 then
FPoFamilyStats.AddStatisticsToLog(StatLog);
finally
SL.Free;
end;
//debugln('TPoFamilyRunTests: ErrorCount = ',DbgS(ErrorCount));
end;
procedure InitTestOptions;
var
Index: TPoTestType;
begin
for Index := Low(TPoTestType) to High(TPoTestType) do optRunAllTests := optRunAllTests + [Index];
end;
Initialization
InitTestOptions;
end.