1 {
2 *****************************************************************************
3 *                                                                           *
4 *  This file is part of the ZCAD                                            *
5 *                                                                           *
6 *  See the file COPYING.modifiedLGPL.txt, included in this distribution,    *
7 *  for details about the copyright.                                         *
8 *                                                                           *
9 *  This program is distributed in the hope that it will be useful,          *
10 *  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
11 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                     *
12 *                                                                           *
13 *****************************************************************************
14 }
15 {
16 @author(Andrey Zubarev <zamtmn@yandex.ru>)
17 }
18 
19 unit uzctranslations;
20 {$INCLUDE def.inc}
21 
22 interface
23 uses uzbpaths,LCLVersion,uzbstrproc{$IFNDEF DELPHI},LazUTF8,gettext,translations,
24      fileutil,LResources{$ENDIF},uzcsysinfo,sysutils,uzclog,forms,Classes, typinfo,
25      uzcsysparams,LazLogger;
26 
27 const
28   ZCADTranslatedPOFileName='zcad.%s.po';
29   ZCADPOFileName='zcad.po';
30   ZCADRTTranslatedPOFileName='rtzcad.%s.po';
31   ZCADRTPOFileName='rtzcad.po';
32   ZCADRTBackupPOFileName='rtzcad.po.backup';
33 type
34     TmyPOFile = class(TPOFile)
FindByIdentifiernull35                      function FindByIdentifier(const Identifier: String):TPOFileItem;
36                      procedure SaveToFile(const AFilename: string);
37                      {$IF LCL_FULLVERSION<1030000}
38                      procedure Add(const Identifier, OriginalValue, TranslatedValue, Comments,
39                                          Context, Flags, PreviousID: string);
40                      {$ENDIF}
41                      {$IF LCL_FULLVERSION>=1030000}
42                      procedure Add(const Identifier, OriginalValue, TranslatedValue,
43                                    Comments, Context, Flags, PreviousID: string; SetFuzzy: boolean = false; LineNr: Integer = -1);
44                      {$ENDIF}
Translatenull45                      function Translate(const Identifier, OriginalValue: String): String;
exportcompileritemsnull46                      function exportcompileritems(sourcepo:TPOFile):integer;
47                 end;
48     TPoTranslator=class(TAbstractTranslator)
49     public
50      procedure TranslateStringProperty(Sender:TObject;
51        const Instance: TPersistent; PropInfo: PPropInfo; var Content:string);override;
52     end;
53 
InterfaceTranslatenull54 function InterfaceTranslate(const Identifier, OriginalValue: String): String;
55 procedure DisableTranslate;
56 procedure EnableTranslate;
57 var
58    PODirectory, Lang, FallbackLang: AnsiString;
59    po: TmyPOFile;
60    actualypo: TmyPOFile;
61    _UpdatePO:integer=0;
62    _NotEnlishWord:integer=0;
63    _DebugWord:integer=0;
64    DisableTranslateCount:integer;
65 const
66   identpref='zcadexternal.';
67 implementation
68 var
69    TranslateLogModuleId:TLogModuleDeskIndex;
70 procedure DisableTranslate;
71 begin
72      inc(DisableTranslateCount);
73 end;
74 procedure EnableTranslate;
75 begin
76      dec(DisableTranslateCount);
77 end;
78 procedure TPoTranslator.TranslateStringProperty(Sender: TObject;
79   const Instance: TPersistent; PropInfo: PPropInfo; var Content: string);
80 var
81   s: String;
82 begin
83   if not Assigned(po) then exit;
84   if not Assigned(PropInfo) then exit;
85 {Нужно ли нам это?}
86   if Instance is TComponent then
87    if csDesigning in (Instance as TComponent).ComponentState then exit;
88 {:)}
89   if (AnsiUpperCase(PropInfo^.PropType^.Name)<>'TTRANSLATESTRING') then exit;
90   s:=po.Translate(Content, Content);
91   if s<>'' then Content:=s;
92 end;
93 
FindByIdentifiernull94 function TmyPOFile.FindByIdentifier(const Identifier: String):TPOFileItem;
95 begin
96   result:=FindPoItem(Identifier);
97   //uncoment for lazarus < r57491
98   //result:=TPOFileItem({FIdentifierToItem}FIdentLowVarToItem.Data[Identifier]);
99 end;
100 procedure TmyPOFile.SaveToFile(const AFilename: string);
101 begin
102      inherited//self.f
103 end;
exportcompileritemsnull104 function TmyPOFile.exportcompileritems(sourcepo:TPOFile):integer;
105 var
106    j:integer;
107    ident:string;
108    Item,NewItem: TPOFileItem;
109 begin
110       for j:=0 to Fitems.Count-1 do
111            begin
112                 item:=TPOFileItem(FItems[j]);
113                  ident:=item.IdentifierLow;
114                  if (pos('~',ident)<=0)
115                  and(pos('.',ident)>0) then
116                  begin
117                       NewItem:=nil;
118                       sourcepo.FillItem(NewItem,ident, item.Original, item.Translation, item.Comments,
119                                     item.Context, item.Flags,'');
120                       //uncoment if Lazarus<r57425
121                       //sourcepo.Add(ident, item.Original, item.Translation, item.Comments,
122                       //              item.Context, item.Flags,'');
123                  end;
124            end;
125       result:=items.Count-sourcepo.items.Count;
126 end;
TmyPOFile.Translatenull127 function TmyPOFile.Translate(const Identifier, OriginalValue: String): String;
128 var
129   Item: TPOFileItem;
130 begin
131   Item:=FindPoItem(Identifier);
132   //uncoment for lazarus < r57491
133   //Item:=TPOFileItem({FIdentifierToItem}FIdentLowVarToItem.Data[Identifier]);
134   if Item=nil then
135     Item:=TPOFileItem(FOriginalToItem.Data[OriginalValue]);
136   if Item<>nil then begin
137     Result:=Item.Translation;
138     if Result='' then Result:=OriginalValue;
139   end else
140     Result:=OriginalValue;
141 end;
142 procedure TmyPOFile.Add(const Identifier, OriginalValue, TranslatedValue,
143   Comments, Context, Flags, PreviousID: string; SetFuzzy: boolean = false; LineNr: Integer = -1);
144 var
145    t:boolean;
146    NewItem:TPOFileItem;
147 begin
148      t:=self.FAllEntries;
149      self.FAllEntries:=true;
150      NewItem:=nil;
151      FillItem(NewItem,Identifier, OriginalValue, TranslatedValue, Comments,Context, Flags, PreviousID);
152      //uncoment if Lazarus<r57425
153      //inherited  Add(Identifier, OriginalValue, TranslatedValue, Comments,Context, Flags, PreviousID);
154      self.FAllEntries:=t;
155 end;
156 
157 procedure createpo;
158 var
159    AFilename:string;
160 begin
161      if not sysparam.saved.updatepo then
162      begin
163            if Lang<>'' then
164                            begin
165                                 AFilename:=Format(PODirectory + ZCADRTTranslatedPOFileName,[Lang]);
166                                 if FileExists{UTF8}(AFilename) then
167                                                                  begin
168                                                                       po:=TmyPOFile.Create(AFilename);
169                                                                  end;
170                            end;
171            if (FallbackLang<>'')and(not assigned(po)) then
172                            begin
173                                 AFilename:=Format(PODirectory + ZCADRTTranslatedPOFileName,[FallbackLang]);
174                                 if FileExists{UTF8}(AFilename) then
175                                                                  begin
176                                                                       po:=TmyPOFile.Create(AFilename);
177                                                                  end;
178                            end;
179            if (not assigned(po)) then
180                                      begin
181                                           po:=TmyPOFile.Create;
182                                      end;
183 
184      end
185      else
186          begin
187               AFilename:=(PODirectory + ZCADRTPOFileName);
188               if FileExists{UTF8}(AFilename) then
189                                                begin
190                                                     po:=TmyPOFile.Create(AFilename,true);
191                                                     actualypo:=TmyPOFile.Create;
192                                                end
193                                            else
194                                                begin
195                                                     programlog.LogOutStr('Founf command line swith "UpdatePO". File "zcad.po" not found. STOP!',0,LM_Fatal);
196                                                     halt(0);
197                                                end;
198          end;
199 end;
InterfaceTranslatenull200 function InterfaceTranslate( const Identifier, OriginalValue: String): String;
201 const nontranslatedword='InterfaceTranslate: found not translated word: identifier:"%s" originalValue:"%s"';
202 var
203   Item: TPOFileItem;
204 begin
205     if DisableTranslateCount>0 then
206                               begin
207                                    result:=OriginalValue;
208                                    exit;
209                               end;
210     result:=po.Translate(Identifier, OriginalValue);
211     programlog.LogOutFormatStr('InterfaceTranslate: identifier:"%s" originalValue:"%s" translate to "%s"',[Identifier,OriginalValue,result],0,LM_Debug,TranslateLogModuleId);
212 
213     if sysparam.saved.updatepo then
214      begin
215           Item:=po.FindPoItem(Identifier);
216           //uncoment for lazarus < r57491
217           //Item:=TPOFileItem(po.{FIdentifierToItem}FIdentLowVarToItem{FOriginalToItem}.Data[UTF8LowerCase(Identifier)]);
218           if not assigned(item) then
219           begin
220                if (pos('**',OriginalValue)>0)or(pos('??',OriginalValue)>0)or(pos('__',OriginalValue)=1)then
221                begin
222                     inc(_DebugWord);
223                     programlog.LogOutStr(format('InterfaceTranslate: found debug word: identifier:"%s" originalValue:"%s"',[Identifier,OriginalValue]),0,LM_Warning,TranslateLogModuleId);
224                end
225                else
226                begin
227                if (utf8length(Identifier)=length(Identifier))and
228                   (utf8length(OriginalValue)=length(OriginalValue)) then
229                begin
230                     if pos(identpref,Identifier)<>1 then
231                         begin
232                              programlog.LogOutStr(format(nontranslatedword,[Identifier,OriginalValue]),0,LM_Warning,TranslateLogModuleId);
233                              po.Add(identpref+Identifier,OriginalValue, {TranslatedValue}'', {Comments}'',{Context}'', {Flags}'', {PreviousID}'');
234                              actualypo.Add(identpref+Identifier,OriginalValue, {TranslatedValue}'', {Comments}'',{Context}'', {Flags}'', {PreviousID}'');
235                         end
236                     else
237                         begin
238                              programlog.LogOutStr(format(nontranslatedword,[Identifier,OriginalValue]),0,LM_Warning,TranslateLogModuleId);
239                              po.Add(Identifier,OriginalValue, {TranslatedValue}'', {Comments}'',{Context}'', {Flags}'', {PreviousID}'');
240                              actualypo.Add(Identifier,OriginalValue, {TranslatedValue}'', {Comments}'',{Context}'', {Flags}'', {PreviousID}'');
241                         end;
242                     inc(_UpdatePO);
243                     //po.SaveToFile(PODirectory + 'zcad.po');
244                end
245                   else
246                       begin
247                       inc(_NotEnlishWord);
248                       programlog.LogOutStr(format('InterfaceTranslate: found non ASCII word: identifier:"%s" originalValue:"%s"',[Identifier,OriginalValue]),0,LM_Warning,TranslateLogModuleId);
249                       //log.LogOut(Identifier+'--------------'+OriginalValue)
250                       end;
251 
252                end;
253           end
254           else
255           begin
256                if item.Original<>OriginalValue then
257                                                    begin
258                                                    item.ModifyFlag('fuzzy',true);
259                                                    item.Original:=OriginalValue;
260                                                    end;
261                actualypo.Add({identpref+}item.IdentifierLow, item.Original, item.Translation, item.Comments,
262                               item.Context, item.Flags,'');
263           end;
264 
265      end;
266 end;
267 
268 procedure initialize;
269     begin
270       DisableTranslateCount:=0;
271       PODirectory := ProgramPath+'languages/';
272       GetLanguageIDs(Lang, FallbackLang); // определено в модуле gettext
273       createpo;
274       LRSTranslator:=TPoTranslator.Create;
275       if not sysparam.saved.updatepo then
276                                        begin
277                                            TranslateResourceStrings(PODirectory + ZCADTranslatedPOFileName, Lang, FallbackLang);
278                                            TranslateUnitResourceStrings('anchordockstr', PODirectory + 'anchordockstr.%s.po', Lang, FallbackLang);
279                                            TranslateUnitResourceStrings('lclstrconsts', PODirectory + 'lclstrconsts.%S.po', Lang, FallbackLang);
280                                        end;
281     end;
282 
283 initialization
284   TranslateLogModuleId:=programlog.registermodule('TRANSLATOR');
285   initialize;
286 finalization
287   debugln('{I}[UnitsFinalization] Unit "',{$INCLUDE %FILE%},'" finalization');
288   if assigned(actualypo) then freeandnil(actualypo);
289   if assigned(po) then freeandnil(po);
290   if assigned(LRSTranslator) then freeandnil(LRSTranslator);
291 end.
292