Mehrsprachigkeit mit XML

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
Kiffi
Beiträge: 10714
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Mehrsprachigkeit mit XML

Beitrag von Kiffi »

Hallö,

mit dem nachstehenden Code möchte ich demonstrieren, wie einfach es
ist, mittels XML Mehrsprachigkeit in einer Applikation zu realisieren.

Hinweis: Der Code benötigt die MSXML3-Lib aus den PBOSL.

Code: Alles auswählen

Enumeration
  #frmMain
  #lblLanguage
  #cboLanguage
  #lblName
  #txtName
  #lblSurname
  #txtSurname
  #cmdOK
  #cmdCancel
EndEnumeration

Global oDocLanguages ; Global XML-Object to hold all language-values

Procedure.s GetText(ID$, Language$)
  
  oNode = MSXML3_SelectSingleNode(oDocLanguages, "items/item[@id='" + ID$ + "']/" + Language$)
  If oNode
    ReturnValue$=MSXML3_GetText(oNode)
    MSXML3_ReleaseObject(oNode)
  EndIf
  ProcedureReturn ReturnValue$
  
EndProcedure

Procedure ReloadCaptions(Language$)
  SetWindowTitle(#frmMain,     GetText("frmMain",     Language$))
  SetGadgetText (#lblLanguage, GetText("lblLanguage", Language$))
  SetGadgetText (#lblName,     GetText("lblName",     Language$))
  SetGadgetText (#lblSurname,  GetText("lblSurname",  Language$))
  SetGadgetText (#cmdOK,       GetText("cmdOK",       Language$))
  SetGadgetText (#cmdCancel,   GetText("cmdCancel",   Language$))
EndProcedure
  
oDocLanguages = MSXML3_CreateDomDocument()

MSXML3_Load(oDocLanguages, "languages.xml")

If OpenWindow(#frmMain, 0, 0, 320, 140, #PB_Window_ScreenCentered | #PB_Window_SystemMenu, "")
  
  If CreateGadgetList(WindowID(#frmMain))
    
    TextGadget  (#lblLanguage, 10, 15,  60, 20, "")
    
    ComboBoxGadget(#cboLanguage, 70, 10, 240, 200)
    AddGadgetItem (#cboLanguage, -1, "en")
    AddGadgetItem (#cboLanguage, -1, "de")
    SetGadgetState(#cboLanguage, 0)
    
    TextGadget  (#lblName,     10,  45,  60, 20, "")
    StringGadget(#txtName,     70,  40, 240, 20, "")
    TextGadget  (#lblSurname,  10,  75,  60, 20, "")
    StringGadget(#txtSurname,  70,  70, 240, 20, "")
    ButtonGadget(#cmdOK,      145, 105,  80, 25, "")
    ButtonGadget(#cmdCancel,  230, 105,  80, 25, "")
    
    ReloadCaptions("en")
    
    Repeat
      
      WWE = WaitWindowEvent()
      EGI = EventGadgetID()
      
      Select WWE
        
        Case #PB_Event_Gadget
          
          Select EGI
            
            Case #cboLanguage
              
              Select GetGadgetState(#cboLanguage)
                Case 0 : ReloadCaptions("en")
                Case 1 : ReloadCaptions("de")
              EndSelect
              
            Case #cmdOK     : Quit = 1
            Case #cmdCancel : Quit = 1
              
          EndSelect
          
        Case #PB_Event_CloseWindow : Quit = 1
          
      EndSelect
      
    Until Quit = 1
    
  EndIf
  
EndIf
hier noch die entsprechende XML-Datei. Bitte unter '[c]languages.xml[/c]' speichern.

Code: Alles auswählen

<?xml version="1.0" encoding="ISO-8859-1"?> 
<items>
	<item id="frmMain">
		<de>Beispiel: Mehrsprachigkeit</de>
		<en>Demo: Multilingualism</en>
	</item>
	<item id="lblLanguage">
		<de>&Sprache:</de>
		<en>&Language:</en>
	</item>
	<item id="lblName">
		<de>&Vorname:</de>
		<en>&Name:</en>
	</item>
	<item id="lblSurname">
		<de>&Nachname:</de>
		<en>&Surname:</en>
	</item>
	<item id="cmdOK">
		<de>OK</de>
		<en>OK</en>
	</item>
	<item id="cmdCancel">
		<de>Abbrechen</de>
		<en>Cancel</en>
	</item>
</items>
Have fun ... Kiffi
Benutzeravatar
benny
Beiträge: 383
Registriert: 29.08.2004 09:18
Wohnort: Am Ende des www's
Kontaktdaten:

Beitrag von benny »

N1, Kiffi :allright:

Sowas sollte man gleich in 'nen Visual Designer reinbauen!
So long,
benny!
.
nur t0te f1sche schw1mmen m1t dem str0m - 00100 !
Benutzeravatar
Kiffi
Beiträge: 10714
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Beitrag von Kiffi »

@Benny: Danke für die Blumen! :-)

> Sowas sollte man gleich in 'nen Visual Designer reinbauen!

könnte man machen, wenn man einen nativen XML-Parser hätte (unter
Linux z.B. gibt es keinen MSXML3-Parser). Sowas ist zwar schon in Arbeit;
bis der aber zuverlässig arbeitet, dauert das noch etwas.

Hier noch mal ein kleines Updates des Codes. Nun werden auch die
verfügbaren Sprachen aus dem XML gelesen. Das ermöglicht eine
Erweiterung um eine oder mehrere Sprachen, ohne den Code der
Applikation ändern zu müssen.

Code: Alles auswählen

Enumeration
  #frmMain
  #lblLanguage
  #cboLanguage
  #lblName
  #txtName
  #lblSurname
  #txtSurname
  #cmdOK
  #cmdCancel
EndEnumeration

Global oDocLanguages ; Global XML-Object to hold all language-values

Global AllLanguages.s   ; String to hold all available languages seperated by pipes ('de|en|fr|...')

Global SelectedLanguage.l

Procedure GetLanguages()
  
  AllLanguages     = ""
  SelectedLanguage = 0   ; First entry is the default language
  
  oNodeList = MSXML3_SelectNodes(oDocLanguages, "items/available_languages/ln")
  If oNodeList
    For lCounter = 0 To MSXML3_NodeListGetLength(oNodeList)
      oNode = MSXML3_NodeListGetItem(oNodeList, lCounter)
      If oNode
        AllLanguages + MSXML3_GetText(oNode) + "|"
        MSXML3_ReleaseObject(oNode)
      EndIf
    Next ; lCounter
    MSXML3_ReleaseObject(oNodeList)
  EndIf
  
EndProcedure

Procedure.s GetText(ID$)
  
  oNode = MSXML3_SelectSingleNode(oDocLanguages, "items/item[@id='" + ID$ + "']/" + StringField(AllLanguages, SelectedLanguage, "|"))
  If oNode
    ReturnValue$=MSXML3_GetText(oNode)
    MSXML3_ReleaseObject(oNode)
  EndIf
  ProcedureReturn ReturnValue$
  
EndProcedure

Procedure ReloadCaptions()
  
  ; Reload Language-Combobox
  oldLanguage = SelectedLanguage              ; remember actual language
  oldIndex = GetGadgetState(#cboLanguage)     ; remember selected comboboxindex
  
  ClearGadgetItemList(#cboLanguage)
  For SelectedLanguage = 1 To CountString(AllLanguages, "|")
    AddGadgetItem (#cboLanguage, -1, GetText(StringField(AllLanguages, SelectedLanguage, "|")))
  Next
  
  SetGadgetState(#cboLanguage, oldIndex)
  SelectedLanguage = oldLanguage
  
  SetWindowTitle(#frmMain,     GetText("frmMain"))
  
  SetGadgetText (#lblLanguage, GetText("lblLanguage"))
  SetGadgetText (#lblName,     GetText("lblName"))
  SetGadgetText (#lblSurname,  GetText("lblSurname"))
  SetGadgetText (#cmdOK,       GetText("cmdOK"))
  SetGadgetText (#cmdCancel,   GetText("cmdCancel"))
  
EndProcedure
  
oDocLanguages = MSXML3_CreateDomDocument()

MSXML3_Load(oDocLanguages, "languages.xml")

GetLanguages()

If OpenWindow(#frmMain, 0, 0, 320, 140, #PB_Window_ScreenCentered | #PB_Window_SystemMenu, "")
  
  If CreateGadgetList(WindowID(#frmMain))
    
    TextGadget    (#lblLanguage, 10, 15,  60, 20, "")
    
    ComboBoxGadget(#cboLanguage, 70, 10, 240, 200)
    AddGadgetItem (#cboLanguage,-1,"") ; Dummy-Entry
    SetGadgetState(#cboLanguage, 0)
    
    TextGadget  (#lblName,     10,  45,  60, 20, "")
    StringGadget(#txtName,     70,  40, 240, 20, "Peter")
    TextGadget  (#lblSurname,  10,  75,  60, 20, "")
    StringGadget(#txtSurname,  70,  70, 240, 20, "Parker")
    ButtonGadget(#cmdOK,      145, 105,  80, 25, "")
    ButtonGadget(#cmdCancel,  230, 105,  80, 25, "")
    
    ReloadCaptions()
    
    Repeat
      
      Select WaitWindowEvent()
        
        Case #PB_Event_Gadget
          
          Select EventGadgetID()
            
            Case #cboLanguage
              
              If GetGadgetState(#cboLanguage) > -1
                SelectedLanguage = GetGadgetState(#cboLanguage) + 1
                ReloadCaptions()
              EndIf
              
            Case #cmdOK     : Break
            Case #cmdCancel : Break
              
          EndSelect
          
        Case #PB_Event_CloseWindow : Break
          
      EndSelect
      
    ForEver
    
    CloseWindow(#frmMain)
    
    End
    
  EndIf
  
EndIf
hier noch die entsprechende XML-Datei. Bitte unter 'languages.xml' speichern.

Code: Alles auswählen

<?xml version="1.0" encoding="ISO-8859-1"?> 
<items>

	<available_languages>
		<ln>en</ln>
		<ln>de</ln>
	</available_languages>

	<item id="de">
		<de>Deutsch</de>
		<en>German</en>
	</item>
	<item id="en">
		<de>Englisch</de>
		<en>English</en>
	</item>

	<item id="frmMain">
		<de>Beispiel: Mehrsprachigkeit</de>
		<en>Demo: Multilingualism</en>
	</item>
	<item id="lblLanguage">
		<de>&Sprache:</de>
		<en>&Language:</en>
	</item>
	<item id="lblName">
		<de>&Vorname:</de>
		<en>&Name:</en>
	</item>
	<item id="lblSurname">
		<de>&Nachname:</de>
		<en>&Surname:</en>
	</item>
	<item id="cmdOK">
		<de>OK</de>
		<en>OK</en>
	</item>
	<item id="cmdCancel">
		<de>Abbrechen</de>
		<en>Cancel</en>
	</item>
</items>
Grüße ... Kiffi
Benutzeravatar
Konne
Beiträge: 764
Registriert: 30.03.2005 02:20
Kontaktdaten:

Beitrag von Konne »

Ist es eigendlich schlecht die Texte einer Sprache jeweils in eine eigene ini zu packen?
Das würde das herunterladen neuer Sprachfiles extrem vereinfachen,
da nicht immer alle neu gezogen werden müssten.
Kennt jemand Gegenargumente dafür?
Wie machen es denn andere Programme?
Benutzeravatar
Kiffi
Beiträge: 10714
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Beitrag von Kiffi »

> Ist es eigendlich schlecht die Texte einer Sprache jeweils in eine eigene ini
> zu packen?

nein. Ist halt Geschmackssache.

> Das würde das herunterladen neuer Sprachfiles extrem vereinfachen,
> da nicht immer alle neu gezogen werden müssten.

Extrem vereinfachen ist IMO eine kleine Übertreibung. Sind Deine
Sprachdateien denn so gross?

> Kennt jemand Gegenargumente dafür?

Meiner Meinung nach ist die Pflege/Wartung vieler kleiner Dateien
aufwändiger als wenn man alles in einer Datei vorfindet. Nehmen wir mal
an, Du möchtest eine Sprache neu einpflegen. Dankenswerterweise findet
sich auch ein netter Zeitgenosse, der dieser Sprache mächtig ist. Ich
glaube, dass er es einfacher hat, wenn er in der in dem von mir gezeigten
XML-Beispiel alles in einer Datei vorfindet.

Grüße ... Kiffi
Benutzeravatar
benny
Beiträge: 383
Registriert: 29.08.2004 09:18
Wohnort: Am Ende des www's
Kontaktdaten:

Beitrag von benny »

@Konne:

IMHO ist daran nichts schlechtes und es ist in Sachen Mehrsprachigkeit
auch die richtige Alternative. Damit besteht natürlich lediglich die Möglichkeit
(oder evtl. sieht jmd auch eine Gefahr darin), daß sämtlliche Texte auch vom
User verändert werden können. Aber das sollte man eigentlich als Feature
ansehen.

INI-Dateien sind meiner Meinung nach auch gut. Ich würde dann drauf
achten, daß man auch das Programm nicht im Nachhernein ändern muss.
Soll heißen, Du hast beispielsweise einen Unterorderner in Deiner Anwendung
der z.B. languages heißt. In diesem kommen dann alle Sprachdateien.

Beim Starten wird dann immer geprüft, welche Sprachen verfügbar sind
und somit auch benutzbar sind.

Somit entfällt eine notwendige Anpassung des Programmes und man kann
nach Belieben nach und nach neue Sprachdateien dem Programm ver-
fügbar machen :!:

Im Java Umfeld gibt es ein Framework, welches sich struts nennt,
dieses bietet u.a. auch die Mehrsprachigkeit an und dort werden die je-
weiligen Sprachinformationen in einfachen Textdateien abgelegt.
So long,
benny!
.
nur t0te f1sche schw1mmen m1t dem str0m - 00100 !
Benutzeravatar
freedimension
Admin
Beiträge: 1987
Registriert: 08.09.2004 13:19
Wohnort: Ludwigsburg
Kontaktdaten:

Beitrag von freedimension »

Konne hat geschrieben:Ist es eigendlich schlecht die Texte einer Sprache jeweils in eine eigene ini zu packen?
Ich wundere mich auch ein wenig über die Herangehensweise. Nehmen wir einmal an ich wäre Ungar und mir gefällt das Programm so gut, dass ich das einungarischen möchte muss ich das in der Datei mit all den anderen Sprachen machen. Ein anderer pflegt polnisch ein ... italienisch ... indisch ... nun ja, man kann sich das Durcheinander wahrscheinlich lebhaft vorstellen. Das ganze jetzt wieder in eine Datei zusammenzuklopfen ist auch nicht ohne, obwohl sich dafür sicherlich ein kleines Tool schreiben liese :freak:

Nochwas zu der Sprachdatei:
Das eXtensible in XML heißt nicht, dass man nach Belieben neue Tags hinzufügen kann (klar kann man, aber so war's nicht gedacht). Hier ein en-Tag, dort ein de-Tag und später dann vielleicht noch ein es-Tag?
Warum genau wird hier, wenn schon denn schon, nicht mit Attributen gearbeitet?
Beginne jeden Tag als ob es Absicht wäre!
Bild
BILDblog
Benutzeravatar
Konne
Beiträge: 764
Registriert: 30.03.2005 02:20
Kontaktdaten:

Beitrag von Konne »

@benny
Also ich mach des so:
Alle Sprachinis kommen in einem Ordner und dann lese ich da mit den Directory Befehlen alle Dateien raus.
Da die Dateien die Namen der Sprache haben kann ich sie dann ganz einfach in nem Combobox Gadget anzeigen.

Das mit der veränderbarkeit ist natürlich ein Feature.
Benutzeravatar
benny
Beiträge: 383
Registriert: 29.08.2004 09:18
Wohnort: Am Ende des www's
Kontaktdaten:

Beitrag von benny »

Konne hat geschrieben:@benny
Also ich mach des so:
Alle Sprachinis kommen in einem Ordner und dann lese ich da mit den Directory Befehlen alle Dateien raus.
Da die Dateien die Namen der Sprache haben kann ich sie dann ganz einfach in nem Combobox Gadget anzeigen.

Das mit der veränderbarkeit ist natürlich ein Feature.
Jup. So in der Art meinte ich das auch :!:
So long,
benny!
.
nur t0te f1sche schw1mmen m1t dem str0m - 00100 !
Antworten