XUL Einführung:Lokalisierung
Aus MDC
XUL und XML stellen Entities als komfortablen Weg bereit Lokalisierungen zu ermöglichen.
Inhaltsverzeichnis |
[bearbeiten] Entities
Viele Anwendungen sind so gebaut, dass das Interface in verschiedene Sprachen zu übersetzten so einfach wie möglich ist. Üblicherweise wird eine Tabelle aus Strings für jede Sprache erstellt. Anstelle von den Text direkt in die Applikation zu programmieren, stellt jede Textstelle nur eine Referenz zur Stringtabelle dar. XML stellt Entities zur Verfügung, welche für den gleichen Zweck verwendet werden können.
Du solltest mit Entities bereits vertraut sein, wenn du schon HTML geschrieben hast. Der Code < und > sind Beispiele von Entities, welche anstelle von grösser als und kleiner als Zeichen im Text verwendet werden können. XML besitzt einen Syntax, welcher dir das deklarieren eigener Entities erlaubt. Du kannst diese so verwenden, dass das Entity durch seinen Wert ersetzt wird, welcher ein Textstring ist. Entities können immer wenn Text auftritt verwendet werden, inklusive den Attributwerten. Das Beispiel unten demonstriert die Verwendung eines Entity in einem Button.
<button label="&findLabel;"/>
Der Text der als Label erscheinen wird, wird den Wert des Entity &findLabel; sein. Eine Datei welche die Entity-Deklaration enthält wird für jede unterstützte Sprache erstellt. In Englisch, das &findLabel; Entity wird wahrscheinlich mit dem Text "Find" deklariert sein.
[bearbeiten] DTD-Dateien
Entities sind in Document Type Declaration (DTD) Dateien deklariert. Dateien dieses Typs werden normalerweise verwendet um den Syntax und die Semantik einer bestimmten XML-Datei zu deklarieren, aber sie lassen dich auch Entities deklarieren. Im Mozilla Chrome-System wirst du die DTD Dateien im locales Unterordner finden. Normalerweise existiert eine DTD Datei (mit der Endung .dtd) pro XUL-Datei.
Wenn du in den Chrome-Ordner schaust, solltest du ein Archiv für deine Sprache (de-De.jar ist das normale für Deutsch) finden. Es ist möglich lokale Datein in verschiedenen Sprachen, z.B. Deutsch (de-DE) und Englisch (en-US) zu haben. Innerhalb dieser Archive sind die Dateien zu finden, welche den lokalisierten Text für jedes Fenster enthalten. Die Struktur der Archive ist sehr ähnlich derjenigen, die für Skins verwendet wird.
Im Innern der Archive würdest du die DTD-Dateien platzieren in welchen du die Entities deklarierst. Normalerweise wirst du für jede XUL-Datei eine DTD-Datei mit dem gleichen Namen aber einer .dtd Endung haben. Daher für den Dateisuchdialog werden wir eine Datei namens findfile.dtd benötigen.
Für nicht installierte chrome Dateien kannst du einfach die DTD-Datei ins selbe Verzeichnis wie die XUL-Datei ablegen.
Sobald du eine DTD-Datei für dein XUL erstellt hast, wirst du eine Zeile in die XUL-Datei einfügen müssen, welche angibt, dass du die DTD-Datei verwenden willst. Andernfalls werden Fehler auftreten, weil die Entities nicht gefunden werden. Um dies zu tun, füge die folgende Zeile irgendwo im oberen Bereich der XUL-Datei ein:
<!DOCTYPE window SYSTEM "chrome://findfile/locale/findfile.dtd">
Diese Zeile spezifiziert, dass die URL auf eine DTD-Datei verweist. In diesem Fall haben wir deklariert, dass wir die findfile.dtd DTD-Datei verwenden wollen. Diese Zeile ist typischerweise gerade vor dem window Element plaziert.
[bearbeiten] Entities deklarieren
Die Entities werden mit einem einfachen Syntax deklariert:
<!ENTITY findLabel "Find">
Dieses Beispiel erstellt ein Entity mit dem Namen findLabel und dem Wert "Find". Dies bedeutet, dass überall wo der Text "&findLabel;" in der XUL-Datei auftritt es durch den Text "Find" ersetzt wird. Beachte dass die Deklaration kein Slash am Ende besitzt. In der DTD-Datei einer anderen Sprache wird der Text stattdessen in dieser Sprache geschrieben.
in Japanisch: <!ENTITY findLabel "検索">
Zum Beispiel der folgende Text:
<description value="&findLabel;"/>
wird übersetzt als:
Englische Version: <description value="Find"/> Japanische Version: <description value="検索"/>
Du wird ein Entity für jede Beschriftung und Textstelle haben, den du in deinem Interface verwendest. Du solltest keinen direkt angezeigten Text in den XUL-Datein haben.
Zusätzlich zu der Verwendung in Beschriftungen, sollten Entities für jeden Wert verwendet werden, welcher in einer anderen Sprache abweichen könnte. Access-Keys und Tastatur-Shortcuts zum Beispiel.
XUL <menuitem label="&undo.label;" accesskey="&undo.key;"/> DTD <!ENTITY undo.label "Undo"> <!ENTITY undo.key "u">
Das Beispiel oben verwendet zwei Entities, eines für die Beschriftung des Menüpunktes und ein zweiter für den Access-Key.
[bearbeiten] Änderung des Dateisuche Beispiels
Lass uns nun anschauen, wie wir das alles zusammenfügen können, indem wir den Dateisuchedialog so modifizieren, so dass eine DTD-Datei für alle seine Textstellen verwendet wird. Die gesamte XUL-Datei mit allen Änderungen in Rot ist unterhalb gezeigt.
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<?xml-stylesheet href="findfile.css" type="text/css"?>
<!DOCTYPE window SYSTEM "chrome://findfile/locale/findfile.dtd">
<window
id="findfile-window"
title="&findWindow.title;"
persist="screenX screenY width height"
orient="horizontal"
onload="initSearchList()"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script src="findfile.js"/>
<popupset>
<popup id="editpopup">
<menuitem label="Cut" accesskey="&cutCmd.accesskey;"/>
<menuitem label="Copy" accesskey="©Cmd.accesskey;"/>
<menuitem label="Paste" accesskey="&pasteCmd.accesskey;" disabled="true"/>
</popup>
</popupset>
<keyset>
<key id="cut_cmd" modifiers="accel" key="&cutCmd.commandkey;"/>
<key id="copy_cmd" modifiers="accel" key="©Cmd.commandkey;"/>
<key id="paste_cmd" modifiers="accel" key="&pasteCmd.commandkey;"/>
<key id="close_cmd" keycode="VK_ESCAPE" oncommand="window.close();"/>
</keyset>
<vbox flex="1">
<toolbox>
<menubar id="findfiles-menubar">
<menu id="file-menu" label="&fileMenu.label;"
accesskey="&fileMenu.accesskey;">
<menupopup id="file-popup">
<menuitem label="&openCmd.label;"
accesskey="&openCmd.accesskey;"/>
<menuitem label="&saveCmd.label;"
accesskey="&saveCmd.accesskey;"/>
<menuseparator/>
<menuitem label="&closeCmd.label;"
accesskey="&closeCmd.accesskey;" key="close_cmd" oncommand="window.close();"/>
</menupopup>
</menu>
<menu id="edit-menu" label="&editMenu.label;"
accesskey="&editMenu.accesskey;">
<menupopup id="edit-popup">
<menuitem label="&cutCmd.label;"
accesskey="&cutCmd.accesskey;" key="cut_cmd"/>
<menuitem label="©Cmd.label;"
accesskey="©Cmd.accesskey;" key="copy_cmd"/>
<menuitem label="&pasteCmd.label;"
accesskey="&pasteCmd.accesskey;" key="paste_cmd" disabled="true"/>
</menupopup>
</menu>
</menubar>
<toolbar id="findfiles-toolbar">
<toolbarbutton id="opensearch" label="&openCmdToolbar.label;"/>
<toolbarbutton id="savesearch" label="&saveCmdToolbar.label;"/>
</toolbar>
</toolbox>
<tabbox>
<tabs>
<tab label="&searchTab;" selected="true"/>
<tab label="&optionsTab;"/>
</tabs>
<tabpanels>
<tabpanel id="searchpanel" orient="vertical" context="editpopup">
<description>
&findDescription;
</description>
<spacer class="titlespace"/>
<groupbox orient="horizontal">
<caption label="&findCriteria;"/>
<menulist id="searchtype">
<menupopup>
<menuitem label="&type.name;"/>
<menuitem label="&type.size;"/>
<menuitem label="&type.date;"/>
</menupopup>
</menulist>
<spacer class="springspace"/>
<menulist id="searchmode">
<menupopup>
<menuitem label="&mode.is;"/>
<menuitem label="&mode.isnot;"/>
</menupopup>
</menulist>
<spacer class="springspace"/>
<menulist id="find-text" flex="1"
editable="true"
datasources="file:///mozilla/recents.rdf"
ref="http://www.xulplanet.com/rdf/recent/all">
<template>
<menupopup>
<menuitem label="rdf:http://www.xulplanet.com/rdf/recent#Label" uri="rdf:*"/>
</menupopup>
</template>
</menulist>
</groupbox>
</tabpanel>
<tabpanel id="optionspanel" orient="vertical">
<checkbox id="casecheck" label="&casesensitive;"/>
<checkbox id="wordscheck" label="&matchfilename;"/>
</tabpanel>
</tabpanels>
</tabbox>
<tree id="results" style="display: none;" flex="1">
<treecols>
<treecol id="name" label="&results.filename;" flex="1"/>
<treecol id="location" label="&results.location;" flex="2"/>
<treecol id="size" label="&results.size;" flex="1"/>
</treecols>
<treechildren>
<treeitem>
<treerow>
<treecell label="mozilla"/>
<treecell label="/usr/local"/>
<treecell label="&bytes.before;2520&bytes.after;"/>
</treerow>
</treeitem>
</treechildren>
</tree>
<splitter id="splitbar" resizeafter="grow" style="display: none;"/>
<spacer class="titlespace"/>
<hbox>
<progressmeter id="progmeter" value="50%" style="display: none;"/>
<spacer flex="1"/>
<button id="find-button" label="&button.find;"
oncommand="doFind()"/>
<button id="cancel-button" label="&button.cancel;"
oncommand="window.close();"/>
</hbox>
</vbox>
</window>
Jede Textstelle wurde durch eine Entity ersetzt. Eine DTD-Datei wurde nahe am Anfang eingefügt. Jede Entity welche eingefügt wurde, sollte in der DTD-Datei deklariert sein. Das Fenster wird nicht angezeigt, wenn eine Entity in der XUL-Datei gefunden wird, welche nicht deklariert wurde.
Beachte dass der Name der Entity nicht wichtig ist. Im Beispiel oben wurden die Wörter der Entities mit Bindestrichen getrennt. Dies ist keine Vorgabe. Die Entity-Namen folgen den selben Konventionen wie der Rest des Mozilla Codes.
Du hast vielleicht bemerkt, dass der Text '2520 bytes' durch zwei Entities ersetzt wurde. Dies ist, weil die Struktur in anderen Sprachen variieren kann. Z.B. könnte es nötig sein, dass die Einheit vor der Zahl steht.
Die Access-Keys und Tastatur-Shortcuts wurden auch in Entities übersetzt, weil sie in anderen Sprachen abweichen können.
Nun die DTD-Datei - findfile.dtd:
<!ENTITY findWindow.title "Find Files">
<!ENTITY fileMenu.label "File">
<!ENTITY editMenu.label "Edit">
<!ENTITY fileMenu.accesskey "f">
<!ENTITY editMenu.accesskey "e">
<!ENTITY openCmd.label "Open Search...">
<!ENTITY saveCmd.label "Save Search...">
<!ENTITY closeCmd.label "Close">
<!ENTITY openCmd.accesskey "o">
<!ENTITY saveCmd.accesskey "s">
<!ENTITY closeCmd.accesskey "c">
<!ENTITY cutCmd.label "Cut">
<!ENTITY copyCmd.label "Copy">
<!ENTITY pasteCmd.label "Paste">
<!ENTITY cutCmd.accesskey "t">
<!ENTITY copyCmd.accesskey "c">
<!ENTITY pasteCmd.accesskey "p">
<!ENTITY cutCmd.commandkey "X">
<!ENTITY copyCmd.commandkey "C">
<!ENTITY pasteCmd.commandkey "V">
<!ENTITY openCmdToolbar.label "Open">
<!ENTITY saveCmdToolbar.label "Save">
<!ENTITY searchTab "Search">
<!ENTITY optionsTab "Options">
<!ENTITY findDescription "Enter your search criteria below and select the Find button to begin the search.">
<!ENTITY findCriteria "Search Criteria">
<!ENTITY type.name "Name">
<!ENTITY type.size "Size">
<!ENTITY type.date "Date Modified">
<!ENTITY mode.is "Is">
<!ENTITY mode.isnot "Is Not">
<!ENTITY casesensitive "Case Sensitive Search">
<!ENTITY matchfilename "Match Entire Filename">
<!ENTITY results.filename "Filename">
<!ENTITY results.location "Location">
<!ENTITY results.size "Size">
<!ENTITY bytes.before "">
<!ENTITY bytes.after "bytes">
<!ENTITY button.find "Find">
<!ENTITY button.cancel "Cancel">
Um den Text in einer neuen Sprache hinzuzufügen genügt es eine weitere DTD-Datei zu erstellen. Durch die Verwendung des Chrome Systems um die DTD-Datei einer anderen Sprache hinzuzufügen, kann die selbe XUL-Datei für jede Sprache verwendet werden.
Das Dateisuche Beispiel so weit: http://developer.mozilla.org/samples/xultu/examples//findfile/findfile-locale.xul.txt
Als nächstes werden wir Property Files anschauen.
Siehe auch: http://developer.mozilla.org/en/docs/XUL_Tutorial:Creating_a_Skin