Button Home/Top/Zurück


Mehrsprachige Access-Anwendungen




Mit der Popularität einer Anwendung steigt auch die Gefahr , daß diese in anderen Sprachen verfügbar sein muß.
Nun steht der Entwickler vor der Entscheidung die betreffende Datenbank zu kopieren und händisch alle Beschriftungen und Meldungstexte in eine andere Sprache zu übersetzen oder eine Sprachumsetzung zu implementieren.
Letzteres ist sicherlich die bessere Lösung, da im ersten Fall die Gefahr besteht, daß die beiden Datenbanken auseinanderlaufen. D.h. Änderungen an der z.B. deutschen Version werden in der englischen Version nicht nachgezogen. Kommt nun zu allem Überfluß noch eine dritte oder vierte Sprache dazu, ist das Chaos perfekt.

Beim DonKarl gibt es zu diesem Thema folgenden Hinweis FAQ 1.19 DB AUF ANDERSPRACHIGEM SYSTEM, den man unbedingt vorher gelesen haben sollte.
Zum anderen sollte man den Aufwand, den die Mehrsprachigkeit bedeutet, nicht unterschätzen.

Lösungsansatz
Das Ziel muß sein, eine Datenbank zu erhalten, die über einen Aufrufparameter o.ä. auf eine Sprache eingestellt wird.
Die Sprachumsetzung muß für folgende Elemente erfolgen:
  • Meldungstexte
  • Beschriftungen von Formularen, Berichten und Steuerelementen
  • Ausgaben in der Statuszeile
  • Ausgaben als Tooltip
  • Ausgaben von Gültigkeitsmeldungen, die an Steuerelementen definiert werden.
Alle diese Meldungstexte und Beschriftungen werden in Tabellen der Datenbank definiert und bei Bedarf von dort geladen.

Weiter zu beachten sind:
  • unterschiedliche Währungs- und Datumsformate
    Hier sollte auf selbstdefinierte Formatierung verzichtet werden.
    Stattdessen sollten nur die vordefinierten Standardformate und Typen verwendet werden.
    Für Währungsfelder heißt dies, daß diese immer mit dem Typ- und dem Format Währung definiert werden.
    Datumsfelder werden müssen immer vom Typ Datum/Uhrzeit und dem Format Standarddatum definiert werden.
  • unterschiedliche Dezimaldarstellungen (auch innerhalb von VBA)
    Solange bei der Darstellung von Zahlen keine tausender Trennzeichen verwendet werden, sollte es keine Problem geben.
  • unterschiedliche Laufweiten in den Beschriftungen
    Hiermit ist die unterschiedliche Länge von Beschriftungen gemeint. Die Beschriftung neben einem Eingabefeld für einen Familiennamen kann entweder "Familienname:" (13 Zeichen) oder "surname:" (8 Zeichen) sein.
    Hier ist also darauf zu achten, daß das Beschriftungsfeld so breit ist, um die längste der möglichen Beschriftungen aufzunehmen.
  • Gültigkeitsregeln und Meldungen in der Tabellendefinition.
    Hier gibt es ein Problem mit einer der nachfolgend beschriebenen Varianten. Bei einer der Varianten erfolgt die Sprachumsetzung zur Laufzeit (beim Öffnen von Formularen und Berichten). Da die Gültigkeitsmeldungen in der Tabellendefinition aber nur im Entwurfsmodus geändert werden können, würden hier eine einmalige Sprachumsetzung ausreichend sein.


Voraussetzungen
Für die Meldungstexte und Steuerelementbeschriftungen müssen "Henkel" geschaffen werden, mit deren Hilfe die Sprachumsetzung erfolgen kann.
Für Meldungstexte bietet sich hier eine Message-ID an, ähnlich einer Fehlernummer oder einem Fehlercode.
Für den Entwickler heißt dies, alle Aufrufe der Funktionen MsgBox() und Err.Raise in der Datenbank ausfindig zu machen um dort festcodierte Texte durch einen Funktionsaufruf (mit Message-ID) zu ersetzen.

Für die Beschriftungen in Formularen und Berichten sollte als "Henkel" die Bezeichnung des Steuerelementes, des Formulars oder des Berichtes herangezogen werden.
Für den Entwickler heißt dies, das alle Bezeichnungen (von Bezeichnungsfeldern, Formularen, Berichten) anzupassen sind. Dabei sollte darauf geachtet werden, daß durch die Verwendung von gleichlautenden Bezeichnungen der manuelle Pflegeaufwand (Übersetzen der Beschriftungen) verringert werden kann. So sollte überall dort wo der Text Personalnummer in einem Bezeichnungsfeld stehen soll, dieses Bezeichnungsfeld z.B. den Namen txtPersonalnummer haben.
Die Beschriftung selber sollte nicht als "Henkel" verwendet werden, da in diesem Fall die Sprachumsetzung immer von Sprache A nach Sprache B erfolgen muß. Bei einer Implementierung, bei der die Beschriftungen dauerhaft geändert werden, muß dann immer erst festgestellt werden in welcher Sprache die Datenbank gerade vorliegt.

Implementierung
Für die Meldungstext wird eine Tabelle angelegt, die ungefähr so aussehen sollte:
MsgID | SpracheID | Meldungstext
------+-----------+--------------------------------------------
   1  |     1     | Bitte geben Sie den Nachnamen an.
   1  |     2     | Please insert the sure name.
   2  |     1     | Bitte geben Sie den Vornamen an.
   2  |     2     | Please insert the fist name.
	  
Um einen Meldungstext zu ermitteln kann eine allgemeine Funktion implementiert werden, die so aussehen könnte:
Function GetMessage(MsgID) As String
'
' Meldungstext zu einer Message gemäß Spracheinstellung
' ermitteln
'
Dim vVar As Variant
    '
    ' Meldungstext aus der Tabelle "Meldungstexte" lesen
    '
    vVar = DLookup("[Meldungstext]", "Meldungstexte", "[MsgID]=" & Str$(MsgID) & _
                   " AND SpracheID=" & Str$(GlbSpracheID))
    '
    ' prüfen, ob eine Meldung gefunden wurde
    '
    If IsNull(vVar) Then
        GetMessage = "Kein Meldungstext für ID " & Str$(MsgID) & " definiert"
    Else
        GetMessage = vVar
    End If
 
End Function

In diesem Beispiel ist GlbSpracheID eine globale Variable, die beim Öffnen der Datenbank gesetzt wird.
Um nun eine Meldung auszugeben kann diese Funktion verwendet werden:
Private Sub dfNachname_Exit(Cancel As Integer)
'
' Der Nachname muß angegeben werden
'
    If Trim$(Me.dfNachname) = "" Then
        MsgBox GetMessage(1)
    End If
 
End Sub

In diesem Beispiel wird beim Verlassen eines Textfeldes (dfNachname) geprüft ob dort eine Eingabe erfolgt ist. Wenn nicht wird die entsprechende Fehlermeldung ausgegeben.

Die Sprachumsetzung von Beschriftungen ist ein wenig komplizierter.
Als Grundlage dient wieder eine Tabelle, in der die Beschriftungen definiert werden.
SpracheID | Steuerelementname | Beschriftung    | ToolTipText | Statuszeilentext | Gueltigkeitsmeldung
----------+-------------------+-----------------+-------------+------------------+-----------------------
   1      | FrmPersonaldaten  | Personaldaten   |             |                  |
   1      | RptPersonal       | Personaldaten   |             |                  |
   1      | txtAnschrift      | Anschrift:      | Anschrift...|                  |
   1      | txtNachname       | Nachname:       | Nachname ...|                  |
   1      | txtPersNr         | Personalnummer: | Personal....|                  |
   1      | txtVorname        | Vorname:        | Vorname der.|                  |
   1      | dfVorname         |                 | Eingabe des.| Eingabe des Vor..| Bitte geben Sie den...
   2      | FrmPersonaldaten  | staff data      |             |                  |
   2      | RptPersonal       | staff data      |             |                  |
   2      | txtAnschrift      | contact:        | primary con.|                  |
   2      | txtNachname       | surname:        | surname of. |                  |
   2      | txtPersNr         | staff no.:      | staff numbe.|                  |
   2      | txtVorname        | firstname:      | firstname...|                  |
   1      | dfVorname         |                 | insert of ..| insert of the ...| please, give the ....
	  
Für die Sprachumsetzung von Formularen ist eine Prozedur notwendig, in der alle Steuerelemente eines Formulars geprüft und deren Beschriftung ggf. ersetzt werden.
Sub SetFormBeschriftung(AktFrm As Form)
'
' Alle Beschriftungen für ein Formular entsprechend
' der Spracheinstellung setzen.
'
Dim AktCtrl As Control
 
    '
    ' Formulartitel (Überschrift)
    '
    AktFrm.Caption = GetBeschriftung(AktFrm.Name, cCaption)
    '
    ' Alle Steuerelemente des Formulars abklappern
    '
    For Each AktCtrl In AktFrm.Controls
        '
        ' Prüfen, ob der Steuerelement-Typ eine
        ' Beschriftung beinhaltet.
        ' Dies sind:
        '
        ' + Bezeichungsfelder: acLabel
        ' + Pushbuttons: acCommandButton
        '
        If AktCtrl.ControlType = acLabel Or _
           AktCtrl.ControlType = acCommandButton Then
            AktCtrl.Caption = GetBeschriftung(AktCtrl.Name, cCaption)
        End If
        '
        ' Tool-Tip-Text für alle Steuerelemente setzen
        '
        AktCtrl.ControlTipText = GetBeschriftung(AktCtrl.Name, cToolTipText)
        '
        ' Statuszeilentext für alle Steuerelemente (außer Labels) setzen
        '
        If AktCtrl.ControlType <> acLabel Then
            AktCtrl.StatusBarText = GetBeschriftung(AktCtrl.Name, cStatusText)
        End If
        '
        ' Wenn notwendig, dann die Gültigkeitsmeldung setzen
        '
        If AktCtrl.ControlType <> acLabel And _
           AktCtrl.ControlType <> acCommandButton Then
            If AktCtrl.ValidationRule <> "" Then
                AktCtrl.ValidationText = GetBeschriftung(AktCtrl.Name, cValidationText)
            End If
        End If
    Next AktCtrl
 
End Sub

Für Berichte sieht die Prozedur identisch aus, mit Ausnahme das dort kein Formular- sondern ein Berichts-Objekt übergeben wird.
Nun muß noch die Ereignisprozedur Beim Öffnen aller Formulare und Berichte implementiert werden. Aber keine Angst, viel ist da nicht zu machen:

Private Sub Form_Open(Cancel As Integer)
 
 
    SetFormBeschriftung Me
 
End Sub

Nun fehlt noch die Funktion GetBeschriftung() welche in der Prozedur SetFormBeschriftung() verwendet wird. Diese sieht so aus:
Function GetBeschriftung(CtrlName As String, Art As Integer) As String
'
' Ermittelt die Beschriftung zu einem Steuerelement
'
Dim vVar As Variant
    '
    ' prüfen, ob ein Controlname angegeben ist
    '
    If Trim$(CtrlName) = "" Then
        MsgBox "Kein Controlname angegeben", "GetBeschriftung"
        Exit Function
    End If
    '
    ' Auswahl der Beschriftungsart
    '
    Select Case Art
    Case cToolTipText:
        '
        ' Tool-Tip-Text aus Tabelle "Beschriftungen" lesen
        '
        vVar = DLookup("[ToolTipText]", "Beschriftungen", _
                       "[Steuerelementname]='" & CtrlName & "' AND " & _
                       "[SpracheID]=" & Str$(GlbSpracheID))
    Case cCaption:
        '
        ' Beschriftung aus Tabelle "Beschriftungen" lesen
        '
        vVar = DLookup("[Beschriftung]", "Beschriftungen", _
                       "[Steuerelementname]='" & CtrlName & "' AND " & _
                       "[SpracheID]=" & Str$(GlbSpracheID))
    Case cStatusText:
        '
        ' Statuszeilentext aus Tabelle "Beschriftungen" lesen
        '
        vVar = DLookup("[Statuszeilentext]", "Beschriftungen", _
                       "[Steuerelementname]='" & CtrlName & "' AND " & _
                       "[SpracheID]=" & Str$(GlbSpracheID))
    Case cValidationText:
        '
        ' Gültigkeitmeldung aus Tabelle "Beschriftungen" lesen
        '
        vVar = DLookup("[Gueltigkeitsmeldung]", "Beschriftungen", _
                       "[Steuerelementname]='" & CtrlName & "' AND " & _
                       "[SpracheID]=" & Str$(GlbSpracheID))
    End Select
    '
    ' prüfen, ob eine Beschriftung gefunden wurde
    '
    If IsNull(vVar) Then
        GetBeschriftung = ""
        '
        ' Den Namen des Steuerelementes in die Tabelle Beschriftung eintragen,
        ' damit man weiß was noch zu ergänzen ist.
        '
        CurrentDb.Execute "INSERT INTO Beschriftungen (SpracheID, Steuerelementname) " & _
                          "VALUES(1,'" & CtrlName & "');"
 
    Else
        GetBeschriftung = vVar
    End If
 
End Function

Nun könnten Skeptiker auf die Idee kommen, daß dadurch das diese Sprachumsetzung zur Laufzeit erfolgt, mit Performance-Einbußen zu rechnen ist.
Da ein Formular/Bericht in der Regel zwischen 1 bis maximal 30 Steuerelemente enthält (oder besser: enthalten sollte) ist bei den heutigen Rechnern auf gar keinen Fall mit solchen Schwierigkeiten zu rechnen.

Wem dies aber trotzdem nicht geheuer ist, dem sei die Variante der Sprachumsetzung ans Herz gelegt, welche die Sprachumsetzung im Entwurfsmodus vornimmt.
Hierbei werden (via VBA) alle Formulare und Berichte einer Datenbank im Entwurfsmodus geöffnet und die Beschriftungen direkt im Entwurf geändert.
Dazu ist folgende Prozedur notwendig:
Sub SpracheUmsetzen()
'
' Umsetzen der Sprach im Entwurfsmodus von Berichten und Formularen
'
Dim AktFrm As Form
Dim AktReport As Report
Dim AktDb As Database
Dim AktCont As Container
Dim AktDoc As Document
 
    '
    ' aktuelle Datenbank auswählen
    '
    Set AktDb = CurrentDb
    '
    ' Aus der Container-Auflistung die Formulare auswählen
    '
    Set AktCont = AktDb.Containers!Forms
    '
    ' Schleife über alle Formulare
    '
    For Each AktDoc In AktCont.Documents
        '
        ' Das Formular "Sprachauswahl" wird nicht bearbeitet
        '
        If AktDoc.Name <> "Sprachauswahl" Then
            '
            ' Formular im Design-Modus öffnen
            '
            DoCmd.OpenForm AktDoc.Name, acDesign
            '
            ' Objektvariable auf das Formular setzen
            '
            Set AktFrm = Forms(AktDoc.Name)
            '
            ' Beschriftungen austauschen
            '
            SetFormBeschriftung AktFrm
            '
            ' Formular schließen und Änderungen speichern
            '
            DoCmd.Close acForm, AktDoc.Name, acSaveYes
        End If
    Next AktDoc
    '
    ' Aus der Container-Auflistung die Berichte auswählen
    '
    Set AktCont = AktDb.Containers!Reports
    '
    ' Schleife über alle Berichte
    '
    For Each AktDoc In AktCont.Documents
        '
        ' Bericht im Design-Modus öffnen
        '
        DoCmd.OpenReport AktDoc.Name, acViewDesign
        '
        ' Objektvairable auf den Bericht setzen
        '
        Set AktReport = Reports(AktDoc.Name)
        '
        ' Beschriftungen austauschen
        '
        SetReportBeschriftung AktReport
        '
        ' Bericht schließen und Änderungen speichern
        '
        DoCmd.Close acReport, AktDoc.Name, acSaveYes
    Next AktDoc
 
End Sub

Bei dieser Variante erhöht sich allerdings der Administrationsaufwand, da für jede Sprache eine Kopie der Datenbank angelegt und verwaltet werden muß.


WinZip Icon Download der Sprachumsetzung zur Laufzeit (46 KB)
WinZip Icon Download der Sprachumsetzung im Entwurfsmodus (54 KB)

Button Home/Top/Zurück