Inhaltsverzeichnis
Translate

GnuGetText-Werkzeuge für Delphi


Integration in Delphi-Programme

Definition der Texte

Alle Strings, die in andere Sprachen übersetzt werden sollen, müssen im Quelltext so gekennzeichnet sein, dass sie von dxgettext beim Durchsuchen der Dateien eindeutig gefunden werden.

Formulare

Texte, die in einem Formular definiert sind, wie z.B. Caption, Hint und Text werden von dxgettext automatisch erkannt. Im Quelltext der zugehörigen Unit muss die Funktion TranslateComponent (siehe unten) im OnCreate-Ereignis des Formulars angegeben werden.

Ressourcen-Strings

Alle in einer Sektion resourcestring definierten Texte werden automatisch erkannt und während der Laufzeit durch die jeweilige Übersetzung ersetzt.
Beispiel:

   resourcestring
     msg = 'Hello, World'; 
     ... 

Andere Strings im Quelltext

Zu übersetzende Strings müssen als Argument einer der folgenden Funktionen angegeben werden, damit sie von dxgettext erkannt werden:
_(<string>), gettext(<string>) und dgettext(<domain><string>).

Die Funktionen sind in der Unit GnuGetText definiert.
Beispiele:

   gettext('Hello, World');           // Textdefinition für die Standarddomäne "default"
   _('Hello, World');                 // Kurzform der Funktion "gettext"
   dgettext('domain','Hello, World'); // wie "gettext" aber mit anderer Domäne 
   ... 

Erforderliche Programmergänzungen

Initialisierung des Projektes

In der dpr-Datei des Projekts sind einige Ergänzungen erforderlich, wenn neben der Standarddomäne default auch andere verwendet werden und, wenn bestimmte Komponenten oder Klassen , wie z.B. TFont von der Übersetzung ausgeschlossen werden sollen.
Beispiel:

  program sample;
  
  uses
    GnuGetText in 'GnuGetText.pas',   // enthält die unten aufgerufenen Funktionen
    Vcl.Forms,
    SampleMain in 'SampleMain.pas' {frmMerge};
  
  begin
    TP_GlobalIgnoreClass(TFont);      // Ausschluss von Klassen von der Übersetzung
    AddDomains(['delphi10','units']); // Definition zusätzlicher Textdomänen
  
    Application.Initialize;
    Application.MainFormOnTaskbar := True;
    Application.CreateForm(TfrmMain, frmMain);
    Application.Run;
  end.

Als erstes muss die Unit GnuGetText in der uses-Klausel angegeben werden, da in ihr die aufzurufenden Funktionen definiert sind. Je nach Bedarf kann dann vor der Initialisierung der Anwendung eine der folgenden Funktionen eingefügt werden:

Die Beschreibungen von weiteren möglichen Funktionen findet man in der ausführlichen englischen Beschreibung.

Einbinden GnuGetText in die Units

In Units, die ein Formular verwenden, müssen beim Erstellen die im Formular verwendeten Texte durch die jeweiligen Übersetzungen ersetzt werden. Dazu wird die Prozedur TranslateComponent im OnCreate-Ereignis des Formulars aufgerufen.

Beispiele:

  procedure TMyForm.FormCreate (Sender: TObject);
    begin
    TranslateComponent (self);
    ...
    end;  
    
  procedure TMyForm.FormCreate (Sender: TObject);
    begin
    TranslateComponent (self,'units');
    ...
    end;  
    

Festlegen der Sprache beim Start des Programms

Wenn die Unit GnuGetText, wie oben beschrieben, in die uses-Klausel der Projekt-Datei eingebunden ist, wird bei ihrer Initialisierung (Programmabschnitt initialization) automatisch die vom Benutzer im System eingestellte Anzeigesprache ermittelt und als Standardsprache gespeichert. Wenn der Benutzer eine andere Sprache verwenden möchte, kann er dies in der dpr-Datei vor der Anwendungsinitialisierung durch Aufruf der Prozedur Uselanguage erreichen.
Beispiel:

  program sample;
  
  uses
    GnuGetText in 'GnuGetText.pas',
    ...  
  begin
    AddDomains(['delphi10','units']);
    UseLanguage('de');
    ...  
  end.

Ändern der Sprache während der Laufzeit

Zunächst muss die neue Sprache im GnuGetText-System registriert werden. Dann muss für jedes verwendete Formular die Prozedur TranslateComponent aufgerufen werden.
Beispiel:

  procedure ChangeLanguage (NewLangCode : LanguageString);
  var
    i : integer;
  begin
    UseLanguage(NewLangCode);
    with Application do for i:=0 to ComponentCount-1 do if (Components[i] is TForm) then
      ReTranslateComponent(Components[i]);
    end;

Einbinden der Übersetzungen in das Projekt

Die Übersetzungen können entweder aus den mo-Dateien beim Start des Programms geladen oder als Ressourcen in die exe-Datei eingebunden werden. Beide nachfolgend beschriebenen Verfahren erlauben, wenn mehrere exe-Dateien einer Projektgruppe die gleichen Übersetzungen verwenden, eine gemeinsame Benutzung.

Laden aus den mo-Dateien

Bei der Erstellung des Installationspakets ist darauf zu achten, dass bei der Installation des Programms exakt die im Nachfolgenden beschriebene Unterverzeichnisstruktur angelegt wird.

Sie ist ein wenig unübersichtlich und erklärt sich am besten durch das nachfolgende Beispiel. Zunächst gibt es im Verzeichnis mit dem ausführbaren Programm (exe-Datei) ein Unterverzeichnis locale. Darunter befindet sich für jede unterstützte Sprache ein weiteres Unterverzeichnis, dessen Name dem Kürzel nach ISO639 (z.B. de, es, it) entsprechen muss. In jedem dieser sprachspezifischen Unterverzeichnisse gibt es dann ein weiteres Unterverzeichnis LC_MESSAGES, in dem sich schließlich die mo-Dateien (default.mo und evtl. die für weitere Textdomänen) mit den jeweiligen Übersetzungen befinden.
Das nachfolgende Beispiel erläutert die Struktur:

  <Exe-Verzeichnis>\  
    > locale\
      > de\ 
        > LC_MESSAGES\
          > default.mo         
          > delphi10.mo
      > es\ 
        > LC_MESSAGES\
          > default.mo         
          > delphi10.mo
      ...    

Einbetten in die exe-Datei als Ressourcen

Dazu wird dem Delphi-Projekt eine Ressourcendatei hinzugefügt. Dies geschieht entweder mit Projekt ⇒ Dem Projekt hinzufügen... (Umsch+F11), wenn die rc-Datei bereits mit einem externen Editor erstellt wurde, oder es wird mit Datei ⇒ Neu ⇒ Weitere... die Objektgalerie geöffnet, um eine neue Ressource zu erstellen. Man wählt dort Textdatei und .rc - Ressourcendatei und gibt den erforderlichen Code im Delphi-Texteditor ein. Das Delphi-System fügt in beiden Fällen automatisch einen entsprechenden Eintrag in die dpr-Datei ein, so dass die Ressource automatisch bei jeder Compilierung aktualisiert und geladen wird.

Format der rc-Datei

Alle Einträge in der Ressourcendatei sind vom Typ RCDATA. Es werden folgende Bezeichner verwendet:

Dabei sind:

Beispiel:

  IDR_LANGUAGES RCDATA "languages\\language.cfg"
  IDR_TRANS_DE_LANGUAGES RCDATA "..\\Common\\Languages\\de\\languages.mo"
  IDR_TRANS_DE_DEFAULT RCDATA "languages\\de\\default.mo"
  IDR_TRANS_DE_DELPHI10 RCDATA "..\\Common\\Languages\\de\\delphi10.mo"
  IDR_TRANS_DE_DIALOGS RCDATA "..\\Common\\Languages\\de\\dialogs.mo"
  IDR_TRANS_DE_UNITS RCDATA "..\\Common\\Languages\\de\\units.mo"

Wenn mehrere exe-Dateien einer Projektgruppe die gleichen Übersetzungen verwenden, genügt es diese rc-Datei (z.B. languages.rc) nur einmal zu erstellen und jedem Projekt der Gruppe hinzuzufügen.


Weitere Hilfsfunktionen

Einige weitere Hilfsfunktionen stellt die Unit LangUtils.pas bereit:

Sprachauswahl beim Programmstart

Zur Initialisierung der Sprachenverwaltung wird in der dpr-Datei des Projekts die Funktion InitTranslation aufgerufen. Es gibt mehrere überladene Versionen:

Die Aufruf-Parameter haben folgende Bedeutung:

<domains>
Liste der zusätzlichen Text-Domänen (siehe auch die Funktion AddDomains in GnuGettext.pas), z.B. [delphi10,units]
<directory>
Optionales Unterverzeichnis von AppData\Roaming, in dem die cfg-Datei mit der Spracheinstellungen abgelegt ist.
<filename>
Alternativer Name der cfg-Datei, z.B. myprog.cfg oder myprog.ini. Fehlt diese Angabe, wird eine Datei <Anwendungsname>.cfg verwendet. Es wird dort ein Eintrag folgender Art angelegt:
    [Language]
      LangID=xx   (z.B. de, en, etc.)

Die Funktion muss in der dpr-Datei des Projektes vor Application.Initialize aufgerufen werden. Sie lädt die erforderlichen Sprach-Ressourcen (entweder aus externen oder in eingebetteten mo-Dateien). Außerdem sucht sie in der o.g. cfg-Datei oder in der Befehlszeile (s.u.) nach einer voreingestellten Sprache. Wird keine dieser Einstellungen gefunden, wird die vom System verwendete Sprache ausgewählt.

Ändern der Sprache über die Befehlszeile

Es wird geprüft, ob die Befehlszeile beim Aufruf des Programms die Option /la:xx enthält (xx ist der Zwei-Buchstaben-Code des Landes, z.B. de). Diese Einstellung hat Vorrang vor einer Sprachauswahl in der cfg-Datei.

Ändern der Sprache über ein Menü

Ein Programm-Menü (TMainMenu oder TPopupMenu) kann durch eine Liste der bereitgestellten Sprachen erweitert werden, so dass die Auswahl einer anderen Sprache einfach durch Klick auf einen dieser Menüeinträge erfolgt. Diese Liste wird in der jeweils ausgewählten Sprache angezeigt (s.u.). Die Unit LangUtils stellt dazu die Klasse TLanguageList zur Verfügung. In der Haupt-Unit sind dazu einige Ergänzungen erforderlich:

Im Interface-Teil
    interface
    uses ..., LangUtils, ...
    ...
    type
      TMainForm = class(TForm)
        ...
      private
        ...
        Languages : TLanguageList;
        procedure SetLanguageClick(Sender : TObject; Language : TLangCodeString);
        ...
      end;
      ...
Im FormCreate-Ereignis
  procedure TfrmMain.FormCreate(Sender: TObject);
  begin
    ...
    Languages:=TLanguageList.Create(PrgPath,LangName);
    with Languages do begin
      Menu:=itmLanguage;
      LoadLanguageNames(SelectedLanguage);
      OnLanguageItemClick:=SetLanguageClick;
      end;
      ...
Als OnClick-Ereignis
  procedure TfrmMain.SetLanguageClick(Sender : TObject; Language : TLangCodeString);
  begin
    if not AnsiSameStr(SelectedLanguage,Language) then begin
      Languages.SelectedLanguageCode:=Language;
      ChangeLanguage(Language);
      Languages.LoadLanguageNames(Language);
      ...
      end;
    end;
Weitere Erläuterungen
LoadLanguageNames('xx');
Die Menüeinträge werden an die jeweils ausgewählte Sprache angepasst. Dazu müssen entsprechende übersetzte Listen bereitgestellt werden, wobei es eine unterschiedliche Verfahrensweise gibt, je nachdem ob die Übersetzungen aus Dateien geladen werden oder als Ressourcen eingebunden sind. Weitere Erläuterungen dazu findet man weiter unten.
ChangeLanguage('xx');
Diese Funktion nimmt die Umschaltung der Sprache vor (xx ist der Zwei-Buchstaben-Code des Landes, z.B. de). In GnuGetText werden die zur ausgewählten Sprache gehörenden Ressourcen geladen, bzw. aktiviert. Außerdem werden sämtliche Formulare der Anwendung an die geänderte Sprache angepasst.

Bereitstellung der Sprachenlisten für das Auswahlmenü

Laden aus externen Dateien
Im Verzeichnis der Anwendung (exe-Datei) liegt eine Datei language.cfg mit den englischen Bezeichnungen der zu unterstützenden Sprachen (siehe unten, linke Spalte). Die Liste darf auch Einträge für Sprachen enthalten, die noch nicht unterstützt werden, aber für eine spätere Erweiterung vorgesehen sind. Sie werden am Zeilenanfang durch das Zeichen "#" gekennzeichnet, um sie zu deaktivieren. Entsprechende Dateien mit dem gleichen Namen und den übersetzten Sprachbezeichnungen befinden sich in denselben Unterverzeichnissen, wie die mo-Dateien (LC_MESSAGES, s.o.). Die beiden rechten Spalten unten enthalten Bespiele. Das "#"-Zeichen muss hier nicht eingefügt werden, da dies aus der englischen Originalliste übernommen wird.

Beispiel:

  
# International language codes  
#da=Danish
de=German
en=English
es=Spanish
#fi=Finnish
fr=French
#hr=Croatian
hu=Hungarian
it=Italian
nl=Dutch
  
# German
da=Dänisch
de=Deutsch
en=Englisch
es=Spanisch
fi=Finnisch
fr=Französisch
hr=Kroatisch
hu=Ungarisch
it=Italienisch
nl=Holländisch
   
# French
da=Danois
de=Allemand
en=Anglais
es=Espagnol
fi=Finnois
fr=Français
hr=Croate
hu=Hongrois
it=Italien
nl=Néerlandais
Einbinden als Ressource

Der Ressourcen-Datei (s.o.) wird die Zeile IDR_LANGUAGES RCDATA "languages\\language.cfg" hinzugefügt. Der Aufbau dieser Datei ist im vorhergehenden Abschnitt (s.o.) beschrieben. Die Übersetzungen der Sprachbezeichner werden als mo-Dateien für die Text-Domäne LANGUAGES eingebunden. Entsprechend wird für jede der zu unterstützenden Sprachen in die Ressourcen-Datei eine Zeile mit dem Bezeichner IDR_TRANS_xx_LANGUAGES RCDATA eingefügt (xx = Zwei-Buchstaben-Code des Landes).

Beispiel:

  IDR_LANGUAGES RCDATA "languages\\language.cfg"
  IDR_TRANS_DE_LANGUAGES RCDATA "..\\Common\\Languages\\de\\languages.mo"
  IDR_TRANS_FR_LANGUAGES RCDATA "..\\Common\\Languages\\fr\\languages.mo"
  ...


J. Rathlev, D-24222 Schwentinental, Juni 2025