mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-10-25 07:41:32 +02:00
updatepofiles tool now uses translations unit, localize scripts process the original package list
git-svn-id: trunk@17325 -
This commit is contained in:
parent
3910289f27
commit
5890d4f9fa
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -4361,6 +4361,7 @@ tools/snapshots/testmonitorcfg.pas svneol=native#text/plain
|
||||
tools/svn2revisioninc.lpi svneol=native#text/plain
|
||||
tools/svn2revisioninc.pas svneol=native#text/plain
|
||||
tools/update_pkgfileslcl_inc.sh svneol=native#text/plain
|
||||
tools/updatepofiles.lpi svneol=native#text/plain
|
||||
tools/updatepofiles.pas svneol=native#text/pascal
|
||||
tools/xpm_to_png/convert.bat svneol=native#text/plain
|
||||
tools/xpm_to_png/xpm_to_png.lpi svneol=native#text/plain
|
||||
|
||||
@ -148,7 +148,6 @@ function UTF8ToSystemCharSet(const s: string): string; inline;
|
||||
|
||||
function UpdatePoFile(Files: TStrings; const POFilename: string): boolean;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
function UTF8ToSystemCharSet(const s: string): string; inline;
|
||||
@ -229,12 +228,58 @@ var
|
||||
BasePoFile, POFile: TPoFile;
|
||||
i: Integer;
|
||||
E: EPOFileError;
|
||||
|
||||
procedure UpdatePoFilesTranslation;
|
||||
var
|
||||
j: Integer;
|
||||
Lines: TStringList;
|
||||
begin
|
||||
// Update translated PO files
|
||||
Lines := FindAllTranslatedPoFiles(POFilename);
|
||||
try
|
||||
for j:=0 to Lines.Count-1 do begin
|
||||
POFile := TPOFile.Create(Lines[j], true);
|
||||
try
|
||||
POFile.Tag:=1;
|
||||
POFile.UpdateTranslation(BasePOFile);
|
||||
try
|
||||
POFile.SaveToFile(Lines[j]);
|
||||
except
|
||||
on Ex: Exception do begin
|
||||
E := EPOFileError.Create(Ex.Message);
|
||||
E.ResFileName:=Lines[j];
|
||||
E.POFileName:=POFileName;
|
||||
raise E;
|
||||
end;
|
||||
end;
|
||||
finally
|
||||
POFile.Free;
|
||||
end;
|
||||
end;
|
||||
finally
|
||||
Lines.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
begin
|
||||
Result := false;
|
||||
|
||||
if (Files=nil) or (Files.Count=0) then
|
||||
|
||||
if (Files=nil) or (Files.Count=0) then begin
|
||||
|
||||
if FileExistsUTF8(POFilename) then begin
|
||||
// just update translated po files
|
||||
BasePOFile := TPOFile.Create(POFilename, true);
|
||||
try
|
||||
UpdatePoFilesTranslation;
|
||||
finally
|
||||
BasePOFile.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
exit;
|
||||
|
||||
end;
|
||||
|
||||
InputLines := TStringList.Create;
|
||||
try
|
||||
// Read base po items
|
||||
@ -272,29 +317,8 @@ begin
|
||||
BasePOFile.SaveToFile(POFilename);
|
||||
Result := BasePOFile.Modified;
|
||||
|
||||
// Update translated PO files
|
||||
InputLines.Free;
|
||||
InputLines := FindAllTranslatedPoFiles(POFilename);
|
||||
for i:=0 to InputLines.Count-1 do begin
|
||||
POFile := TPOFile.Create(InputLines[i], true);
|
||||
try
|
||||
POFile.Tag:=1;
|
||||
POFile.UpdateTranslation(BasePOFile);
|
||||
try
|
||||
POFile.SaveToFile(InputLines[i]);
|
||||
except
|
||||
on Ex: Exception do begin
|
||||
E := EPOFileError.Create(Ex.Message);
|
||||
E.ResFileName:=InputLines[i];
|
||||
E.POFileName:=POFileName;
|
||||
raise E;
|
||||
end;
|
||||
end;
|
||||
finally
|
||||
POFile.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
UpdatePOFilesTranslation;
|
||||
|
||||
finally
|
||||
InputLines.Free;
|
||||
BasePOFile.Free;
|
||||
|
||||
67
localize.bat
67
localize.bat
@ -35,73 +35,84 @@ echo on
|
||||
|
||||
@REM IDE
|
||||
@set IDE_RST=units\%ArchOS%\LazarusIDEStrConsts.rst
|
||||
rstconv -c UTF-8 -i %IDE_RST% -o languages\lazaruside.po
|
||||
tools\updatepofiles languages\lazaruside.po
|
||||
tools\updatepofiles %IDE_RST% languages\lazaruside.po
|
||||
|
||||
@REM IDEIntf
|
||||
@set ObjInsp_RST=ideintf\units\%ArchOS%\ObjInspStrConsts.rst
|
||||
rstconv -c UTF-8 -i %ObjInsp_RST% -o ideintf\languages\objinspstrconsts.po
|
||||
tools\updatepofiles ideintf\languages\objinspstrconsts.po
|
||||
tools\updatepofiles %ObjInsp_RST% ideintf\languages\objinspstrconsts.po
|
||||
|
||||
@REM INSTALLER
|
||||
@set Installer_RST=tools\install\win\installerstrconsts.rst
|
||||
if not exist %Installer_RST% goto SkipInstaller
|
||||
rstconv -c UTF-8 -i %Installer_RST% -o languages\installerstrconsts.po
|
||||
tools\updatepofiles languages\installerstrconsts.po
|
||||
tools\updatepofiles %Installer_RST% languages\installerstrconsts.po
|
||||
:SkipInstaller
|
||||
|
||||
@REM CodeTools
|
||||
@set CodeTools_RST=components\codetools\units\%ArchOS%\CodeToolsStrConsts.rst
|
||||
rstconv -c UTF-8 -i %CodeTools_RST% -o components\codetools\languages\codetoolsstrconsts.po
|
||||
tools\updatepofiles components\codetools\languages\codetoolsstrconsts.po
|
||||
tools\updatepofiles %CodeTools_RST% components\codetools\languages\codetoolsstrconsts.po
|
||||
|
||||
@REM SynEdit
|
||||
@set SynEdit_RST=components\synedit\units\%ArchOS%\SynEditStrConst.rst
|
||||
rstconv -c UTF-8 -i %SynEdit_RST% -o components\synedit\languages\synedit.po
|
||||
tools\updatepofiles components\synedit\languages\synedit.po
|
||||
tools\updatepofiles %SynEdit_RST% components\synedit\languages\synedit.po
|
||||
|
||||
@REM SynMacroRecorder
|
||||
@set SynMacroRec_RST=components\synedit\units\%ArchOS%\synmacrorecorder.rst
|
||||
rstconv -c UTF-8 -i %SynMacroRec_RST% -o components\synedit\languages\synmacrorecorder.po
|
||||
tools\updatepofiles components\synedit\languages\synmacrorecorder.po
|
||||
tools\updatepofiles %SynMacroRec_RST% components\synedit\languages\synmacrorecorder.po
|
||||
|
||||
@REM SynUniHighLighterShellScript
|
||||
@set SynUniHighLighterShellScript_RST=components\synedit\units\%ArchOS%\synhighlighterunixshellscript.rst
|
||||
rstconv -c UTF-8 -i %SynUniHighLighterShellScript_RST% -o components\synedit\languages\synhighlighterunixshellscript.po
|
||||
tools\updatepofiles components\synedit\languages\synhighlighterunixshellscript.po
|
||||
tools\updatepofiles %SynUniHighLighterShellScript_RST% components\synedit\languages\synhighlighterunixshellscript.po
|
||||
|
||||
@REM LCL
|
||||
@set LCL_RST=lcl\units\%ArchOS%\lclstrconsts.rst
|
||||
rstconv -c UTF-8 -i %LCL_RST% -o lcl\languages\lclstrconsts.po
|
||||
tools\updatepofiles lcl\languages\lclstrconsts.po
|
||||
tools\updatepofiles %LCL_RST% lcl\languages\lclstrconsts.po
|
||||
|
||||
@REM CGI
|
||||
@set CGI_RST=components\cgi\lib\%ArchOS%\cgimodules.rst
|
||||
rstconv -c UTF-8 -i %CGI_RST% -o components\cgi\languages\cgimodules.po
|
||||
tools\updatepofiles components\cgi\languages\cgimodules.po
|
||||
tools\updatepofiles %CGI_RST% components\cgi\languages\cgimodules.po
|
||||
|
||||
@REM LazReport
|
||||
@set LazReport_RST=components\lazreport\source\lib\%ArchOS%\lr_const.rst
|
||||
tools\updatepofiles %LazReport_RST% components\lazreport\source\languages\lr_const.po
|
||||
|
||||
@REM MemDS
|
||||
@set MemDS_RST=components\memds\lib\%ArchOS%\frmselectdataset.rst
|
||||
tools\updatepofiles %MemDS_RST% components\memds\languages\frmselectdataset.po
|
||||
|
||||
@REM Printers
|
||||
@set Printers_RST=components\printers\design\lib\%ArchOS%\ideprinting.rst
|
||||
rstconv -c UTF-8 -i %Printers_RST% -o components\printers\design\languages\ideprinting.po
|
||||
tools\updatepofiles components\printers\design\languages\ideprinting.po
|
||||
tools\updatepofiles %Printers_RST% components\printers\design\languages\ideprinting.po
|
||||
|
||||
@REM ProjectTemplates
|
||||
@set ProjectTemplates_RST=components\projecttemplates\lib\%ArchOS%\frmtemplatevariables.rst
|
||||
rstconv -c UTF-8 -i %ProjectTemplates_RST% -o components\projecttemplates\languages\frmtemplatevariables.po
|
||||
tools\updatepofiles components\projecttemplates\languages\frmtemplatevariables.po
|
||||
tools\updatepofiles %ProjectTemplates_RST% components\projecttemplates\languages\frmtemplatevariables.po
|
||||
|
||||
@set ProjectTemplates_RST=components\projecttemplates\lib\%ArchOS%\idetemplateproject.rst
|
||||
rstconv -c UTF-8 -i %ProjectTemplates_RST% -o components\projecttemplates\languages\idetemplateproject.po
|
||||
tools\updatepofiles components\projecttemplates\languages\idetemplateproject.po
|
||||
tools\updatepofiles %ProjectTemplates_RST% components\projecttemplates\languages\idetemplateproject.po
|
||||
|
||||
@set ProjectTemplates_RST=components\projecttemplates\lib\%ArchOS%\projecttemplates.rst
|
||||
rstconv -c UTF-8 -i %ProjectTemplates_RST% -o components\projecttemplates\languages\projecttemplates.po
|
||||
tools\updatepofiles components\projecttemplates\languages\projecttemplates.po
|
||||
tools\updatepofiles %ProjectTemplates_RST% components\projecttemplates\languages\projecttemplates.po
|
||||
|
||||
@REM TDBF
|
||||
@set TDBF_RST=components\tdbf\lib\%ArchOS%\registerdbf.rst
|
||||
tools\updatepofiles %TDBF_RST% components\tdbf\languages\registerdbf.po
|
||||
|
||||
@REM TP_IPro
|
||||
@set TP_IPro_RST=components\turbopower_ipro\units\%ArchOS%\ipconst.rst
|
||||
tools\updatepofiles %TP_IPro_RST% components\turbopower_ipro\languages\ipconst.po
|
||||
|
||||
@set TP_IPro_RST=components\turbopower_ipro\units\%ArchOS%\iputils.rst
|
||||
tools\updatepofiles %TP_IPro_RST% components\turbopower_ipro\languages\iputils.po
|
||||
|
||||
@REM MessageComposer
|
||||
@set MessageComposer_RST=components\messagecomposer\lib\%ArchOS%\messagecomposer.rst
|
||||
rstconv -c UTF-8 -i %MessageComposer_RST% -o components\messagecomposer\languages\messagecomposer.po
|
||||
tools\updatepofiles components\messagecomposer\languages\messagecomposer.po
|
||||
tools\updatepofiles %MessageComposer_RST% components\messagecomposer\languages\messagecomposer.po
|
||||
|
||||
@REM LazReport editor sample
|
||||
@set LREditor_RST=components\lazreport\samples\editor\maincalleditor.rst
|
||||
if not exist %LREditor_RST% goto SkipLREditor
|
||||
tools\updatepofiles %LREditor_RST% components\lazreport\samples\editor\languages\calleditorwithpkg.po
|
||||
:SkipLREditor
|
||||
|
||||
@goto Exit
|
||||
|
||||
|
||||
29
localize.sh
29
localize.sh
@ -30,8 +30,21 @@ fi
|
||||
RSTFILES=(
|
||||
". lazarusidestrconsts lazaruside"
|
||||
"ideintf objinspstrconsts"
|
||||
"components/codetools codetoolsstrconsts"
|
||||
"components/synedit syneditstrconst synedit"
|
||||
"components/synedit synmacrorecorder"
|
||||
"components/synedit synhighlighterunixshellscript"
|
||||
"components/tdbf registerdbf"
|
||||
"components/turbopower_ipro ipconst"
|
||||
"components/turbopower_ipro iputils"
|
||||
"components/cgi cgimodules"
|
||||
"components/lazreport/samples/editor maincalleditor calleditorwithpkg"
|
||||
"components/memds frmselectdataset"
|
||||
"components/messagecomposer messagecomposer"
|
||||
"components/printers/design ideprinting"
|
||||
"components/projecttemplates projecttemplates"
|
||||
"components/projecttemplates frmtemplatevariables"
|
||||
"components/projecttemplates idetemplateproject"
|
||||
"lcl lclstrconsts"
|
||||
)
|
||||
|
||||
@ -49,19 +62,9 @@ for idx in ${!RSTFILES[@]}; do
|
||||
|
||||
if [ -n "$RST" ]; then
|
||||
POFileFull=$RSTDIR/languages/$POFILE.po
|
||||
echo $POFileFull
|
||||
|
||||
echo 'msgid ""
|
||||
msgstr ""
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
' > $POFileFull
|
||||
|
||||
rstconv -i $RST -o $POFileFull.tmp
|
||||
cat $POFileFull.tmp >> $POFileFull
|
||||
rm $POFileFull.tmp
|
||||
./tools/updatepofiles $POFileFull
|
||||
|
||||
./tools/updatepofiles $RST $POFileFull
|
||||
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
57
tools/updatepofiles.lpi
Normal file
57
tools/updatepofiles.lpi
Normal file
@ -0,0 +1,57 @@
|
||||
<?xml version="1.0"?>
|
||||
<CONFIG>
|
||||
<ProjectOptions>
|
||||
<PathDelim Value="\"/>
|
||||
<Version Value="6"/>
|
||||
<General>
|
||||
<Flags>
|
||||
<SaveOnlyProjectUnits Value="True"/>
|
||||
<MainUnitHasUsesSectionForAllUnits Value="False"/>
|
||||
<MainUnitHasCreateFormStatements Value="False"/>
|
||||
<MainUnitHasTitleStatement Value="False"/>
|
||||
</Flags>
|
||||
<MainUnit Value="0"/>
|
||||
<TargetFileExt Value=".exe"/>
|
||||
<ActiveEditorIndexAtStart Value="0"/>
|
||||
</General>
|
||||
<VersionInfo>
|
||||
<ProjectVersion Value=""/>
|
||||
</VersionInfo>
|
||||
<PublishOptions>
|
||||
<Version Value="2"/>
|
||||
<IgnoreBinaries Value="False"/>
|
||||
<IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
|
||||
<ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/>
|
||||
</PublishOptions>
|
||||
<RunParams>
|
||||
<local>
|
||||
<FormatVersion Value="1"/>
|
||||
<LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
|
||||
</local>
|
||||
</RunParams>
|
||||
<RequiredPackages Count="1">
|
||||
<Item1>
|
||||
<PackageName Value="LCL"/>
|
||||
</Item1>
|
||||
</RequiredPackages>
|
||||
<Units Count="1">
|
||||
<Unit0>
|
||||
<Filename Value="updatepofiles.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="UpdatePoFiles"/>
|
||||
<CursorPos X="39" Y="113"/>
|
||||
<TopLine Value="100"/>
|
||||
<EditorIndex Value="0"/>
|
||||
<UsageCount Value="28"/>
|
||||
<Loaded Value="True"/>
|
||||
</Unit0>
|
||||
</Units>
|
||||
</ProjectOptions>
|
||||
<CompilerOptions>
|
||||
<Version Value="8"/>
|
||||
<PathDelim Value="\"/>
|
||||
<Other>
|
||||
<CompilerPath Value="$(CompPath)"/>
|
||||
</Other>
|
||||
</CompilerOptions>
|
||||
</CONFIG>
|
||||
@ -37,79 +37,31 @@ program UpdatePoFiles;
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
uses
|
||||
Classes, SysUtils, FileUtil, AvL_Tree;
|
||||
Classes, SysUtils, FileUtil, Translations;
|
||||
|
||||
type
|
||||
TMsgItem = record
|
||||
Comment: string;
|
||||
ID: string;
|
||||
Str: string;
|
||||
end;
|
||||
PMsgItem = ^TMsgItem;
|
||||
|
||||
function CompareMsgItems(Data1, Data2: pointer): integer;
|
||||
var
|
||||
MsgItem1: PMsgItem;
|
||||
MsgItem2: PMsgItem;
|
||||
begin
|
||||
MsgItem1:=PMsgItem(Data1);
|
||||
MsgItem2:=PMsgItem(Data2);
|
||||
Result:=CompareStr(MsgItem1^.ID,MsgItem2^.ID);
|
||||
end;
|
||||
|
||||
procedure DisposeMsgTree(var Tree: TAVLTree);
|
||||
var
|
||||
Node: TAVLTreeNode;
|
||||
MsgItem: PMsgItem;
|
||||
begin
|
||||
Node:=Tree.FindLowest;
|
||||
while Node<>nil do begin
|
||||
MsgItem:=PMsgItem(Node.Data);
|
||||
Dispose(MsgItem);
|
||||
Node:=Tree.FindSuccessor(Node);
|
||||
end;
|
||||
Tree.Free;
|
||||
Tree:=nil;
|
||||
end;
|
||||
|
||||
type
|
||||
TPoFile = class
|
||||
public
|
||||
Tree: TAVLTree;
|
||||
Header: TStringList;
|
||||
UTF8Header: string;
|
||||
constructor Create;
|
||||
destructor Destroy; override;
|
||||
end;
|
||||
|
||||
{ TPoFile }
|
||||
|
||||
constructor TPoFile.Create;
|
||||
begin
|
||||
Tree:=TAVLTree.Create(@CompareMsgItems);
|
||||
Header:=TStringList.Create;
|
||||
end;
|
||||
|
||||
destructor TPoFile.Destroy;
|
||||
begin
|
||||
DisposeMsgTree(Tree);
|
||||
Header.Free;
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
//==============================================================================
|
||||
var
|
||||
Files: TStringList;
|
||||
Prefix: string;
|
||||
ResFiles: array of TStringList;
|
||||
|
||||
procedure IncPrefix;
|
||||
procedure AddResFile(const PoIndex:Integer; const AResFile:string);
|
||||
begin
|
||||
Prefix:=Prefix+' ';
|
||||
if PoIndex>(Length(ResFiles)-1) then
|
||||
SetLength(ResFiles, PoIndex+1);
|
||||
|
||||
if ResFiles[PoIndex]=nil then
|
||||
ResFiles[PoIndex] := TStringList.Create;
|
||||
|
||||
ResFiles[PoIndex].Add(AResFile);
|
||||
end;
|
||||
|
||||
procedure DecPrefix;
|
||||
procedure ClearResFiles;
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
Prefix:=LeftStr(Prefix,length(Prefix)-2);
|
||||
for i:=0 to Length(ResFiles)-1 do
|
||||
if ResFiles[i]<>nil then
|
||||
ResFiles[i].Free;
|
||||
end;
|
||||
|
||||
function ParamsValid: boolean;
|
||||
@ -118,300 +70,74 @@ var
|
||||
Filename: String;
|
||||
Ext: String;
|
||||
Name: string;
|
||||
PoIndex: Integer;
|
||||
begin
|
||||
Result:=false;
|
||||
if ParamCount<1 then exit;
|
||||
PoIndex:=0;
|
||||
|
||||
if ParamCount<1 then
|
||||
exit;
|
||||
|
||||
for i:=1 to ParamCount do begin
|
||||
Filename:=ParamStrUTF8(1);
|
||||
|
||||
Filename:=ParamStrUTF8(i);
|
||||
|
||||
Ext:=ExtractFileExt(Filename);
|
||||
|
||||
if not FileExistsUTF8(Filename) then begin
|
||||
|
||||
if (Ext='.rst') or (Ext='.lrt') then
|
||||
continue; // ignore resource files
|
||||
|
||||
writeln('ERROR: file not found: ',FileName);
|
||||
exit;
|
||||
end;
|
||||
Ext:=ExtractFileExt(Filename);
|
||||
if (Ext<>'.po') then begin
|
||||
|
||||
if (Ext<>'.po') and (Ext<>'.rst') and (Ext<>'.lrt') then begin
|
||||
writeln('ERROR: invalid extension: ',Filename);
|
||||
exit;
|
||||
end;
|
||||
|
||||
Name:=ExtractFileName(Filename);
|
||||
Name:=LeftStr(Name,length(Name)-length(Ext));
|
||||
if Pos('.',Name)>0 then begin
|
||||
writeln('ERROR: invalid unitname: ',Name);
|
||||
exit;
|
||||
end;
|
||||
if Files=nil then Files:=TStringList.Create;
|
||||
Files.Add(Filename);
|
||||
|
||||
if Ext='.po' then begin
|
||||
if Files=nil then
|
||||
Files:=TStringList.Create;
|
||||
Files.Add(Filename);
|
||||
inc(PoIndex);
|
||||
SetLength(ResFiles, Files.Count); // make sure Files and ResFiles are in sync
|
||||
end else
|
||||
AddResFile(PoIndex, FileName);
|
||||
end;
|
||||
Result:=true;
|
||||
end;
|
||||
|
||||
function ReadMessageItem(SrcFile: TStringList; var Line: integer): PMsgItem;
|
||||
var
|
||||
s: string;
|
||||
begin
|
||||
New(Result);
|
||||
while Line<SrcFile.Count do begin
|
||||
s:=SrcFile[Line];
|
||||
if (s<>'') and (s[1]='#') then begin
|
||||
Result^.Comment:=Result^.Comment+copy(s,2,length(s));
|
||||
end
|
||||
else if (LeftStr(s,7)='msgid "') then begin
|
||||
// read ID
|
||||
Result^.ID:=copy(s,8,length(s)-8);
|
||||
inc(Line);
|
||||
while Line<SrcFile.Count do begin
|
||||
s:=SrcFile[Line];
|
||||
if (s<>'') and (s[1]='"') then begin
|
||||
Result^.ID:=Result^.ID+#10+copy(s,2,length(s)-2);
|
||||
inc(Line);
|
||||
end else
|
||||
break;
|
||||
end;
|
||||
// read Str
|
||||
if Line<SrcFile.Count then begin
|
||||
s:=SrcFile[Line];
|
||||
if LeftStr(s,8)='msgstr "' then begin
|
||||
Result^.Str:=copy(s,9,length(s)-9);
|
||||
inc(Line);
|
||||
while Line<SrcFile.Count do begin
|
||||
s:=SrcFile[Line];
|
||||
if (s<>'') and (s[1]='"') then begin
|
||||
Result^.Str:=Result^.Str+#10+copy(s,2,length(s)-2);
|
||||
inc(Line);
|
||||
end else
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
exit;
|
||||
end;
|
||||
inc(Line);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure WriteMessageItem(MsgItem: PMsgItem; DestFile: TStringList);
|
||||
|
||||
procedure WriteItem(const Prefix: string; Str: string);
|
||||
var
|
||||
s: String;
|
||||
p: Integer;
|
||||
begin
|
||||
s:=Prefix+' "';
|
||||
p:=1;
|
||||
while (p<=length(Str)) do begin
|
||||
if Str[p]=#10 then begin
|
||||
// a new line
|
||||
s:=s+copy(Str,1,p-1)+'"';
|
||||
DestFile.Add(s);
|
||||
Str:=copy(Str,p+1,length(Str));
|
||||
p:=1;
|
||||
// start new line
|
||||
s:='"';
|
||||
end else
|
||||
inc(p);
|
||||
end;
|
||||
if (Str<>'') or (s<>'"') then begin
|
||||
s:=s+Str+'"';
|
||||
DestFile.Add(s);
|
||||
end;
|
||||
end;
|
||||
|
||||
begin
|
||||
if MsgItem^.Comment<>'' then
|
||||
DestFile.Add('#'+MsgItem^.Comment);
|
||||
WriteItem('msgid',MsgItem^.ID);
|
||||
WriteItem('msgstr',MsgItem^.Str);
|
||||
DestFile.Add('');
|
||||
end;
|
||||
|
||||
function ReadPoFile(const Filename: string): TPoFile;
|
||||
var
|
||||
SrcFile: TStringList;
|
||||
MsgItem: PMsgItem;
|
||||
Line: Integer;
|
||||
begin
|
||||
Result:=TPoFile.Create;
|
||||
|
||||
// read source .po file
|
||||
//writeln(Prefix,'Loading ',Filename,' ...');
|
||||
SrcFile:=TStringList.Create;
|
||||
SrcFile.LoadFromFile(UTF8ToSys(Filename));
|
||||
|
||||
if (SrcFile.Count>0) and (copy(SrcFile[0],1,3)=UTF8FileHeader) then begin
|
||||
Result.UTF8Header:=copy(SrcFile[0],1,3);
|
||||
SrcFile[0]:=copy(SrcFile[0],4,length(SrcFile[0]));
|
||||
end;
|
||||
|
||||
Line:=0;
|
||||
while Line<SrcFile.Count do begin
|
||||
if (SrcFile[Line]='') then begin
|
||||
// empty line
|
||||
inc(Line);
|
||||
end
|
||||
else begin
|
||||
// message
|
||||
MsgItem:=ReadMessageItem(SrcFile,Line);
|
||||
// ignore doubles
|
||||
if (Result.Tree.FindKey(MsgItem,@CompareMsgItems)<>nil) then begin
|
||||
Dispose(MsgItem);
|
||||
continue;
|
||||
end;
|
||||
// add message
|
||||
Result.Tree.Add(MsgItem);
|
||||
end;
|
||||
end;
|
||||
|
||||
SrcFile.Free;
|
||||
end;
|
||||
|
||||
procedure WritePoFile(PoFile: TPoFile; const Filename: string);
|
||||
var
|
||||
DestFile: TStringList;
|
||||
Node: TAVLTreeNode;
|
||||
MsgItem: PMsgItem;
|
||||
Save: Boolean;
|
||||
OldDestFile: TStringList;
|
||||
begin
|
||||
//writeln(Prefix,'Saving ',Filename,' ...');
|
||||
DestFile:=TStringList.Create;
|
||||
if (PoFile.Header.Count>0) then begin
|
||||
DestFile.Add('msgid ""');
|
||||
DestFile.Add('msgstr ""');
|
||||
DestFile.AddStrings(PoFile.Header);
|
||||
DestFile.Add('');
|
||||
end;
|
||||
Node:=PoFile.Tree.FindLowest;
|
||||
while Node<>nil do begin
|
||||
MsgItem:=PMsgItem(Node.Data);
|
||||
WriteMessageItem(MsgItem,DestFile);
|
||||
Node:=PoFile.Tree.FindSuccessor(Node);
|
||||
end;
|
||||
if (PoFile.UTF8Header<>'') and (DestFile.Count>0) then
|
||||
DestFile[0]:=PoFile.UTF8Header+DestFile[0];
|
||||
Save:=true;
|
||||
if FileExistsUTF8(Filename) then begin
|
||||
OldDestFile:=TStringList.Create;
|
||||
OldDestFile.LoadFromFile(UTF8ToSys(Filename));
|
||||
if OldDestFile.Text=DestFile.Text then Save:=false;
|
||||
OldDestFile.Free;
|
||||
end;
|
||||
if Save then
|
||||
DestFile.SaveToFile(UTF8ToSys(Filename));
|
||||
DestFile.Free;
|
||||
end;
|
||||
|
||||
function FindAllTranslatedPoFiles(const Filename: string): TStringList;
|
||||
var
|
||||
Path: String;
|
||||
Name: String;
|
||||
NameOnly: String;
|
||||
Ext: String;
|
||||
FileInfo: TSearchRec;
|
||||
CurExt: String;
|
||||
begin
|
||||
Result:=TStringList.Create;
|
||||
Path:=ExtractFilePath(Filename);
|
||||
Name:=ExtractFilename(Filename);
|
||||
Ext:=ExtractFileExt(Filename);
|
||||
NameOnly:=LeftStr(Name,length(Name)-length(Ext));
|
||||
if FindFirstUTF8(Path+GetAllFilesMask,faAnyFile,FileInfo)=0 then begin
|
||||
repeat
|
||||
if (FileInfo.Name='.') or (FileInfo.Name='..') or (FileInfo.Name='')
|
||||
or (CompareFilenames(FileInfo.Name,Name)=0) then continue;
|
||||
CurExt:=ExtractFileExt(FileInfo.Name);
|
||||
if (CompareFilenames(CurExt,'.po')<>0)
|
||||
or (CompareFilenames(LeftStr(FileInfo.Name,length(NameOnly)),NameOnly)<>0)
|
||||
then
|
||||
continue;
|
||||
Result.Add(Path+FileInfo.Name);
|
||||
until FindNextUTF8(FileInfo)<>0;
|
||||
end;
|
||||
FindCloseUTF8(FileInfo);
|
||||
end;
|
||||
|
||||
procedure MergePoTrees(SrcTree, DestTree: TAVLTree);
|
||||
var
|
||||
SrcNode, DestNode: TAVLTreeNode;
|
||||
SrcMsgItem, DestMsgItem: PMsgItem;
|
||||
OldNode: TAVLTreeNode;
|
||||
begin
|
||||
// add all message items from SrcTree into DestTree
|
||||
SrcNode:=SrcTree.FindLowest;
|
||||
while SrcNode<>nil do begin
|
||||
SrcMsgItem:=PMsgItem(SrcNode.Data);
|
||||
DestNode:=DestTree.FindKey(SrcMsgItem,@CompareMsgItems);
|
||||
if DestNode<>nil then begin
|
||||
// ID already exists -> update comment
|
||||
DestMsgItem:=PMsgItem(DestNode.Data);
|
||||
DestMsgItem^.Comment:=SrcMsgItem^.Comment;
|
||||
end else begin
|
||||
// new ID -> add new message item to DestTree
|
||||
New(DestMsgItem);
|
||||
DestMsgItem^.Comment:=SrcMsgItem^.Comment;
|
||||
DestMsgItem^.ID:=SrcMsgItem^.ID;
|
||||
DestMsgItem^.Str:=SrcMsgItem^.Str;
|
||||
DestTree.Add(DestMsgItem);
|
||||
end;
|
||||
SrcNode:=SrcTree.FindSuccessor(SrcNode);
|
||||
end;
|
||||
// remove all old messages in DestTree
|
||||
DestNode:=DestTree.FindLowest;
|
||||
while DestNode<>nil do begin
|
||||
DestMsgItem:=PMsgItem(DestNode.Data);
|
||||
OldNode:=DestNode;
|
||||
DestNode:=DestTree.FindSuccessor(DestNode);
|
||||
if (DestMsgItem^.ID<>'')
|
||||
and (SrcTree.FindKey(DestMsgItem,@CompareMsgItems)=nil) then begin
|
||||
// unused message -> delete it
|
||||
writeln('Deleting unused message "',DestMsgItem^.ID,'"');
|
||||
Dispose(DestMsgItem);
|
||||
DestTree.Delete(OldNode);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure UpdatePoFile(const Filename: string);
|
||||
var
|
||||
SrcFile, DestFile: TPoFile;
|
||||
DestFiles: TStringList;
|
||||
i: Integer;
|
||||
begin
|
||||
writeln('Loading ',Filename,' ...');
|
||||
SrcFile:=ReadPoFile(Filename);
|
||||
DestFiles:=FindAllTranslatedPoFiles(Filename);
|
||||
IncPrefix;
|
||||
for i:=0 to DestFiles.Count-1 do begin
|
||||
writeln(Prefix,'Updating ',DestFiles[i]);
|
||||
IncPrefix;
|
||||
DestFile:=ReadPoFile(DestFiles[i]);
|
||||
MergePoTrees(SrcFile.Tree,DestFile.Tree);
|
||||
WritePoFile(DestFile,DestFiles[i]);
|
||||
DestFile.Free;
|
||||
DecPrefix;
|
||||
end;
|
||||
DecPrefix;
|
||||
DestFiles.Free;
|
||||
SrcFile.Free;
|
||||
end;
|
||||
|
||||
procedure UpdateAllPoFiles;
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
for i:=0 to Files.Count-1 do begin
|
||||
UpdatePoFile(Files[i]);
|
||||
end;
|
||||
for i:=0 to Files.Count-1 do
|
||||
UpdatePoFile(ResFiles[i], Files[i]);
|
||||
end;
|
||||
|
||||
begin
|
||||
Prefix:='';
|
||||
Files:=nil;
|
||||
if not ParamsValid then begin
|
||||
|
||||
if not ParamsValid then
|
||||
writeln('Usage: ',ExtractFileName(ParamStrUTF8(0))
|
||||
,' filename1.po [filename2.po ... filenameN.po]');
|
||||
exit;
|
||||
end else begin
|
||||
,' filename1.po [filename2.po ... filenameN.po]')
|
||||
else
|
||||
UpdateAllPoFiles;
|
||||
end;
|
||||
Files.Free;
|
||||
|
||||
if Files<>nil then
|
||||
Files.Free;
|
||||
|
||||
ClearResFiles;
|
||||
end.
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user