[c++] Bester Weg für die Lokalisierung von Strings



2 Answers

Ich weiß nicht viel darüber, wie dies normalerweise unter Windows geschieht, aber die Art und Weise, wie lokalisierte Zeichenketten in Apples Cocoa-Framework behandelt werden, funktioniert ziemlich gut. Sie haben eine sehr einfache Textformatdatei, die Sie an einen Übersetzer senden können, und einige Präprozessor-Makros, um die Werte aus den Dateien abzurufen.

In Ihrem Code sehen Sie die Zeichenfolgen in Ihrer Muttersprache und nicht als undurchsichtige IDs.

Question

Das ist eine allgemeine Frage, offen für Meinungen. Ich habe versucht, einen guten Weg für die Lokalisierung von String-Ressourcen für eine Windows MFC-Anwendung und verwandte Dienstprogramme zu entwerfen. Meine Wunschliste ist:

  • Muss Zeichenfolgenliterale im Code beibehalten (im Gegensatz zum Ersetzen durch Makro #define-Ressourcen-IDs), damit die Nachrichten noch inline lesbar sind
  • Muss lokalisierte String-Ressourcen zulassen (duh)
  • Darf keine zusätzlichen Laufzeitumgebungsbeschränkungen auferlegen (zB: Abhängigkeit von .NET, etc.)
  • Sollte minimale Eindringlichkeit in bestehenden Code haben (je weniger Modifikation desto besser)
  • Sollte debugbar sein
  • Generiert Ressourcendateien, die mit gängigen Tools bearbeitet werden können (dh: gemeinsames Format)
  • Verwenden Sie keine Copy / Paste-Kommentar-Blöcke, um Literal-Strings im Code oder irgendetwas anderes zu speichern, das das Potential für die Desynchronisation schafft
  • Wäre nett, statische (Kompilierungszeit) Überprüfung zu erlauben, dass jeder "notierte" String in der / den Ressource-Datei (en) ist
  • Es wäre schön, ein sprachspezifisches Ressourcen-String-Pooling zu ermöglichen (für Komponenten in verschiedenen Sprachen, zB: native C ++ und .NET)

Ich habe einen Weg, der alle meine Wunschliste bis zu einem gewissen Grad erfüllt, außer für die statische Überprüfung, aber ich musste ein bisschen benutzerdefinierten Code entwickeln, um es zu erreichen (und es hat Einschränkungen). Ich frage mich, ob jemand dieses Problem besonders gut gelöst hat.

Edit: Die Lösung, die ich momentan habe, sieht so aus:

ShowMessage( RESTRING( _T("Some string") ) );
ShowMessage( RESTRING( _T("Some string with variable %1"), sNonTranslatedStringVariable ) );

Ich habe dann ein benutzerdefiniertes Dienstprogramm, um die Zeichenfolgen innerhalb der 'RESTRING'-Blöcke zu analysieren und sie in eine RESX-Datei für die Lokalisierung und ein separates C # COM-Objekt zu platzieren, um sie aus lokalisierten Ressourcendateien mit Fallback zu laden. Wenn das C # -Objekt nicht verfügbar ist (oder nicht geladen werden kann), greife ich auf die Zeichenfolge im Code zurück. Das Makro wird zu einer Vorlagenklasse erweitert, die das COM-Objekt aufruft und die Formatierung usw. ausführt.

Wie auch immer, ich dachte, es wäre nützlich, das hinzuzufügen, was ich jetzt als Referenz habe.




Da es für Meinungen offen ist, hier ist, wie ich es mache.

Meine lokalisierte Textdatei ist eine einfache tabulatorgetrennte Textdatei, die in Excel geladen und bearbeitet werden kann. Die erste Spalte ist für die Definition und jede Spalte rechts ist eine nachfolgende Sprache, zum Beispiel:

ID              ENGLISH      FRENCH    GERMAN
STRING_YES      YES          OUI       YA
STRING_NO       NO           NON       NEIN

Dann ist in meinem Makefile ein Cusom-Build-Schritt, der eine strings.h-Datei und eine strings.dat generiert. In meinem Fall erstellt es eine Enum-Liste für die String-IDs und dann eine Binärdatei mit Offsets für den Text. Da in meiner App der Benutzer die Sprache jederzeit ändern kann, habe ich sie alle im Speicher, aber Sie könnten leicht Ihren Pre-Verarbeiter haben, eine andere Ausgabedatei für jede Sprache zu erzeugen, wenn nötig.

Die Sache, die ich an diesem Entwurf mag, ist, dass, wenn irgendwelche Zeichenfolgen fehlen, ich einen Kompilierfehler erhalten würde, während, wenn Zeichenfolgen zur Laufzeit nachgeschlagen wurden, Sie möglicherweise nicht über eine fehlende Zeichenfolge in einem selten verwendeten Teil des Codes bis später wissen.




Der einfache Weg besteht darin, nur String-IDs in Ihrem Code zu verwenden - keine literalen Strings. Sie können dann für jede Sprache verschiedene Versionen der Datei .rc erstellen und entweder DLLs für Ressourcen oder einfach nur unterschiedliche Sprachversionen erstellen.

Es gibt ein paar Shareware utilstohelp, die die rc-Datei lokalisieren, die die Größe der Dialogelemente für Sprachen mit längeren Wörtern behandelt und vor fehlenden Übersetzungen warnt.

Ein komplizierteres Problem ist die Wortreihenfolge, wenn Sie mehrere Zahlen in einem printf haben, die für die Grammatik der verschiedenen Sprachen in einer anderen Reihenfolge sein müssen. Es gibt einige erweiterte printf-Klassen in Codeproject, mit denen Sie Dinge wie printf ("word% 1s und% 2s", var1, var2) angeben können, sodass Sie bei Bedarf auch% 1s und% 2s wechseln können.




Related