Tutoriel MSEide


Eine mehrsprachige Anwendung mit MSEi18n

Meine Anwendung

Meine Anwendung orientiert sich am Beispiel im Ordner <msedir>/apps/i18ndemo/.

Erstellen der Anwendung in MSEide

Meine Anwendung hat eine Komponente vom Typ tstringdisp und drei Schaltflächen, die zum Ändern der Sprache verwendet werden.

type
  tmainfo = class(tmainform)
    sd_weather: tstringdisp;
    bt_english: tbutton;
    bt_german: tbutton;
    bt_french: tbutton;

Komponenteneigenschaften

Im Objektinspektor weise ich der Eigenschaft frame.caption der Komponente sd_weather einen Wert zu.

Objektinspektor

Ich weise auch der text-Eigenschaft derselben Komponente einen Wert zu.

Objektinspektor

Ich habe auch die caption-Eigenschaft des Hauptformulars ausgefüllt.

Objektinspektor

Die msei18nutils-Unit

In main.pas füge ich den Verweis auf die Unit msei18nutils hinzu.

implementation

uses
  main_mfm,
  msei18nutils;

Ein String vom Typ resourcestring

Ich deklariere einen String vom Typ resourcestring.

uses
  main_mfm,
  msei18nutils;

resourcestring
  rs_goodbye = 'Good bye!';

Ich kompiliere meine Anwendung. Der Compiler informiert mich, dass er eine main.rsj-Datei erstellt.

Writing Resource String Table file: main.rsj

Aus Neugier werfe ich einen Blick in diese Datei (die sich im selben Ordner wie die kompilierten Units befindet).

{"version":1,"strings":[
{"hash":90624273,"name":"main.rs_goodbye","sourcebytes":[71,111,111,100,32,98,121,101,33],"value":"Good bye!"}
]}

Alles scheint korrekt. Es ist Zeit, die Anwendung MSEi18n zu öffnen.

MSEi18n

Die Anwendung MSEi18n befindet sich im Ordner <msedir>/tools/i18n/. Sie ist auch im Repository codeberg.org/rchastain/msei18n verfügbar.

MSEi18n-Konfiguration

Nachdem ich MSEi18n kompiliert habe, öffne ich es und klicke im Menü Settings auf den Menüpunkt Configure MSEi18n.

Die Felder MSEDIR und COMPILER müssen wie im folgenden Bild ausgefüllt werden.

In MSEDIR gebe ich den Pfad zum MSEgui-Ordner an, mit einem abschließenden / (hier /home/roland/Applications/mseide-463-dev/), denn die anderen Makros werden durch einfaches Anhängen gebildet, zum Beispiel ${MSEDIR}lib/common/. In COMPILER gebe ich den Free-Pascal-Compiler an (hier ppcx64; fpc ist ebenfalls möglich).

MSEi18n Configure

Erstellen eines Übersetzungsprojekts

Ich erstelle ein neues Übersetzungsprojekt (eine TRP-Datei), indem ich auf den Menüpunkt New klicke.

MSEi18n New

Nachdem ich den Speicherort und den Namen meines Projekts ausgewählt habe, klicke ich auf OK.

Bearbeiten des Projekts

Jetzt bearbeite ich mein Übersetzungsprojekt. Dazu klicke ich auf den Menüpunkt Edit.

Ich klicke in die Spalte File, um eine neue Zeile im Raster zu erstellen, und füge in diese Zeile die Datei main.mfm ein. In der Spalte Kind wähle ich rfk_module aus.

Da ich in meiner Anwendung einen String vom Typ resourcestring verwende, füge ich eine zweite Zeile hinzu. Dazu klicke ich mit der rechten Maustaste auf die erste Zeile und wähle im angezeigten Menü Append Row.

In der Spalte File gebe ich main.rsj an. In der Spalte Kind wähle ich rfk_resstrings aus.

Außerdem fülle ich die Spalten Language und Directory aus (eine Zeile für Deutsch, eine Zeile für Französisch).

MSEi18n Edit

Übersetzen der Strings

Mit einem Klick auf OK schließe ich das Fenster. Ich kann nun einerseits die in meiner MFM-Datei enthaltenen Strings und andererseits den in der RSJ-Datei enthaltenen String vom Typ resourcestring übersetzen.

MSEi18n

Sie werden feststellen, dass ich die Optionen flat und string only aktiviert habe, um nur die Daten anzuzeigen, die mich interessieren.

Speichern des Projekts

Sobald die Übersetzungsarbeiten abgeschlossen sind, speichere ich mein Projekt durch einen Klick auf den Menüpunkt Save.

Kompilierung

Bevor ich das Projekt kompiliere, erstelle ich die Ordner, die die Module enthalten sollen, basierend auf dem, was ich beim Bearbeiten des Projekts angegeben habe.

mkdir -p de
mkdir -p fr

Mit einem Klick auf Make kann ich das Projekt nun kompilieren. Es öffnet sich ein Fenster, in dem ich überprüfen kann, ob die Kompilierung der Module durch Free Pascal erfolgreich verlaufen ist.

MSEi18n Make

Hier ist der Inhalt des Projektordners nach der Kompilierung.

projet
├── de
│   ├── demo_de.pas
│   ├── libdemo_de.so
│   ├── main.mfm
│   ├── main_mfm.pas
│   ├── main.rsj
│   └── main_rst.pas
├── demo
├── demo.pas
├── demo.prj
├── demo.trd
├── demo.trp
├── fr
│   ├── demo_fr.pas
│   ├── libdemo_fr.so
│   ├── main.mfm
│   ├── main_mfm.pas
│   ├── main.rsj
│   └── main_rst.pas
├── libdemo_de.so
├── libdemo_fr.so
├── main.mfm
├── main_mfm.pas
├── main.pas
├── Makefile
├── MakefileWin
└── out
    ├── main.rsj
    └── … (kompilierte Units)

Es ist Zeit, meine Anwendung fertigzustellen. Also öffne ich mein demo.prj-Projekt in MSEide erneut (falls ich es geschlossen hatte).

Ändern der Anwendungssprache

Die Funktion loadlangunit

Ich erstelle eine Methode für das onexecute-Ereignis der Schaltfläche bt_german.

Im Hauptteil dieser Methode verwende ich die Funktion loadlangunit, um die Sprache zu ändern, mit dem Basisnamen des Moduls als Parameter.

procedure tmainfo.onexecute_bt_german(const sender: TObject);
begin
  loadlangunit('demo_de');
end;

Der Name des Moduls setzt sich aus dem Namen des Projekts (demo), einem Unterstrich und der in der Spalte Language angegebenen Sprache (de) zusammen.

Unter Linux sucht loadlangunit('demo_de') die Bibliothek libdemo_de.so zuerst in den üblichen Bibliotheksverzeichnissen des Systems und dann im Ordner der ausführbaren Datei; unter Windows sucht sie demo_de.dll. Deshalb kopiert MSEi18n die Bibliotheken nach der Kompilierung in den Projektordner: Darum erscheinen libdemo_de.so und libdemo_fr.so in der obigen Baumstruktur zweimal.

Das Gleiche mache ich für Französisch.

procedure tmainfo.onexecute_bt_french(const sender: TObject);
begin
  loadlangunit('demo_fr');
end;

Um die Anwendung wieder auf Englisch zu setzen (die Sprache der in der MFM-Datei enthaltenen Strings), muss ich nur die Funktion loadlangunit mit einem leeren String als Argument aufrufen.

procedure tmainfo.onexecute_bt_english(const sender: TObject);
begin
  loadlangunit('');
end;

Die utf8tostring-Funktion

Bleibt noch der String rs_goodbye vom Typ resourcestring. Ich möchte, dass sich meine Anwendung vom Benutzer in der zuletzt ausgewählten Sprache verabschiedet, wenn dieser das Fenster schließt.

Also füge ich eine Methode für das onclosequery-Ereignis der Klasse tmainfo hinzu.

procedure tmainfo.onclosequery_mainfo(const sender: tcustommseform; var amodalresult: modalresultty);
begin
end;

Im Hauptteil dieser Methode verwende ich die Funktion utf8tostring, um die Übersetzung des Strings rs_goodbye zu erhalten.

Ein resourcestring ist nämlich ein UTF-8-kodierter AnsiString, während MSEgui mit Unicode-Strings arbeitet (der Typ msestring von MSEgui entspricht unicodestring). Die Funktion utf8tostring von Free Pascal wandelt ihn um, damit Sonderzeichen wie ä oder é korrekt angezeigt werden. Deshalb deklariere ich die Variable s vom Typ unicodestring.

procedure tmainfo.onclosequery_mainfo(const sender: tcustommseform; var amodalresult: modalresultty);
var
  s: unicodestring;
begin
  s := utf8tostring(rs_goodbye);
  showmessage(s);
end;

Das ist alles! Jetzt muss ich meine Anwendung nur noch kompilieren und ausprobieren.

Auf Wiedersehen

Wenn Sie möchten, können Sie den Projektquellcode herunterladen.