BeanDev: Plattform Übersetzung als Plugin
Wie ich schon in einem älteren Blog-Eintrag geschrieben hatte, ist es möglich eine Programm-Suite mit einem Branding so zu versehen, dass man eine Übersetzung der Plattform hat.
Bei dem Verfahren gibt es einen bedeutenden Nachteil: Nur per ZIP-Distribution wird die Übersetzung installiert. Der Anwender kann nicht darüber entscheiden, ob er diese Sprache haben will und kann das auch nicht zurücknehmen (außer er löscht die JAR-Dateien aus dem ./locale-Ordner.
Tonny Kohar zeigt in seinem Blog, wie man für eigene Projekte ein Plugin erstellen kann, um eine Sprachvariante installierbar zu machen.
Das beschriebene Build-Script ist aber sehr auf das Projekt zugeschnitten und skizziert nur den Aufbau. Ich habe mich mal der Sache angenommen und ein Build-Script erstellt, dass generell für alle Projekte verwendet werden kann. Außerdem halte ich mich an die Suite-Branding Konvention die lokalisierten Bundle.properties im branding-Ordner (und nicht unter src) zu halten. Das vereinfacht die Integration in das bestehende Build-System von NetBeans.
Wie Tonny auch schon schreibt, reicht es, erst ein normales Modul zu erstellen. Ich gebe dem Modul immer den Namen der Suite mit der Endung -l10n.Ggf. kann man aber auch das Sprachkennzeichen verwenden (z.B. deDE), damit man später unterschieldiche Übersetzungen in getrennten Installationen anbieten kann.
In der Files Ansicht des Explorers lege ich dann den branding-Ordner an. Im Gegensatz zur Suite wird der branding-Ordner in einem Module nicht automatisch vom Build-Script erkannt. Suite-Projekte starten ein speziellen Build-Abschnitt, wenn der branding-Ordner existiert.
Unter dem branding-Ordner werden nun die Abschnitte der Übersetzungen für die Module abgelegt. Core weicht da ein wenig vom Standard ab, aber die Modul-Übersetzungen der Plattform heißen vom Ordner immer wie die zu erzeugenden Übersetzungs-JAR-Dateien:
Unter core und modules werden nun für die Platform-Module die Bundle_xx_XX.properties-Dateien, ein paar Helpset-Dateien und Bildchen eingefügt. Ich hatte schon mal was vorbereitet (allerdings ohne _de_DE-Anhängsel an den Bundle-Dateien): Ein ZIP-Archiv findet sich hier.
Im Prinzip sollte es so aussehen:
Jetzt geht es ans Eingemachte. Das Build-Script muss erweitert werden.
Dafür nun Build.xml öffnen (findet sich am schnellsten in der Projektansicht unter Important Files).
Direkt unter dem ersten import geht es los. Zunächst benötigen wir die Eigenschaften aus dem Suite-Projekt, damit wir den Application-Namen bekommen:
<property file="${suite.dir}/nbproject/project.properties" prefix="prjsuite"/>
Dann erzeugen wir ein kleines Makro, damit die Tipparbeit für die Module nicht ausufert:
<macrodef name="sub-jar">
<attribute name="dep"/>
<attribute name="module" default="modules"/>
<sequential>
<jar jarfile="${locale.dir}/@{dep}_${app.name}.jar" compress="${build.package.compress}">
<fileset dir="branding/@{module}/@{dep}.jar/"/>
</jar>
</sequential>
</macrodef>
Nun hängen wir uns in das Target build-init ein, um zwei Variablen zu füllen:
<target name="build-init" depends="harness.build-init">
<property name="locale.dir" value="${basedir}/build/cluster/modules/locale/"/>
<property name="app.name" value="${prjsuite.app.name}"/>
</target>
Dabei ist locale.dir das Zielverzeichnis für die Übersetzungen und app.name holt sich einfach den Wert aus den Suite-Properties.
Nun hängen wir uns in das jar-Target, erzeugen das locale.dir und basteln schon für das core.jar die erste Übersetzung. Da kann ich das Makro nicht verwenden, weil der Zielname der Übersetzung anders als die JAR-Datei heißen soll:
<target name="jar" depends="projectized-common.jar">
<mkdir dir="${locale.dir}"/>
<!-- Sonderbehandlung für das core-package -->
<jar jarfile="${locale.dir}/org-netbeans-core_${app.name}.jar" compress="${build.package.compress}">
<fileset dir="branding/core/core.jar/"/>
</jar>
Nun folgen die restlichen Übersetzungen aus dem modules-Ordner. Das funktioniert sehr gut mit dem Makro. Hier ein Auszug:
<!-- Lokalisierung für die modules packages -->
<sub-jar dep="org-jdesktop-layout"/>
<sub-jar dep="org-netbeans-api-progress"/>
<sub-jar dep="org-netbeans-api-visual"/>
<sub-jar dep="org-netbeans-core-execution"/>
Als letztes in diesem Target kopiere ich die fertigen Archive in das Suite-Projekt. Das ist nicht unbedingt notwendig, erleichtert aber das Erstellen von ZIP-Distributionen mit fertig übersetzten Archiven:
<!-- Kopieren der JAR-Dateien in das Suite locale Verzeichnis-->
<copy todir="${cluster}/modules/locale/" >
<fileset dir="${locale.dir}">
<exclude name="${module.jar.basename}"/>
</fileset>
</copy>
</target>
Somit ist zumindest die Erstellung der übersetzten Dateien automatisiert in ein extra Modul implementiert. Aber installierbar ist das noch nicht. Ich verlasse mich da ganz auf die Fähigkeiten von Tonny und übernehme sein erweitertes Target nbm:
<target name="nbm" depends="projectized-common.nbm">
<property name="nbm-expand" value="nbm-expand"/>
<!-- 1: NBM Datei extrahieren -->
<unjar src="build/${nbm}" dest="build/${nbm-expand}">
<patternset>
<exclude name="META-INF/**"/>
</patternset>
</unjar>
<!-- 2: Übersetzugen in den passenden Ordner packen -->
<copy todir="build/${nbm-expand}/netbeans/modules/locale/" >
<fileset dir="${cluster}/modules/locale/" />
</copy>
<!-- 3: Nun wieder als JAR zusammensetzen -->
<jar jarfile="build/${nbm}" compress="true">
<fileset dir="build/${nbm-expand}" />
</jar>
<!-- 4: Signieren, wenn gewünscht -->
<antcall target="sign-nbm" />
</target>
Für das optionale Signieren fehlt noch:
<target name="sign-nbm" if="keystore">
<signjar jar="build/${nbm}" keystore="${keystore}" storepass="${storepass}" alias="${nbm_alias}" />
</target>
Und das war es auch schon!
Das Modul kann nun ganz normal im Update-Center publiziert werden. Es können weitere Sprachen hinzugefügt werden. Nur funktioniert es nicht, dass man mehrere Module mit unterschiedlichen Sprachen installieren kann. Dazu müsste man das Makro umprogrammieren und dort ein Lokalisierungskennzeichen (z.B. _deDE) hinzufügen:
<jar jarfile="${locale.dir}/@{dep}_${app.name}_deDE.jar" compress="${build.package.compress}">
<fileset dir="branding/@{module}/@{dep}.jar/"/>
</jar>
Vielleicht kann man sich dazu auch ein Symbol in den project.properties anlegen. Man darf nur die Sonderbehandlung von core.jar nicht vergessen!
Hier noch mal das komplette Build.xml Script, wo alle Module der NetBeans-Plaform übersetzt werden.
Beste Grüße,
Josch.
Da werden Sie geholfen:
Das deutsche NetBeans Forum
![Validate my RSS feed [Valid RSS]](http://www.sepix.de/fileadmin/valid-rss.png)
Dienstag, 23-12-08 10:13
This blog Is very informative , I am really pleased to post my comment on this blog . It helped me with ocean of knowledge so I really belive you will do much better in the future . Good job web master .