CEO and founder of Lingohub. Envisioning a multilingual digital world. Email me if you have questions about how Lingohub can help you take your products global.

HelmutDamen Jacke Damenjacke Fjäll Räven Mantel Trenchcoat UVSzqpM Industry Updates 3 Comments

Wenn ein Programm in mehreren Ländern auf den Markt gebracht werden soll, wird schon bei der Programmierung darauf geachtet, dass alle Ausgaben an den Benutzer nicht fest einprogrammiert sind, sondern dynamisch ausgetauscht werden können. Dieser Vorgang heißt “Internationalisierung” (i18n). Meist werden dann alle Texte, die der Benutzer zu sehen bekommt, Übersetzern zur “Lokalisierung” (l10n) in die jeweilige Sprache übergeben. Wenn Grafiken nicht nur Abbildungen oder Icons enthalten, sondern auch Texte oder Inhalte, die in bestimmten Kulturen anders (oder gar nicht) dargestellt werden, müssen auch Sie durch durch Abfrage der “Locale” (System-Sprache/Region, z.B. “de-DE”) oder Benutzereinstellungen austauschbar sein. Das gilt natürlich auch für Sound- und Videoausgaben. In diesem Gastbeitrag geht es um die Tücken bei der i18n und l10n von Strings (Texten).

©2014 CC-BY-SA 3.0 DE Christopher Köbel

Entscheider oder Entwickler, die ihr Programm nicht nur in einem Land vermarkten wollen, sorgen frühzeitig vor. Die Zeiten, in denen zuerst eine Heimatversion mit im Programmcode integrierten “internen Strings” (auch: “hard-coded”) erstellt wurde, die dann durch das Ändern des Quellcodes für jedes Land angepasst werden musste, sind glücklicherweise vorbei. Heute werden “externe Strings” verwendet, die in “Ressourcen” lagern, z.B. den “Message Object”-Dateien (.mo) des verbreiteten GNU Gettext-Systems oder den “Properties

“-Dateien (.properties) von Java. Java kann automatisch auch Kalender-, Datums- und Zeitangaben sowie Zahlenformate anpassen.

Die Vorteile der Auslagerung liegen auf der Hand: Im Nachhinein muss nicht der ganze Quellcode auf zu übersetzende Texte durchsucht werden, der Übersetzer kann den Code nicht versehentlich unbrauchbar machen, etc. Allerdings können Strings zu Fallstricken werden, wenn die Programmierer altgediente Praktiken munter weiterverwenden, zum Beispiel die Verkettung (engl. concatenation) von Strings. Diese stellt z.B. C++ mit der Funktion strcat(); zur Verfügung, viele Sprachen bieten auch den Verkettungs-Operator “.” an, was dann so aussieht: $text = "Hallo, " . $name . ", heute ist " . $datum . "."; Die im Code vorhandenen Strings und die in den Variablen abgelegten Daten werden dann zu einem einzigen Satz verkettet.

Eine Verkettung erlaubt es, Textbausteine immer wieder zu benutzen und mit Hilfe der Variablen die Ausgabe dynamisch anzupassen. Das spart viel Arbeit – wenn man es richtig macht.

Der falsche Faden?

Schlecht implementiert hackt die Verkettung von Strings Sätze auseinander, deren Fragmente ohne jeden Kontext weit über die Ressourcendatei verteilt werden. Dann hat ihr Übersetzer nur noch 3 Möglichkeiten:

Steppjacke Steppjacke Superdry Damen Damen Superdry Steppjacke Superdry rdxsBthQCo

  • Er rät blind, was der String ", heute ist " in Zeile 478 der Ressourcendatei wohl bedeuten mag oder ob “start” als Nomen oder Verb übersetzt werden muss
  • er fragt sehr, sehr, …, sehr oft bei Ihnen nach
  • oder er überzeugt Sie, den Quellcode umzuschreiben.

In jedem Fall wären alle Vorteile der Verkettung verspielt.

Selbst wenn die Reihenfolge der Strings in der Ressource die Richtige ist und sich wie der ganze Satz lesen lässt, kommt man mit der unterschiedlichen Grammatik verschiedener Sprachen in die Bredouille. Das betrifft den unterschiedlichen Satzbau (müssen Adjektive vor oder nach dem Nomen stehen?) und immer wieder auch Kasus (Nominativ, Genitiv, Akkusativ, Dativ), Numerus (Einzahl, Mehrzahl) und Genus (männlich, weiblich, sächlich) von Nomen und Adjektiven (die mit ihrem Nomen übereinstimmen müssen: “KNG-Kongruenz”), sowie die Konjugation von Verben. Hier einige Beispiele für Englisch, Deutsch und Französisch:

The counter = Der Zähler = Le compteur
The timer = Die Zeitschaltuhr = La minuterie
was reset to = wurde zurückgesetzt auf = a été(e) remis(e)Steppjacke Steppjacke Superdry Damen Damen Superdry Steppjacke Superdry rdxsBthQCo
The counter was reset to $cnt. = Der Zähler wurde auf $cnt zurückgesetzt. = Le compteur a été remis à $cnt.
The timer was reset to $time. = Die Stoppuhr wurde auf $time zurückgesetzt. = La minuterie a été remise à $time.

Im Deutschen liegt ein Syntaxproblem vor: Im Perfekt soll das Hilfsverb vor dem Akkusativobjekt (“auf $time”) stehen, das Vollverb am Ende des Satzes. Man könnte “Die Zeitschaltuhr wurde zurückgesetzt auf $time.” schreiben, aber es wäre schlechtes Deutsch. Im Französischen ist der Fall gravierender: Ohne die Frage “männliche oder weibliche Verbform?” entscheiden zu können, muss der Übersetzer auf eine hässliche Klammerlösung zurückgreifen – oder er benutzt nur eine Form, sodass im anderen Fall die Übersetzung schlicht falsch ist. Wie denken Sie jetzt über die Zeitersparnis, “was reset to” im Programm an verschiedenen Stellen verwendet zu haben?

Wenn Adjektive dazukommen, macht die Kongruenz mit dem zugehörigen Nomen alles noch komplizierter:

Never push the = Drücken Sie niemals den/die/das = N’appuyez jamais sur le/la
red = rote(n) = rouge
Zubehör Regenjacke Winterjacke Bekleidungamp; Regenmantel ED2IH9 green = grüne(n) = vert(e)
button = Knopf = bouton
key = Taste = touche
Never push the red button = Drücken Sie niemals auf den roten Knopf = N’appuyez jamais sur le bouton rouge.
Never push the green button = Drücken Sie niemals auf denSkogstadMoseter Parka Down Blue Outdoors H2snow Teal wm80vNn grünen Knopf = N’appuyez jamais sur le bouton vert.
Never push the red key = Drücken Sie niemals auf die rote Taste = N’appuyez jamais sur la touche rouge.
Never push the green key = Drücken Sie niemals auf die grüne Taste = N’appuyez jamais sur la touche verte.

Steppjacke Steppjacke Superdry Damen Damen Superdry Steppjacke Superdry rdxsBthQCo

Und dann hängen auch noch Artikel und unzählige Pronomen von Fall, Anzahl und Geschlecht des Hauptwortes ab, französische Adjektive stehen nicht vor, sondern hinter dem Nomen, etc.pp.

Selbst innerhalb von Strings platzierte Variablen bringen Probleme mit sich, wie in dieser Diskussion (auf Englisch) über die sprintf()-Funktion anschaulich wird: […] many companies fall into this second trap of writing strings like “posted by %s, %s” to form “posted by ChiefUser, 5 minutes ago”. This is more or less the same as concatenating (“posted by”, $author, “, “, $time, ” ago”), it’s not really a placeholder if we can’t switch their order around. Eine Lösung sind die sogenannten positional modifiers für sprintf(), wie sie hier bei Stackoverflow (auch auf Englisch) in einer ganz ähnlichen Diskussion beschrieben werden. Auch Qt kennt den Einsatz von Variablen mit Positionsangaben und im exzellenten Smashing Magazine-Artikel Jackamp; Total Jones Jacket Stand Jorbend Collar Eclipse PiukZTOX12 Commandments of Software Localization werden im Kontext der Webentwicklung ebenfalls “parametrized strings” empfohlen.

Was kann man tun?

Zunächst einmal das offensichtliche: Gehen Sie sparsam und vorsichtig mit der concatenation um. Viele Programmiersprachen erlauben es, Variablen auch innerhalb von Strings einzusetzen, wie im ersten Beispielblock gezeigt. Mit ganzen Sätzen und sprechenden Variablennamen (next_page und next_basketitem statt nur next) kann ihr Übersetzer sehen, um was es geht, und über Sinn und Grammatik richtig entscheiden. Auch die Zeichensetzung gehört vollständig in den String hinein und muss vom Übersetzer angepasst werden können. Im Französischen zum Beispiel gibt die Grammatik vor, dass vor Doppelpunkt, Semikolon, Ausrufezeichen und Fragezeichen sowie innerhalb von Anführungszeichen ein nicht-trennendes Leerzeichen steht. Im Arabischen würde man erst die Zahl, dann den Doppelpunkt und dann den von rechts nach links zu lesenden Satz erwarten.

Um im Kontext von Zahlen den Singular und Plural zugehöriger Nomen (“0 Sekunden“, “1 Sekunde”, “2+ Sekunden“) nicht mit unschönen Klammerkonstruktionen à la “$sec SekundeSteppjacke Steppjacke Superdry Damen Damen Superdry Steppjacke Superdry rdxsBthQCo(n)” zu verunzieren, wird in Concatenation is Evil vorgeschlagen, die Zahl hinter den Doppelpunkt eines vollständigen Satzes zu befördern: “Verbleibende Sekunden: $sec”. Alternativ bietet es sich gerade bei Einheiten an, die offizielle Abkürzung zu verwenden: “Verbleibende Zeit: $sec Sek.” oder von der Programmiersprache bereitgestellte Zahlenformate zu nutzen. Ansonsten darf man das Gezählte als mehrere Variablen ablegen, z.B. für Singular, Dual und Plural, dann die freie Verschiebbarkeit dieser Variable im Satz sicherstellen und hoffen, dass es genügt (siehe der Einleitungssatz im “Dual”-Artikel).

Erwägen Sie den Einsatz von XML für die Lokalisierung. XML wird bereits dazu eingesetzt (z.B. “strings.xml” in Android-Apps) und ermöglicht bei entsprechendem XML-Format (XLIFF als Dokumenten-Austauschformat von Übersetzungstools, TMX als Austauschformat von Übersetzungsspeichern), Kontext- und Zusatzinformationen sowie Links auf weitere Ressourcen (Screenshots, …) beizufügen, die Ihre Übersetzung zuverlässiger machen und Rückfragen minimieren. Wie Translate&Localize aus Italien in “Lokalisierung von Videospielen” ganz richtig sagen: “Vorausplanen und Übersetzer frühzeitig einbinden!” Dazu kann eventuell auch gehören, allen übersetzbaren Text aus Programmcode, Hilfen, Dokumentation, etc. für die Übersetzung in XML-Übersetzungsformate zu überführen und später automatisiert in die entsprechenden Formate und Ressourcen zurück zu konvertieren.

Weitere Erklärungen finden Sie hier:

Achten Sie bei der i18n immer auch auf:

  • Genügend Platz für abweichende Wort- und Satzlängen. Englisch “Please hit the Esc key.” (23 Zeichen), Deutsch “Bitte drücken Sie die Esc Taste.” (32 Zeichen, +39%), Französisch “S’il vous plaît, poussez la touche Esc.” (39 Zeichen, +70%). Im Schnitt müssen Sie mit 15-30% Längenunterschieden zwischen Sprachen rechnen.
  • Mögliche UI-Anpassungen für RTL-Sprachen wie Hebräisch oder Arabisch, sowie für senkrecht geschriebene Alphabete. Benutzen Sie, wo immer es geht, Unicode als Zeichenkodierung (i.d.R. UTF-8). Beachten Sie dabei typische Bugs der verwendeten Programmiersprachen (Perl versucht z.B. fälschlicherweise, bei Verkettungen UTF-8 nochmal neu als UTF-8 zu kodieren!)

Und wenn Sie sich noch fragen, ob Sie bei all den Schwierigkeiten überhaupt lokalisieren sollten, lesen Sie doch mal “Globaler Erfolg für europäische Startups – Lokalisierung als SprungbrettS09327 83i2 Jacke Tx Hyb Amazon Adidas J Sosh Gr50 sthrQd” von Helmut Juskewycz, dem CEO und Gründer von LingoHub. Es ist alles halb so wild, wenn man es geplant angeht.

Viele Grüße, Ihr
Christopher Köbel