Autor |
Beitrag |
Silent Bob
Hält's aus hier
Beiträge: 9
|
Verfasst: Di 29.10.02 09:24
Hallo
für meine Diplomarbeit sollte die Software, die ich zu entwickeln habe unter anderem mehrsprachig sein. Gibt es in Delphi dafür eine einfach zu handhabende Unterstützung und wenn ja wie funktioniert sie? Wenn es keine gibt, was gibt es sonst für Lösungsansätze?
Besten Dank für die Hilfe und einen schönen Tag
_________________ "Ich dachte alles wird gut, aber das ist lange her"
|
|
FriFra
      
Beiträge: 557
Win XP Prof, Win XP Home,Win Server 2003,Win 98SE,Win 2000,Win NT4,Win 3.11,Suse Linux 7.3 Prof,Suse Linux 8.0 Prof
D2k5 Prof, D7 Prof, D5 Standard, D3 Prof, K3 Prof
|
Verfasst: Di 29.10.02 10:34
Ich habe mal irgendwo diese Unit gefunden:
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: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180:
| unit Lang;
interface
uses windows,controls,sysutils;
Function INLanguage(English,German:String):String;
implementation
{call inLanguage like this to get the German text else return english if you use different coutntry codes you can do more}
{
# FGetLanguageSettings
# Author: Walter Verhoeven # Date: 14.Sep.2000 # Coming From: InLanguage # Next Event: NONE # Parameters: NONE # Objective: See the users regional settings and return Country #number code # Change: # DD-MMM-YYYYY ¦Programmer # 1) #
}
Function FGetLanguageSettings:Integer; Var OutputBuffer: Pchar; SelectedLCID: LCID; //DWORD constand in Windows.pas begin OutputBuffer:= StrAlloc(4); //alocate memory for the PChar Try Try SelectedLCID:= GetUserDefaultLCID; GetLocaleInfo(SelectedLCID,LOCALE_ICOUNTRY,OutputBuffer,3); Result:= StrToInt(OutputBuffer); Except Result:= 49; //german Abort;
End; Finally StrDispose(OutputBuffer); //alway's free the memory alocated End; end; {
INLanguage
# # Author: Walter Verhoeven # Date: .Jun.2000 # Coming From: # Next Event: FGetLanguageSettings # Parameters: Eglish and german text # Objective: provide a method to return # english or german results based on the # users window prefered language setting. # Change: # DD-MMM-YYYYY ¦Programmer # 1) #
} Function INLanguage(English,German:String):String; begin Case FGetLanguageSettings of 49: Result:=German ; //Return the german string 43: Result:=German ; // if the pC has a german preferance 41: Result:=German ; 352: Result:=German ; Else Result:= English; //if not german then english End; end;
end. |
Aufruf:
Quelltext 1:
| Label1.Caption:=InLanguage('MyLabel','Mein Label); |
Ich habe mir das ganze noch um die optionale verwendung einer ini-datei erweitert, damit ich andere Sprachen einfach über eine Textdatei einbinden kann, aber das ist etwas viel Code...
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Di 29.10.02 11:20
Man könnte auch über Zeichenfolgentabellen gehen, die man eine Ressourcen-Datei packt. Da legt man für jede Sprache eine an. Die gleichen Zeichenfolgen in den verschiedenen Sprachen haben dann jeweils die gleiche ID. Natürtlich muß man dann alles von Hand laden, jedes Label, jedes Item einer Listbox usw. Muß man bei dem anderen Vorschlag auch, nur nimmt dir hier das System die Entscheidung ab welche Sprache genommen wird.
Ich habe mal eine Screenshot der Ressourcen-Datei meines FileSplitters im geöffneten VC gemacht. (Der ist schon auf englischen, deutschen, französischen und chinesischen Systemen gelaufen. Auf den deutschen Systemen in deutsch und auf den restlichen in englisch eben.) Da siehst du was ich meine. Legst du noch eine neutrale Sprache an, wird die immer gewählt, wenn nichts anderes paßt.
Laden der Strings geht so:
Quelltext 1: 2: 3: 4: 5: 6: 7:
| function LoadStr(ID: DWORD): String; var buffer: array[0..255] of Char; begin LoadString(hInstance, ID, buffer, 255); result := String(buffer); end; |
Und so kannst du zur Laufzeit die Sprache umschalten:
Quelltext 1: 2:
| SetThreadLocale(DWORD(Word(SORT_DEFAULT) shl 16) or DWORD(Word(SUBLANG_ENGLISH_US) shl 10) or DWORD(Word(LANG_ENGLISH))); |
Meiner Meinung nach die einfachste Möglichkeit und wenn du dann noch das VC zur Hand hast ein Kinderspiel. Wenn du dir die Ressourcen-Dateien selber schreiebn mußt ist das auch kein Beinbruch, mußt nur in Erfahrung bringen, wie die aussehen müssen.
|
|
neojones
      
Beiträge: 1206
Erhaltene Danke: 1
|
Verfasst: Di 29.10.02 11:48
In der INI-Datei "LanINI" stehen die Einträge so drin:
[Deutsch]
1cap=OK
1hint=Drück das für okay
2cap=Abbrechen
2hint=Drück das wenn Du ein Weichei bist
[English]
1cap=OK
1hint=Click this for okay
2cap=Cancel
2hint=Click this if you are a looser
Und der folgende Code geht alle Componenten des Programmes durch und ändert die Beschriftung und den Hint. Vorteil: Die Sprache lässt sich auch zur Laufzeit umstellen.
Zum praktischen Einsatz: Das Tool myAdmin (coded by meinereiner) benutzt diese Routine zimelich erfolgreich.
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: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88:
| procedure TFMain.ChangeLan(const lan: String); var i, j: Integer; c: TObject; begin LanINI := TINIFile.Create(ProgVerz + '\lan.ini');
WITH Application DO begin FOR i := 0 to ComponentCount - 1 DO BEGIN FOR j := 0 TO Components[i].ComponentCount - 1 DO BEGIN c := Components[i].Components[j]; If (c is TLabel) then begin If (c AS TLabel).Tag <> 0 then begin (c AS TLabel).Caption := LanINI.ReadString(lan, IntToStr((c AS TLabel).Tag)+'cap', ''); end; end;
If (c is TPanel) then begin If (c AS TPanel).Tag <> 0 then begin (c AS TPanel).Caption := LanINI.ReadString(lan, IntToStr((c AS TPanel).Tag)+'cap', ''); end; end;
If (c is TXPButton) then begin If (c AS TXPButton).Tag <> 0 then begin (c AS TXPButton).Caption := LanINI.ReadString(lan, IntToStr((c AS TXPButton).Tag)+'cap', ''); (c AS TXPButton).Hint := LanINI.ReadString(lan, IntToStr((c AS TXPButton).Tag)+'hint', ''); end; end;
If (c is TCheckBox) then begin If (c AS TCheckBox).Tag <> 0 then begin (c AS TCheckBox).Caption := LanINI.ReadString(lan, IntToStr((c AS TCheckBox).Tag)+'cap', ''); end; end;
If (c is TMenuItem) then begin If (c AS TMenuItem).Tag <> 0 then begin (c AS TMenuItem).Caption := LanINI.ReadString(lan, IntToStr((c AS TMenuItem).Tag)+'cap', ''); end; end;
If (c is TGroupBox) then begin If (c AS TGroupBox).Tag <> 0 then begin (c AS TGroupBox).Caption := LanINI.ReadString(lan, IntToStr((c AS TGroupBox).Tag)+'cap', ''); end; end;
If (c is TImage) then begin If (c AS TImage).Tag <> 0 then begin (c AS TImage).Hint := LanINI.ReadString(lan, IntToStr((c AS TImage).Tag)+'hint', ''); end; end;
If (c is TRadioGroup) then begin If (c AS TRadioGroup).Tag <> 0 then begin (c AS TRadioGroup).Caption := LanINI.ReadString(lan, IntToStr((c AS TRadioGroup).Tag)+'cap', ''); end; end;
If (c is TTabSheet) then begin If (c AS TTabSheet).Tag <> 0 then begin (c AS TTAbSheet).Caption := LanINI.ReadString(lan, IntToStr((c AS TTabSheet).Tag) + 'cap', ''); end; end;
If (c is TSpeedButton) then begin If (c AS TSpeedButton).Tag <> 0 then begin (c AS TSpeedButton).Caption := LanINI.ReadString(lan, IntToStr((c AS TSpeedButton).Tag)+'cap', ''); (c AS TSpeedButton).Hint := LanINI.ReadString(lan, IntToStr((c AS TSpeedButton).Tag)+'hint', ''); end; end;
If (c is TButton) then begin If (c AS TButton).Tag <> 0 then begin (c AS TButton).Caption := LanINI.ReadString(lan, IntToStr((c AS TButton).Tag)+'cap', ''); (c AS TButton).Hint := LanINI.ReadString(lan, IntToStr((c AS TButton).Tag)+'hint', ''); end; end; If (c is TBitBtn) then begin If (c AS TBitBtn).Tag <> 0 then begin (c AS TBitBtn).Caption := LanINI.ReadString(lan, IntToStr((c AS TBitBtn).Tag)+'cap', ''); (c AS TBitBtn).Hint := LanINI.ReadString(lan, IntToStr((c AS TBitBtn).Tag)+'hint', ''); end; end; END; END; end; end; |
Viele Grüße,
Matthias
_________________ Ha! Es compiliert! Wir können ausliefern!
|
|
Matthias
      
Beiträge: 121
|
Verfasst: Di 29.10.02 17:07
Hy,
auch ich habe mir mal gedanken zu dem Thema gemacht und meine eigene Lösung erstellt.
1. wollt ich, dass der Kunde dass Programm auch selbst übersetzen kann
2. Ich habe keine lust alle Texte von Hand zu initialisieren
3. Bei Programmänderungen sollten die Änderungen einfach einzupflegen sein
4. Die default Sprachdatei soll möglichst automatisch erstellt werden
5. Beliebig viele Srachen sollten möglich sein
6. Sprachumschaltun während das Programm läuft
Resourcen zu verwenden ist parktisch und üblich jedoch bedeutet es für 1 und 2 einen erhöhten Aufwand.
Deshalb habe ich mich auch für Ini-Dateien entschieden. Bei mir gibt es für jede Sprache eine und eine weitere, über die ich das Sprachmenü erstelle und somit mit beliebig vielen Sprachen arbeiten kann.
Als Index für den Text verwende ich die Eigenschaft Tag, die jede Kompo hat. Ist diese ungleich 0 muß der Inhalt Übersetzt werden. Das Übersetzen übernimmt eine allgemeine Routine, die im OnShow Ereignis eines Formulars aufgerufen wird. Der Rest läuft automatisch, ähnlich wie in dem Beispiel meine Namens Vetters.
Die default Datei wird erstellt, in dem über bedingte Compilierung die Sprachdatei geschrieben anstatt gelesen wird.
ciao
Matthias
|
|
Silent Bob 
Hält's aus hier
Beiträge: 9
|
Verfasst: Di 29.10.02 17:24
Besten Dank an alle .... ich denk ich werde es ebenfalls mit der Ini-File Variante lösen, da sie mir einfach und schnell realsierbar scheint .... und die Zeit drängt eben ....
Habt nen schönen Abend
_________________ "Ich dachte alles wird gut, aber das ist lange her"
|
|
Aya
      
Beiträge: 1964
Erhaltene Danke: 15
MacOSX 10.6.7
Xcode / C++
|
Verfasst: Mi 30.10.02 16:45
Hi,
also ich hab jetzt einfach mal nicht gelesen was meine Vorgänger alles geschrieben haben... aber, bei dem satz "Für meine Diplomarbeit..." *gg* Sollte man wenn man das Diplom darin macht nicht sowas schon alleine hinbekommen?? *duckt sich hastig*
Aber nochmal die lösung wie ich sie immer verwende.. (und nein, ich hab kein Diplom, hab auch niemals Informatik oder dergleichen studiert, bzw irgendwo auf ner Schule oder ähnlichem gelernt *g*)
Nehmen wir an du hast 3 Sprachen, Deutsch, Englisch, Holländisch.
Machst du dafür einfach 3 INI Dateien, "Deutsch.ini", "Englisch.ini", "Holland.ini"... (Holland.ini daher weil Holländisch so lang ist und nen ä drin hat...  )
Jetzt unterteilst du deine INI datei in mehrere sektionen.. z.B. "MainMenu", "Frame1" etc.. jenachdem wie dein Programm aufgebaut ist, und darin machst du einfach für jede Caption etc einen eintrag den du dann in einer funktion LoadLanguage(Language: String); lädst...
dann machst du dir irgendwo im MainMenü oder sonstwo einen eintrag "Sprache" mit den 3 unterspalten, und jedesmal wenn man eine auswählt wird die funktion LoadLanguage mit der entsprechenden sprache geladen...
Wenn du es dann ganz perfekt machen willst machst du beim ini.ReadString() am ende einen Default wert hin, somit hast du sogar eine Standartsprache für den fall das man die INI Dateien löscht...
und wenn es noch perfekter sein soll.. verschlüsselst du die INI Datei (denn es gibt viele Newbies die gern einfach dann die Texte es Prog's ändern und ihre namen hinkritzeln etc.)
und wenn es noch viel viel perfekter sein soll *gg* bzw das ganze mit sehr wenig code gelöst sein soll... nenn die einträge in der INI so wie das z.B. Laben auf deiner Form heißt...
//INI
[Main]
Label1=Hallo
//INI Ende
So, und das ganze rufst du ab indem du dir zuerst in einer StringList die ganzen namen der einträge in [Main] lädst... die arbeitest du von oben nach unten in einer forschleife durch und mit jedemeintrag dann
Quelltext 1:
| TLabel(FindComponent(StringList.Strings[i])).Caption:=ini.ReadString('Main',StringList.Strings[i],''); |
ok, es gibt keinen Default wert mehr, aber du hast das ganze sprachproblem mit 5 Zeilen code gelöst
Au'revoir,
Aya
PS: Bekomm ich auch nen Diplom? 
|
|
Silent Bob 
Hält's aus hier
Beiträge: 9
|
Verfasst: Mi 30.10.02 19:19
Tja ... was soll ich dazu sagen ..... die Mehrsprachigkeit der Software ist eine kleine Wunschanforderung am Rande. Dies über irgendwelche einzulesende Text-Files zu lösen leuchtet ein. Doch ich hab's eben noch nie zuvor gemacht und dachte deswegen mal nachzufragen schadet nichts. Denn dieses Problem haben vor mir schon zig-tausende gelöst und sich darüber den Kopf zerbrochen. Wollte einfach mal schauen welch' elegante Lösungen sich der eine oder andere wache Geist schon ausgedacht hat.
In diesem Sinne
Silent Bob
_________________ "Ich dachte alles wird gut, aber das ist lange her"
|
|
|