Entwickler-Ecke

Delphi Tutorials - Übersetzen von Programmen


Anonymous - Sa 20.09.03 13:37
Titel: Übersetzen von Programmen
Hi.
Dieses Tutorial stellt die Möglichkeit vor, wie man Strings von Komponenten in Programmen ersetzen kann, ohne dies im Quelltext zu tun.

Als erstes müssen die Units "TypInfo" und "IniFiles" eingebunden werden


Delphi-Quelltext
1:
2:
uses
 {...}, IniFiles, TypInfo;


Jetzt folgen ein paar Methoden:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
function GetStringProps(instance: TObject): TStringArray;
var
 j: integer;
 x: TPropList;
begin
 j:= GetPropList(PTypeInfo(TButton.ClassInfo), [tkString, tkWChar, tkLString, tkWString], @x, false);
 setlength(result, j);
 for j := 0 to length(result)-1 do result[j] := x[j].Name;
end;

function IsPropAvailable(instance: TObject; name: string): boolean;
var
 x: tPropList;
 i,j: integer;
begin
 result := false;
 j:= GetPropList(PTypeInfo(instance.ClassInfo), [tkUnknown, tkInteger, tkChar, tkEnumeration, tkFloat,
    tkString, tkSet, tkClass, tkMethod, tkWChar, tkLString, tkWString, 
    tkVariant, tkArray, tkRecord, tkInterface, tkInt64, tkDynArray], @x, false);
 for i := 0 to j-1 do  
  if uppercase(x[i].Name) = uppercase(name) then
  begin  
   result := true;
   exit;
  end
end;

function SetPropertySave(instance: TObject; prop: string; value: variant): boolean;
begin
 result := true;
 if IsPropAvailable(instance, prop) then
  SetPropValue(instance, prop, value)
 else
  result := false; 
end;

procedure SetStringProps(form: TForm; ininame: string; Section: string);
var
 f: TIniFile;
 i,j: integer;
 stringprops: TStringArray;
begin
 f := TIniFile.Create(ininame);
 with form do
 begin
  if f.SectionExists(Section+'.'+name) then
  begin
   stringprops := GetStringProps(form);
   for j := 0 to high(stringprops) do
   begin
    if f.ValueExists(Section+'.'+name,stringprops[j]) then
     SetPropertySave(form, stringprops[j], f.ReadString(Section+'.'+name,stringprops[j],''))
   end;
  end;

  for i := 0 to componentcount-1 do
   if f.SectionExists(Section+'.'+components[i].name) then
   begin
    stringprops := GetStringProps(Components[i]);
    for j := 0 to high(stringprops) do
    begin
     if f.ValueExists(Section+'.'+Components[i].name,stringprops[j]) then
      SetPropertySave(Components[i], stringprops[j], f.ReadString(Section+'.'+Components[i].name,stringprops[j],''))
    end;
   end;
 end;
 f.Free;
end;


Die Procedure SetStringProps erwartet ein Formular, den Pfad zu einer Ini-Datei, in der die Texte gespeichert werden und den Namen einer Section.
Aufgerufen werden kann sie etwa so:


Delphi-Quelltext
1:
2:
3:
 SetStringProps(self, 'C:\test.ini''Englisch');
// oder
 SetStringProps(self, 'C:\test.ini''Deutsch');


Der Aufbau der Inidatei ist folgendermaßen:


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
[Deutsch.Form1]
Caption=Dies ist ein Test.
[Deutsch.Button1]
Caption=Deutsch.
[Deutsch.Button2]
Caption=Englisch.

[Englisch.Form1]
Caption=This is a Test.
[Englisch.Button1]
Caption=German.
[Englisch.Button2]
Caption=English.


Andere Eigenschaften wie z.B. Hint können auch gesetzt werden. (Es müssen allerdings Strings sein)


lkz633 - Do 17.06.04 23:08

Hallo,

dieser Ansatz gefällt mir sehr gut, haette aber dazu noch ein Frage.

Wie übersetzt du Strings in z.B showmessage etc. ?

Danke und Gruss
lkz633


Udontknow - Do 17.06.04 23:34

Na, da wird man eben "von Hand" übersetzen müssen. Ich mach das meist so, daß ich sämtliche Texte in einer anderen Unit als Variablen definiere, die ich dann für jede Sprache dementsprechend bestücke. Anstelle von "ShowMessage('Division durch Null!')" also "ShowMessage(Str_ErrorDivZero)". Da wird dann auch häufig die Funktion Format sehr sinnvoll.

@Obbschtkuche:
Was ist, wenn ich zwei Buttons mit dem gleichen Namen auf unterschiedlichen Formularen habe? Müsste der Formularname nicht noch bei den einzelnen Komponenten als Identifikation einfliessen?

Cu,
Udontknow


Anonymous - So 20.06.04 19:27

Hmm, ist schon was länger her dass ich das gemacht habe, aber man könnte das ja über form.Name noch einbauen.