mirror of
				https://gitlab.com/freepascal.org/lazarus/lazarus.git
				synced 2025-11-04 14:29:25 +01:00 
			
		
		
		
	IDE: updating po files using codetools file caches
git-svn-id: trunk@34334 -
This commit is contained in:
		
							parent
							
								
									87b8887d73
								
							
						
					
					
						commit
						1b781cdb35
					
				@ -32,7 +32,7 @@ interface
 | 
			
		||||
uses
 | 
			
		||||
  Classes, SysUtils, GetText, LCLProc, Translations,
 | 
			
		||||
  IDEProcs, FileProcs, avl_tree,
 | 
			
		||||
  CodeToolManager, DirectoryCacher,
 | 
			
		||||
  CodeToolManager, DirectoryCacher, CodeCache,
 | 
			
		||||
  LazarusIDEStrConsts;
 | 
			
		||||
  { IDE Language (Human, not computer) }
 | 
			
		||||
 | 
			
		||||
@ -65,6 +65,8 @@ type
 | 
			
		||||
    property Items[Index: integer]: TLazarusTranslation read GetItems; default;
 | 
			
		||||
  end;
 | 
			
		||||
 | 
			
		||||
  PPOFile = ^TPOFile;
 | 
			
		||||
  
 | 
			
		||||
// translate all resource strings
 | 
			
		||||
procedure TranslateResourceStrings(const BaseDirectory, CustomLang: string);
 | 
			
		||||
 | 
			
		||||
@ -77,6 +79,12 @@ procedure CollectTranslations(const LazarusDir: string);
 | 
			
		||||
function ConvertRSTFiles(RSTDirectory, PODirectory: string;
 | 
			
		||||
  POFilename: string = '' // set POFilename to gather all rst into one po file
 | 
			
		||||
  ): Boolean;
 | 
			
		||||
procedure UpdatePoFileAndTranslations(SrcFiles: TStrings;
 | 
			
		||||
  const POFilename: string);
 | 
			
		||||
procedure UpdateBasePoFile(SrcFiles: TStrings;
 | 
			
		||||
  const POFilename: string; POFile: PPOFile = nil);
 | 
			
		||||
function FindTranslatedPoFiles(const BasePOFilename: string): TStringList;
 | 
			
		||||
procedure UpdateTranslatedPoFile(const BasePOFile: TPOFile; TranslatedFilename: string);
 | 
			
		||||
 | 
			
		||||
var
 | 
			
		||||
  LazarusTranslations: TLazarusTranslations = nil;
 | 
			
		||||
@ -250,7 +258,7 @@ begin
 | 
			
		||||
      for i:=0 to Items.Count-1 do begin
 | 
			
		||||
        Item:=PItem(Items[i]);
 | 
			
		||||
        if (not Item^.NeedUpdate) or (Item^.RSTFileList.Count=0) then continue;
 | 
			
		||||
        UpdatePoFile(Item^.RSTFileList, Item^.OutputFilename);
 | 
			
		||||
        UpdatePoFileAndTranslations(Item^.RSTFileList, Item^.OutputFilename);
 | 
			
		||||
      end;
 | 
			
		||||
      Result:=true;
 | 
			
		||||
    except
 | 
			
		||||
@ -271,6 +279,148 @@ begin
 | 
			
		||||
  end;
 | 
			
		||||
end;
 | 
			
		||||
 | 
			
		||||
procedure UpdatePoFileAndTranslations(SrcFiles: TStrings;
 | 
			
		||||
  const POFilename: string);
 | 
			
		||||
var
 | 
			
		||||
  BasePOFile: TPOFile;
 | 
			
		||||
  TranslatedFiles: TStringList;
 | 
			
		||||
  TranslatedFilename: String;
 | 
			
		||||
begin
 | 
			
		||||
  BasePOFile:=nil;
 | 
			
		||||
  UpdateBasePoFile(SrcFiles,POFilename,@BasePOFile);
 | 
			
		||||
  if BasePOFile=nil then exit;
 | 
			
		||||
  TranslatedFiles:=nil;
 | 
			
		||||
  try
 | 
			
		||||
    TranslatedFiles:=FindTranslatedPoFiles(POFilename);
 | 
			
		||||
    if TranslatedFiles=nil then exit;
 | 
			
		||||
    for TranslatedFilename in TranslatedFiles do begin
 | 
			
		||||
      if FileAgeCached(TranslatedFilename)>=FileAgeCached(POFilename) then
 | 
			
		||||
        continue;
 | 
			
		||||
      UpdateTranslatedPoFile(BasePOFile,TranslatedFilename);
 | 
			
		||||
    end;
 | 
			
		||||
  finally
 | 
			
		||||
    TranslatedFiles.Free;
 | 
			
		||||
    BasePOFile.Free;
 | 
			
		||||
  end;
 | 
			
		||||
end;
 | 
			
		||||
 | 
			
		||||
procedure UpdateBasePoFile(SrcFiles: TStrings;
 | 
			
		||||
  const POFilename: string; POFile: PPOFile);
 | 
			
		||||
var
 | 
			
		||||
  BasePOFile: TPOFile;
 | 
			
		||||
  i: Integer;
 | 
			
		||||
  Filename: String;
 | 
			
		||||
  POBuf: TCodeBuffer;
 | 
			
		||||
  FileType: TStringsType;
 | 
			
		||||
  SrcBuf: TCodeBuffer;
 | 
			
		||||
  SrcLines: TStringList;
 | 
			
		||||
  OldChangeStep: Integer;
 | 
			
		||||
begin
 | 
			
		||||
  POBuf:=CodeToolBoss.LoadFile(POFilename,true,false);
 | 
			
		||||
  SrcLines:=TStringList.Create;
 | 
			
		||||
  BasePOFile := TPOFile.Create;
 | 
			
		||||
  try
 | 
			
		||||
    if POBuf<>nil then
 | 
			
		||||
      BasePOFile.ReadPOText(POBuf.Source);
 | 
			
		||||
    BasePOFile.Tag:=1;
 | 
			
		||||
 | 
			
		||||
    // Update po file with lrt or/and rst files
 | 
			
		||||
    for i:=0 to SrcFiles.Count-1 do begin
 | 
			
		||||
      Filename:=SrcFiles[i];
 | 
			
		||||
      if CompareFileExt(Filename,'.lrt',false)=0 then
 | 
			
		||||
        FileType:=stLrt
 | 
			
		||||
      else if CompareFileExt(Filename,'.rst',false)=0 then
 | 
			
		||||
        FileType:=stRst
 | 
			
		||||
      else
 | 
			
		||||
        continue;
 | 
			
		||||
      SrcBuf:=CodeToolBoss.LoadFile(Filename,true,false);
 | 
			
		||||
      if SrcBuf=nil then continue;
 | 
			
		||||
      SrcLines.Text:=SrcBuf.Source;
 | 
			
		||||
      BasePOFile.UpdateStrings(SrcLines,FileType);
 | 
			
		||||
    end;
 | 
			
		||||
    SrcLines.Clear;
 | 
			
		||||
    BasePOFile.SaveToStrings(SrcLines);
 | 
			
		||||
    if POBuf=nil then begin
 | 
			
		||||
      POBuf:=CodeToolBoss.CreateFile(POFilename);
 | 
			
		||||
      if POBuf=nil then exit;
 | 
			
		||||
    end;
 | 
			
		||||
    OldChangeStep:=POBuf.ChangeStep;
 | 
			
		||||
    //debugln(['UpdateBasePoFile ',POFilename,' Modified=',POBuf.Source<>SrcLines.Text]);
 | 
			
		||||
    POBuf.Source:=SrcLines.Text;
 | 
			
		||||
    if (not POBuf.IsVirtual) and (OldChangeStep<>POBuf.ChangeStep) then begin
 | 
			
		||||
      debugln(['UpdateBasePoFile saving ',POBuf.Filename]);
 | 
			
		||||
      POBuf.Save;
 | 
			
		||||
    end;
 | 
			
		||||
  finally
 | 
			
		||||
    SrcLines.Free;
 | 
			
		||||
    if POFile<>nil then
 | 
			
		||||
      POFile^:=BasePOFile
 | 
			
		||||
    else
 | 
			
		||||
      BasePOFile.Free;
 | 
			
		||||
  end;
 | 
			
		||||
end;
 | 
			
		||||
 | 
			
		||||
function FindTranslatedPoFiles(const BasePOFilename: string): TStringList;
 | 
			
		||||
var
 | 
			
		||||
  Path: String;
 | 
			
		||||
  Name: String;
 | 
			
		||||
  NameOnly: String;
 | 
			
		||||
  Dir: TCTDirectoryCache;
 | 
			
		||||
  Files: TStrings;
 | 
			
		||||
  Filename: String;
 | 
			
		||||
begin
 | 
			
		||||
  Result:=TStringList.Create;
 | 
			
		||||
  Path:=ExtractFilePath(BasePOFilename);
 | 
			
		||||
  Name:=ExtractFileName(BasePOFilename);
 | 
			
		||||
  NameOnly:=ExtractFileNameOnly(Name);
 | 
			
		||||
  Dir:=CodeToolBoss.DirectoryCachePool.GetCache(Path);
 | 
			
		||||
  Files:=TStringList.Create;
 | 
			
		||||
  try
 | 
			
		||||
    Dir.GetFiles(Files,false);
 | 
			
		||||
    for Filename in Files do begin
 | 
			
		||||
      if CompareFilenames(Filename,Name)=0 then continue;
 | 
			
		||||
      if CompareFileExt(Filename,'.po',false)<>0 then continue;
 | 
			
		||||
      if (CompareFilenames(LeftStr(Filename,length(NameOnly)),NameOnly)<>0)
 | 
			
		||||
      then
 | 
			
		||||
        continue;
 | 
			
		||||
      Result.Add(Path+Filename);
 | 
			
		||||
    end;
 | 
			
		||||
  finally
 | 
			
		||||
    Files.Free;
 | 
			
		||||
    Dir.Release;
 | 
			
		||||
  end;
 | 
			
		||||
end;
 | 
			
		||||
 | 
			
		||||
procedure UpdateTranslatedPoFile(const BasePOFile: TPOFile;
 | 
			
		||||
  TranslatedFilename: string);
 | 
			
		||||
var
 | 
			
		||||
  POBuf: TCodeBuffer;
 | 
			
		||||
  POFile: TPOFile;
 | 
			
		||||
  Lines: TStringList;
 | 
			
		||||
  OldChangeStep: Integer;
 | 
			
		||||
begin
 | 
			
		||||
  POFile := TPOFile.Create;
 | 
			
		||||
  Lines:=TStringList.Create;
 | 
			
		||||
  try
 | 
			
		||||
    POBuf:=CodeToolBoss.LoadFile(TranslatedFilename,true,false);
 | 
			
		||||
    if POBuf<>nil then
 | 
			
		||||
      POFile.ReadPOText(POBuf.Source);
 | 
			
		||||
    POFile.Tag:=1;
 | 
			
		||||
    POFile.UpdateTranslation(BasePOFile);
 | 
			
		||||
    POFile.SaveToStrings(Lines);
 | 
			
		||||
    OldChangeStep:=POBuf.ChangeStep;
 | 
			
		||||
    //debugln(['UpdateTranslatedPoFile ',POBuf.Filename,' Modified=',POBuf.Source<>Lines.Text]);
 | 
			
		||||
    POBuf.Source:=Lines.Text;
 | 
			
		||||
    if (not POBuf.IsVirtual) and (OldChangeStep<>POBuf.ChangeStep) then begin
 | 
			
		||||
      //debugln(['UpdateTranslatedPoFile saving ',POBuf.Filename]);
 | 
			
		||||
      POBuf.Save;
 | 
			
		||||
    end;
 | 
			
		||||
  finally
 | 
			
		||||
    Lines.Free;
 | 
			
		||||
    POFile.Free;
 | 
			
		||||
  end;
 | 
			
		||||
end;
 | 
			
		||||
 | 
			
		||||
{-------------------------------------------------------------------------------
 | 
			
		||||
  TranslateResourceStrings
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -4365,7 +4365,7 @@ begin
 | 
			
		||||
    if Files.Tree.Count=0 then exit(mrOk);
 | 
			
		||||
    Files.GetNames(FileList);
 | 
			
		||||
    try
 | 
			
		||||
      UpdatePoFile(FileList, POFilename);
 | 
			
		||||
      UpdatePoFileAndTranslations(FileList, POFilename);
 | 
			
		||||
      Result := mrOk;
 | 
			
		||||
    except
 | 
			
		||||
      on E:EPOFileError do begin
 | 
			
		||||
 | 
			
		||||
@ -124,6 +124,7 @@ type
 | 
			
		||||
    procedure Report;
 | 
			
		||||
    procedure CreateHeader;
 | 
			
		||||
    procedure UpdateStrings(InputLines:TStrings; SType: TStringsType);
 | 
			
		||||
    procedure SaveToStrings(OutLst: TStrings);
 | 
			
		||||
    procedure SaveToFile(const AFilename: string);
 | 
			
		||||
    procedure UpdateItem(const Identifier: string; Original: string);
 | 
			
		||||
    procedure UpdateTranslation(BasePOFile: TPOFile);
 | 
			
		||||
@ -148,7 +149,6 @@ var
 | 
			
		||||
    // if you don't use UTF-8, install a proper widestring manager and set this
 | 
			
		||||
    // to false.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// translate resource strings for one unit
 | 
			
		||||
function TranslateUnitResourceStrings(const ResUnitName, BaseFilename,
 | 
			
		||||
  Lang, FallbackLang: string):TTranslateUnitResult; overload;
 | 
			
		||||
@ -167,6 +167,12 @@ function UpdatePoFile(Files: TStrings; const POFilename: string): boolean;
 | 
			
		||||
 | 
			
		||||
implementation
 | 
			
		||||
 | 
			
		||||
function ComparePOItems(Item1, Item2: Pointer): Integer;
 | 
			
		||||
begin
 | 
			
		||||
  Result := CompareText(TPOFileItem(Item1).IdentifierLow,
 | 
			
		||||
                        TPOFileItem(Item2).IdentifierLow);
 | 
			
		||||
end;
 | 
			
		||||
 | 
			
		||||
function UTF8ToSystemCharSet(const s: string): string; inline;
 | 
			
		||||
begin
 | 
			
		||||
  if SystemCharSetIsUTF8 then
 | 
			
		||||
@ -178,7 +184,6 @@ begin
 | 
			
		||||
  {$ENDIF}
 | 
			
		||||
end;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function StrToPoStr(const s:string):string;
 | 
			
		||||
var
 | 
			
		||||
  SrcPos, DestPos: Integer;
 | 
			
		||||
@ -975,32 +980,8 @@ begin
 | 
			
		||||
  RemoveUntaggedModules;
 | 
			
		||||
end;
 | 
			
		||||
 | 
			
		||||
procedure TPOFile.RemoveTaggedItems(aTag: Integer);
 | 
			
		||||
procedure TPOFile.SaveToStrings(OutLst: TStrings);
 | 
			
		||||
var
 | 
			
		||||
  Item: TPOFileItem;
 | 
			
		||||
  i: Integer;
 | 
			
		||||
begin
 | 
			
		||||
  // get rid of all entries that have Tag=aTag
 | 
			
		||||
  for i:=FItems.Count-1 downto 0 do begin
 | 
			
		||||
    Item := TPOFileItem(FItems[i]);
 | 
			
		||||
    if Item.Tag<>aTag then
 | 
			
		||||
      Continue;
 | 
			
		||||
    FIdentifierLowToItem.Remove(Item.IdentifierLow);
 | 
			
		||||
    //FOriginalToItem.Remove(Item.Original); // isn't this tricky?
 | 
			
		||||
    FItems.Delete(i);
 | 
			
		||||
    Item.Free;
 | 
			
		||||
  end;
 | 
			
		||||
end;
 | 
			
		||||
 | 
			
		||||
function ComparePOItems(Item1, Item2: Pointer): Integer;
 | 
			
		||||
begin
 | 
			
		||||
  result := CompareText(TPOFileItem(Item1).IdentifierLow,
 | 
			
		||||
                        TPOFileItem(Item2).IdentifierLow);
 | 
			
		||||
end;
 | 
			
		||||
 | 
			
		||||
procedure TPOFile.SaveToFile(const AFilename: string);
 | 
			
		||||
var
 | 
			
		||||
  OutLst: TStringList;
 | 
			
		||||
  j: Integer;
 | 
			
		||||
 | 
			
		||||
  procedure WriteLst(const AProp, AValue: string );
 | 
			
		||||
@ -1053,23 +1034,44 @@ begin
 | 
			
		||||
  if FHelperList=nil then
 | 
			
		||||
    FHelperList:=TStringList.Create;
 | 
			
		||||
 | 
			
		||||
  // write header
 | 
			
		||||
  WriteItem(FHeader);
 | 
			
		||||
 | 
			
		||||
  // Sort list of items by identifier
 | 
			
		||||
  FItems.Sort(@ComparePOItems);
 | 
			
		||||
 | 
			
		||||
  for j:=0 to Fitems.Count-1 do
 | 
			
		||||
    WriteItem(TPOFileItem(FItems[j]));
 | 
			
		||||
end;
 | 
			
		||||
 | 
			
		||||
procedure TPOFile.RemoveTaggedItems(aTag: Integer);
 | 
			
		||||
var
 | 
			
		||||
  Item: TPOFileItem;
 | 
			
		||||
  i: Integer;
 | 
			
		||||
begin
 | 
			
		||||
  // get rid of all entries that have Tag=aTag
 | 
			
		||||
  for i:=FItems.Count-1 downto 0 do begin
 | 
			
		||||
    Item := TPOFileItem(FItems[i]);
 | 
			
		||||
    if Item.Tag<>aTag then
 | 
			
		||||
      Continue;
 | 
			
		||||
    FIdentifierLowToItem.Remove(Item.IdentifierLow);
 | 
			
		||||
    //FOriginalToItem.Remove(Item.Original); // isn't this tricky?
 | 
			
		||||
    FItems.Delete(i);
 | 
			
		||||
    Item.Free;
 | 
			
		||||
  end;
 | 
			
		||||
end;
 | 
			
		||||
 | 
			
		||||
procedure TPOFile.SaveToFile(const AFilename: string);
 | 
			
		||||
var
 | 
			
		||||
  OutLst: TStringList;
 | 
			
		||||
begin
 | 
			
		||||
  OutLst := TStringList.Create;
 | 
			
		||||
  try
 | 
			
		||||
    // write header
 | 
			
		||||
    WriteItem(FHeader);
 | 
			
		||||
    
 | 
			
		||||
    // Sort list of items by identifier
 | 
			
		||||
    FItems.Sort(@ComparePOItems);
 | 
			
		||||
    
 | 
			
		||||
    for j:=0 to Fitems.Count-1 do
 | 
			
		||||
      WriteItem(TPOFileItem(FItems[j]));
 | 
			
		||||
      
 | 
			
		||||
    SaveToStrings(OutLst);
 | 
			
		||||
    OutLst.SaveToFile(UTF8ToSys(AFilename));
 | 
			
		||||
    
 | 
			
		||||
  finally
 | 
			
		||||
    OutLst.Free;
 | 
			
		||||
  end;
 | 
			
		||||
  
 | 
			
		||||
end;
 | 
			
		||||
 | 
			
		||||
function SkipLineEndings(var P: PChar; var DecCount: Integer): Integer;
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user