Lokalizacja

XUL i XML dostarczają encje, które są wygodnym sposobem stosowanym w plikach lokalizacji.

Encje

Wiele aplikacji jest budowana w sposób określony i umożliwiający łatwe przetłumaczenie interfejsu aplikacji na inny język. Zazwyczaj, tabele wraz ze stringami są tworzone dla każdego języka. Zamiast trudnego tekstu kodu, w każdej części tekstu aplikacji, jest referencja do tabeli typu string. XML dostarcza encje, które możemy zastosować dla wspomnianego celu.

Powinieneś już dobrze znać encje, jeśli piszesz w HTML. Kody &lt; i &gt; są przykładami encji, które możemy użyć w miejsce znaku mniejszości (<) lub większości (>), zamiast jego formy w postaci tekstowej. Składnia języka XML, pozwala nam na deklaracje własnych encji. Możemy ich użyć, w taki sposób, że encja jest zamieniana z tą wartością, która jest prostym tekstem. Encje możemy używać zawsze, kiedy są tekstem, który zawiera wartość atrybutów. Przykład poniżej demonstruje użycie encji w przycisku.

<button label="&findLabel;"/>

Tekst, który pojawi się jako etykieta (label), będzie wyświetlała wartość, jaka jest zawarta w encji &findLabel. Plik jest tworzony z powstrzymanej encji zadeklarowanej dla każdego obsługiwanego języka. W języku angielskim zadeklarowanej encji &findLabel będzie przydzielony tekst Znajdź.

Pliki DTD

Encje są zadeklarowane w plikach DTD ( Document Type Declaration ). Zazwyczaj tego typu pliki są używane do deklaracji składni i semantyki poszczególnych plików XML, lecz także umożliwiają deklarację encji. W Mozilli w systemie chrome, możesz zmaleźć pliki DTD są umieszczone w podkatalogu <tt>locales</tt>. Normalnie będzie tam jeden plik DTD (z rozszerzeniem <tt>.dtd</tt>) na jeden plik XUL.

Jeśli widzisz katalog chrome, powinieneś się przyjrzeć archiwum w Twoim języku (en-US.jar jest domyślnym językiem dla angielskiego). Mamy pliki lokalizacji w kilku językach (jak w przykładzie) m.in. w angielskim (en-US) i francuskim (fr). Wewnątrz tych archiwów, będą się znajdowały pliki, które trzymają zlokalizowany tekst dla każdego okna. Struktura archiwów jest bardzo podobna do struktury katalogów dla motywu.

Wewnątrz archiwów, połóż swój plik DTD, w którym zadeklarujesz encje. Zazwyczaj tworzymy jeden plik DTD dla każdego pliku XUL. Posiadają one taką samą nazwę pliku, jedynie rozszerzenie pliku jest inne (.dtd), czyli w naszym przykładowym oknie Znajdź pliki, będzie potrzebny plik o nazwie findfile.dtd.

Dla plików nieinstalowanych w chrome, możemy tylko umieścić plik DTD do tego samego katalogu co plik XUL.

Raz możesz utworzyć plik DTD dla twojego XUL, będziesz potrzebował dodać do plik XUL, który sygnalizuje, co chcesz do użycia pliku DTD. W przeciwnym razie błędy będą się zdarzać jako, że nie można znaleźć encji. Zrób to, dodaj linię pochodzącą z najbliższego miejsca pliku XUL:

<!DOCTYPE window SYSTEM "chrome://findfile/locale/findfile.dtd">

Linia określa, co mamy zasygnalizować w użyciu DTD dla pliku. W tym przypadku, deklarujemy co chcemy użyć w pliku DTD findfile.dtd. Linię tą umieszczamy zawsze za elementem window.

Deklaracja encji

Encję możemy zadeklarować przy użyciu prostej składni, przykład znajduje się poniżej:

<!ENTITY findLabel "Znajdź">

Przykład tworzy encję o nazwie findLabel i wartości Znajdź. Oznacza to, że gdziekolwiek zawarty zostanie tekst &findLabel w pliku XUL, to będzie on zastąpiony tekstem Znajdź. W pliku DTD dla innych wersji językowych, możemy określić wpis w naszym języku, co pozwoli na użycie go zamiast tu zdefiniowanego. Uwaga, jest to deklaracja encji, w której nie ma kończącego znaku slash.

Na przykład, następny tekst:

<description value="&findLabel;"/>

Jest tłumaczony jako:

<description value="Znajdź"/>

Możesz zadeklarować encje dla każdej etykiety (label) lub łańcucha znakowego, które zostaną zadeklarowane w Twoim interfejsie. Powinieneś nie mieć bezpośrednio wyświetlonego tekstu w pliku XUL dla wszystkich.

Nadając encji użycie tekstu etykiety, powinieneś użyć dla niej wartość, która byłaby inna w innym języku. Przykład kluczy dostępu i skrótów klawiaturowych.

 XUL
 <menuitem label="&undo.label;" accesskey="&undo.key;"/>
 DTD
 <!ENTITY undo.label "Undo">
 <!ENTITY undo.key "u">

W przykładzie powyżej użyto dwóch encji, jednej dla etykiety 'Undo' dla pozycji znajdującej się w menu i drugiej dla klucza dostępu.

Zmieniamy przykład "Znajdź pliki"

Zastanówmy się w jaki sposób możemy wszystko ułożyć w oknie dialogowym Znajdź pliki, tak aby został zastosowany plik DTD dla wszystkich łańcuchów znakowych. Encje w pliku XUL są pokazane poniżej w kolorze czerwonym.

<?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>
   <menupopup id="editpopup">
     <menuitem label="&cutCmd.label;" accesskey="&cutCmd.accesskey;"/>
     <menuitem label="&copyCmd.label;" accesskey="&copyCmd.accesskey;"/>
     <menuitem label="&pasteCmd.label;" accesskey="&pasteCmd.accesskey;" disabled="true"/>
   </menupopup>
</popupset>

<keyset>
   <key id="cut_cmd" modifiers="accel" key="&cutCmd.commandkey;"/>
   <key id="copy_cmd" modifiers="accel" key="&copyCmd.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="&copyCmd.label;"
                  accesskey="&copyCmd.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>

Każdy łańcuch tekstowy został zastąpiony poprzez odwołanie się do odpowiedniej encji. Plik DTD został umieszczony zaraz na początku pliku XUL. Każdą encję, którą dodamy, powinniśmy zadeklarować w pliku DTD. Okno nie powinno zostać wyświetlone, jeśli encja będzie umieszczona w pliku XUL, a nie została zadeklarowana.

Uwaga: nazwa encji nie jest ważna. W przykładzie powyżej, słowa w encjach zostały oddzielone kropką. Nie musimy tego robić. Nazwy encji tutaj, są podobne do przyjętej konwencji kodu jakiej używa Mozilla.

Zwróć uwagę, że tekst o rozmiarze '2520 bajtów' zastąpiliśmy poprzez dwie encje. Dzieje się tak, ponieważ struktura wyrażenia może być inna w następnym miejscu. Na przykład, numer może potrzebować stać się równoważnym ilości bajtów, przed zamiast po. Oczywiście może to być bardziej skomplikowane do zrealizowania, aby wyświetlać rozmiar w KB lub potrzebne bardziej będą już Ci MB.

Klucze dostępu, jak i skróty klawiaturowe także będziemy tłumaczyli jako encje, ponieważ będą one prawdopodobnie inne oraz w innych miejscach będą się znajdowały.

Następnie, plik DTD (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">

Wszystko czego potrzeba do zmiany wersji językowej, to utworzenie następnego pliku DTD. Używając systemu chrome dodaj plik DTD dla innych lokalizacji, ten sam plik możemy zastosować w każdym języku.

Przykład Znajdź pliki: Źródła

W następnym artykule, zobaczymy jak wyglądają pliki własności.

 

 

Autorzy i etykiety dokumentu

 Autorzy tej strony: fscholz, teoli, Ptak82, Mgjbot, Marcoos, Minh Nguyen
 Ostatnia aktualizacja: fscholz,