Wir haben unser Lastenheft somit erfolgreich abgearbeitet, und können uns nach der Absolvierung der Pflicht nun der Kür zuwenden.
Unsere Redakteure schreien nun nach dem Komfort der Imperia-Flexmodule, an die sie sich in der Zeit vor der Mehrsprachigkeit unserer Site gewöhnt hatten. Vor der Verwendung von Flex-Modulen mit Copy-Seiten gilt es jedoch einige Hürden zu überspringen. Enthält ein Flex-Modul zum Beispiel eine Variable longtext zur Aufnahme von Fließtext, muss Imperia in der Lage sein, den Variableninhalt auch dann noch zu unterscheiden, wenn dieses Flex-Modul mehrfach eingefügt wurde. Dies wird dadurch erreicht, dass diese Variablen intern um eine Nummerierung erweitert werden, die wieder eine eindeutige Unterscheidbarkeit zwischen den einzelnen Instanzen erlaubt.
Diese interne Nummerierung gerät natürlich durcheinander, wenn Flexmodulaufrufe plötzlich verschwinden oder hinzukommen, und genau dies ist in Multi-Language-Szenarien regelmäßig der Fall. Erstellen wir eines unserer Dokumente beispielsweise in Englisch und Französisch, werden die englischen Flex-Inhalte in der Editier-Ansicht den Index 0 haben, während die französischen Flex-Inhalte mit 1 indiziert werden.
Bei der Publizierung und in der Voransicht werden dagegen stets alle Sprachen bis auf eine ausgeblendet, somit auch die Flex-Aufrufe im Template. Für jede Sprache würde daher auf die Flex-Inhalte mit dem Index 0 zurückgegriffen, was aber leider nur für die erste Sprache in der Liste zum gewünschten Ergebnis führt. In diesen Fällen dürfen wir uns daher nicht mehr auf die automatische Zählung verlassen, sondern müssen dem Imperia-Template-Prozessor durch die Angabe eines expliziten Index auf die Sprünge helfen. Die Index-Vergabe sollte sich während der gesamten Lebendauer der Site natürlich niemals ändern, weshalb wir uns dazu entschließen, zu diesem Zweck eine zentrale Liste zu führen, die für neue Sprachen dann nach oben erweitert werden kann.
Wir geben uns ans Werk, und fügen in unser Code-Include multilang.htms am Ende einen Flexmodul-Aufruf ein:
<!--INSERT_FLEXMODULE:INDEX=<!--CI_PARAM2-->-->
Wir sehen, dass wir unserem Code-Include einen weiteren Parameter (<!--CI_PARAM2-->) für die Flex-Zählung übergeben müssen. Dementsprechend müssen wir natürlich auch den Aufruf im anderen Include-File multilang_setup.pl abändern:
use constant LANGNUMBERS => { en => 0, fr => 1, de => 2, it => 3, }; my @linguas = $metainfo->getValues ('linguas'); # ... foreach my $lingua (@linguas) { my $lang_number = LANGNUMBERS->{$lingua};
$new .= <<EOF; <!--CODEINCLUDE:multilang.htms:PARAMETERS=$lingua/$lang_number--> EOF }
![]() | Auch hier benötigen wir eine hartkodierte Liste der Sprachkürzel, um eine Abbildung von Sprachkürzeln auf die jeweils verwendeten Flex-Indizes zu erhalten. |
![]() | Den jeweils ermittelten Index übergeben wir nun als zusätzlichen Parameter an das Code-Include (Parameter werden durch Slashes getrennt). |
Unser Konzept trägt sich also auch noch bei Verwendung von Flex-Modulen.
Die Verwendung von Flex-Modulen birgt eine weitere Schwierigkeiten im Zusammenhang mit Multi-Language-Seiten. Nehmen wir an, dass in der englischen Redaktion ein komplizierter Aufbau der englischen Seite mit Flex-Modulen erfolgte, und die anderen Sprachredaktionen jetzt vor dem Problem stehen, überhaupt erst einmal diesen Aufbau (inklusive der Parameter, die bei der Ausführung des Flex-Moduls gesetzt wurden) zu reproduzieren, bevor an eine Übersetzung des Contents zu denken ist.
Der Flex-Flexxer ist ein sehr junges Feature des Imperia-Template-Prozessors, das hier Abhilfe schaffen kann. Fügen wir zunächst einmal den entsprechenden Aufruf in unser Template (besser gesagt unser Code-Include) multilang.htms ein:
<!--INSERT_FLEX_FLEXXER--> <!--INSERT_FLEXMODULE:INDEX=<!--CI_PARAM2-->:LABEL=flex_<!--CI_PARAM1-->-->
Rufen wir jetzt ein Dokument im Editier-Modus auf, stellen wir eine kleine Veränderung fest:

Der Flex-Flexxer in der Editieransicht
Die kleine Veränderung zuerst: Die Flex-Modul-Box enthält links oben plöztlich die Beschriftung „flex_fr“. Wenn wir uns noch einmal den Flex-Modul-Aufruf genauer anschauen, stellen wir fest, dass dies exakt dem zusätzlichen Parameter LABEL entspricht, den wir übergeben haben. Natürlich dürfen hier auch anwenderfreundlichere Namen verwendet werden.
Weiterhin fällt natürlich das Icon auf, dass der Template-Prozessor an der Stelle des Flex-Flexxer-Aufrufs eingefügt hat. Klicken wir auf das Icon, öffnet sich ein neues Fenster:

Erweiterte Flex-Aktionen durch den Flex-Flexxer
Die Bedienung des Flex-Flexxers dürfte relativ selbsterklärend sein. Es lassen sich komplette Flex-Modul-Sets (inklusive der Parameter und des Contents) kopieren, verschieben und löschen. Redakteure sind dadurch in der Lage, Flex-Module-Aufbauten aus anderen Sprachversionen als Grundlage der eigenen Version zu verwenden. Näheres kann dem Imperia-Programmierhandbuch entnommen werden.
Die folgende Technik, mit der die Pflege mehrsprachiger Seiten in Imperia noch komfortabler wird, beruht auf einer Idee des Imperia-Partners Seitenbau (http://www.seitenbau.com/). Bislang liegen die einzelnen Sprachversionen in der Editieransicht vertikal untereinander, was gerade bei größeren Dokumenten mit vielen Sprachen sehr leicht zur Unübersichtlichkeit führt. Durch den Einsatz von DHTML lässt sich der Komfort hier stark verbessern. Die Idee von Seitenbau sieht vor, die Content-Pflege-Masken für die einzelnen Sprachen jeweils auf Layer zu verteilen, die über ein Menü am oberen Seitenrand angesteuert werden können, sprich, die Layer werden durch die Anwahl der entsprechenden Menüpunkte sichtbar bzw. unsichtbar gemacht.
Die Vorteile dieser Technik werden wir gleich in vivo kennenlernen. Die Nachteile wollen wir aber natürlich auch nicht verschweigen:
Der Gewinn an Usability wird die erwähnten Nachteile in aller Regel leicht aufwiegen. Dennoch sollte jeder Punkt natürlich genau geprüft werden, bevor der zusätzliche Aufwand bei der Template-Programmierung in Kauf genommen wird.
Im Folgenden wollen wir eine solche Lösung skizzenhaft darstellen. Da dieses Dokument keine Anleitung zur browserunabhängigen DHTML-Programmierung sein will, wird eine Lösung dargestellt, die mit modernen Browsern (Mozilla 1.x, Internet Explorer 6.x, etc.) funktionieren wird, aber natürlich erheblicher Verfeinerungen bedarf, wenn die zu unterstützende Browser-Palette weiter gefasst wird.
Die im Code-Include multilang.htms realisierten Eingabemasken für den Content müssen zunächst in Layer verpackt werden:
#IF ("<!--XX-editmode-->")
<div class="multi" id="div<!--CI_PARAM1-->">
#ENDIF
... Normaler Template-Code ...
#IF ("<!--XX-editmode-->")
</div>
#ENDIF
Unsere DHTML-Spielereien dienen lediglich der Verbesserung des Redaktionsinterfaces, und sollten demnach nur im Edit-Modus des Template-Prozessors aktiviert sein. Dies gilt durchgehend auch für alle weiteren Modifikationen, die ebenfalls durch Abfragen auf den Edit-Modus geschützt werden sollten, um die publizierten Seiten nicht unnötig aufzublähen.
Eine eindeutige ID des Layers gewinnen wir aus dem Sprachkürzel, das als Parameter an unser Code-Include übergeben wird. Aus Gründen der Browserkompatibilität sollte die ID keinen Unterstrich enthalten!
Der notwendige CSS- und JavaScript-Code ist sprachunabhängig und wird deshalb im Master-Template eingefügt. Wir ändern also die Datei templatemultilang.htms ab, und fügen folgenden Code innerhalb des HTML-head-Elements ein:
#IF ("<!--XX-editmode-->")
<style type="text/css">
div.multi {
position: absolute;
left:10px;
top: 60px;
visibility: hidden;
}
</style>
<script language="Javascript">
function show_layer (id)
{
id = 'div' + id;
var all_layers = document.getElementsByTagName ('div');
for (i = 0; i < all_layers.length; ++i) {
var the_class = all_layers[i].className;
if (the_class == null || the_class != 'multi')
continue;
var the_layer = all_layers[i];
the_layer.style.visibility = 'hidden';
}
var el = document.getElementById (id);
el.style.visibility = 'visible';
}
</script>
#ENDIF
Bei der Positionierung der Layer wird man eventuell etwas mit der vertikalen Lage herumexperimentieren müssen. Der gewählte Wert von 60 Pixeln sollte in Ordnung sein. Wird allerdings festgestellt, dass die Editierlayer die Imperia-Steuerelemente (insbesondere die Buttons für Speichern, Abbruch und Voransicht) überdecken, muss die Position verschoben werden, bis wieder eine einwandfreie Bedienbarkeit erreicht ist.
Das CSS-Attribut visibility ist zunächst für alle Layer auf hidden gesetzt, was für die Redakteure lästig und schwer zu durchschauen ist. Nachdem die Layer über die Code-Include-Kaskade eingebunden wurden, fügen wir am Ende des Templates daher nochmals ein wenig JavaScript ein, um sicherzustellen, dass stets ein Editierlayer sichtbar ist:
#IF ("<!--XX-editmode-->")
<script language="Javascript">
show_layer ('<!--XX-linguas-->');
</script>
#ENDIF
Die oben definierte JavaScript-Funktion show_layer erwartet als Argument ein Sprachkürzel, so wie sie in der Meta-Variablen linguas (als Liste!) abgelegt sind. Was wird hier nun aber vom Template-Prozessor eingefügt, wenn die Listen-Variable mit der bekannten XX-Syntax expandiert wird? Aus Kompatibilitätsgründen zu früheren Imperia-Versionen werden diese Variablen bei der XX-Expansion im Template im skalaren Kontext interpretiert, und statt der kompletten Liste wird das erste Element der Liste eingefügt. Da unser Workflow-Plug-In sicherstellt, dass die Liste linguas niemals leer ist, wird hier also immer der zuerst definierte Layer in den Vordergrund geholt.
An dieser Stelle wird man das System später sicher aufbohren müssen, da die Redakteure sehr bald bemängeln werden, dass sie nach jeder Aktion bei der ersten Sprache landen, und die gewünschte Sprache erst umständlich nach oben holen müssen. Die Behebung dieses Mangels ist eine reine Fleißangelegenheit: Man speichert die ID des aktuellen Layers in der JavaScript-Funktion show_layer in einer versteckten Formularvariable, und holt am Anfang diesen Layer in den Vordergrund. Imperia wird die Formularvariable - wie alle CGI-Variablen - als Metavariable abspeichern und persistent machen, so dass sich das System auch nach dem Speichern der Seite den zuletzt aktiven Layer „merkt“.
Es fehlt noch das „Menü“ für die Umschaltung zwischen den Layern. Auch dieser Teil ist sprachunabhängig, aber da wir hier noch einmal etwas Perl-Code benötigen, setzen wir ihn nicht ins Template, sondern in unser Steuer-Include-File multilang_setup.pl. Den Anfang der Datei ändern wir dazu folgendermaßen:
my @linguas = $metainfo->getValues ('linguas');
use Locale::Language;
if ('EDIT' eq $mode) {
foreach my $lingua (@linguas) {
my $full_language = Locale::Language::code2language ($lingua);
$full_language = $lingua unless defined $full_language;
$new .= <<EOF;
<a href="javascript:show_layer ('$lingua');">$full_language</a>
EOF
}
}
Das Perl-Modul Locale::Language gehört nicht zum Perl-Core wird aber mit Imperia zusammen ausgeliefert. Es erlaubt eine Zuordnung der von uns benutzten Sprachkürzel zu (englischen!) Sprachnamen, die wir für die Beschriftung unseres Menüs verwenden.
In der Praxis wird man sicher auf schönere Darstellungen für das Menü, z. B. durch die Verwendung von Länderfähnchen verfallen. Auch hier wird man sicherlich die Konvention mit den Sprachkürzeln zu schätzen wissen, und mit geringem Aufwand Bildlinks einfügen können.
| Guido Flohr | Imperia AG | Impressum |