5

EDIT: Ich habe die Frage komplett neu geschrieben, da es scheint, dass ich in meinen ersten beiden Versionen nicht klar genug war. Danke für die bisherigen Vorschläge.Wie man den Java-Quellcode internationalisiert?

Ich möchte den Quellcode für ein Tutorial-Projekt internationalisieren (beachten Sie bitte, nicht die Runtime-Anwendung). Hier ist ein Beispiel (in Java):

/** A comment */ 
public String doSomething() { 
    System.out.println("Something was done successfully"); 
} 

auf Englisch, und hat dann die Französisch-Version sein, so etwas wie:

/** Un commentaire */ 
public String faitQuelqueChose() { 
    System.out.println("Quelque chose a été fait avec succès."); 
} 

und so weiter. Und dann haben so etwas wie eine Eigenschaft irgendwo Datei diese Übersetzungen mit üblichen Werkzeugen zu bearbeiten, wie zum Beispiel:

com.foo.class.comment1=A comment 
com.foo.class.method1=doSomething 
com.foo.class.string1=Something was done successfully 

und für andere Sprachen:

com.foo.class.comment1=Un commentaire 
com.foo.class.method1=faitQuelqueChose 
com.foo.class.string1=Quelque chose a été fait avec succès. 

Ich versuche, die am einfachsten zu finden, effizienteste und unaufdringliche Art und Weise, dies mit der geringsten Menge an manueller Gruntarbeit zu tun (außer offensichtlich den eigentlichen Text zu übersetzen). Vorzugsweise unter Eclipse arbeiten. Beispielsweise würde der ursprüngliche Code in Englisch geschrieben, dann externalisiert (in Eigenschaften, wobei die ursprüngliche Quelle vorzugsweise unberührt gelassen wird), übersetzt (menschlich) und dann erneut erzeugt (als separate Quelldatei/Projekt).

Einige Wege gefunden haben (anders als das, was AlexS vorgeschlagen):

  • AntLR, eine Sprache Parser/Generator. Es scheint eine unterstützende Eclipse plugin
  • Verwenden Eclipse's AST (Abstract Syntax Tree) und ich rate Build eine Art von Plugin.

Ich bin nur überrascht, dass es kein Tool gibt, das das schon tut.

+1

Verwenden Sie Property-Dateien. –

+0

verweisen Sie hierzu auf http://stackoverflow.com/questions/1318347/how-to-use-java-property-files –

+0

Das [Java Internationalisierungs-Lernprogramm] (http://docs.oracle.com/javase/tutorial/i18n/) index.html) ist ein guter Anfang. –

Antwort

2

ich einzigartige Saiten verwenden würde als methodnames (oder alles, was Sie durch lokalisierte Versionen ersetzt werden soll

public String m37hod_1() { 
    System.out.println(m355a6e_1); 
} 

dann ich eine Property für jede Sprache wie folgt definieren würde.

m37hod_1=doSomething 
m355a6e_1="Something was done successfully" 

Und dann würde ich ein kleines Programm schreiben, das die Quelldateien analysiert und die Zeichenfolgen ersetzt. Also alles gerade außerhalb Finsternis.

Oder ich würde die Ant-Task Replace und Propertyfiles anstelle eines eigenständigen Übersetzungsprogramms verwenden. So etwas:

<replace 
    file="${src}/*.*" 
    value="defaultvalue" 
    propertyFile="${language}.properties"> 
    <replacefilter 
    token="m37hod_1" 
    property="m37hod_1"/> 
    <replacefilter 
    token="m355a6e_1" 
    property="m355a6e_1"/> 
</replace> 

eine dieser Methoden verwenden Sie nichts über die Lokalisierung in Ihre Tutorials erklären müssen (außer Sie wollen), kann aber auf Ihre eigentliche Thema konzentrieren.

+0

+1 für die Beantwortung der eigentlichen Frage. Hinweis: Aussagekräftige IDs sind möglicherweise verständlicher. –

+0

Danke für Ihre Vorschläge. Ja, das ist der einzige Weg, von dem ich jetzt weiß (ich dachte mir, dass ich vielleicht ein grep/shell-Tool zum Suchen und Ersetzen verwenden könnte), aber dann wird der ursprüngliche Code schwieriger zu lesen. Ich würde gerne etwas finden, das benutzerfreundlicher ist und wenn möglich in Eclipse gesteckt wird. – bdery

+0

Wahrscheinlich können Sie Ihre Namen tatsächlich lassen, was sie sind und es würde das gleiche funktionieren. Ich verwende hauptsächlich 1337 für den Geek-Faktor;) – AlexS

0

Verwenden .properties-Datei, wie:

Locale locale = new Locale(language, country); 
ResourceBundle captions= ResourceBundle.getBundle("Messages",locale); 

Auf diese Weise nimmt Java die Messages.properties Datei entsprechend den aktuellen lokalen (die vom Betriebssystem oder Java Locale-Einstellungen erworben wird)

die Datei sollte auf dem classpath, genannt Messages.properties (der Standard ein) oder Messages_de.properties Deutsch usw.

das sehen für ein komplettes Tutorial: http://docs.oracle.com/javase/tutorial/i18n/intro/steps.html

Soweit der Quellcode geht, würde ich dringend empfehlen, mit Englisch zu bleiben. Methodenbezeichnungen wie getUnternehmen() sind schlechter für den durchschnittlichen Entwickler als für einfache englische. Wenn Sie Ihren Code mit ausländischen Entwicklern vertraut machen müssen, schreiben Sie eine entsprechende Entwicklerdokumentation in ihrer Sprache.

Wenn Sie Javadoc sowohl in Englisch als auch in anderen Sprachen haben möchten, lesen Sie SO thread.

+0

Dies beantwortet meine Frage nicht, sorry. Bei Bedarf erneut lesen. – bdery

0

für die gedruckte/geloggte Zeichenkette besitzt Java einige Internationalisierungsfunktionen, auch bekannt als ResourceBundle. Es gibt ein Tutorial über diese on oracle site

Eclipse besitzen auch eine Funktionalität für diese ("Externalize String", wie ich mich erinnere).

für die Funktionsnamen, ich glaube nicht, dass irgendetwas aus, da dies erfordert, dass Sie den Code Quelle auf vieler Version zu halten ...

Grüße

+0

Danke, aber das beantwortet die Frage nicht. – bdery

1

Ein Ansatz wäre, den Code in einer Sprache zu beenden und dann in andere zu übersetzen.

Sie könnten Eclipse verwenden, um Ihnen zu helfen.

  1. Kopieren Sie den fertigen Code in sprachspezifische Projekte. Dann
  2. :
    • Identifiers: In der Gliederungsansicht (Fenster> Sicht anzeigen> Gliederung), wählen Sie jedes Element und Umgestalten> Umbenennen (Alt + Shift + R). Dadurch wird der Bezeichner überall dort umbenannt, wo er verwendet wird.
    • Kommentare: Verwenden Sie Suche> Datei, um alle Instanzen von "/ *" oder "//" zu finden. Klicken Sie auf jedes und ändern Sie es.
    • Saiten:
      1. Verwendung Source> Externalize Strings alle der Literalzeichenfolgen zu finden.
      2. Suche> Datei für "Messages.getString()".
      3. Klicken Sie auf jedes Ergebnis und ändern.
      4. Auf jeder Datei, "Bearbeiten> Suchen/Ersetzen", Ersetzen von "//\$NON-NLS-.*\$" mit einer leeren Zeichenfolge.
+0

Danke, ja, das ist ein Weg. Ich würde gerne eine automatisierte und elegante Art finden, dies zu tun. Ex. Sammeln Sie alle Zeichenfolgen, um sie externalisieren zu lassen, indem Sie mit einem Werkzeug eine große Eigenschaftendatei erzeugen, die alle Klassen, Methoden, Variablen, Kommentare und Zeichenfolgen mit einer Art von qualifiziertem Bezeichner (Beispiel com.foo.class1.method1 = myMethod, etc) enthält übersetzt werden. – bdery

+0

Verstanden. Bedenken Sie dies, wenn ein solches Werkzeug nicht existiert. :) Diese Antwort basiert auf meiner eigenen Erfahrung mit Lokalisierung und der Vermutung, dass Beispielcode für Lernprogramme nicht groß ist. –

2

Was Sie wollen, ist eine massive Codeänderung Motor.

ANTLR wird nicht den Trick machen; ASTs sind notwendig, aber nicht ausreichend. Siehe meinen Aufsatz auf Life After Parsing. Eclipse "AST" kann besser sein, wenn das Eclipse-Paket einige Unterstützung für die Auflösung von Name und Typ bietet; Andernfalls werden Sie nie in der Lage sein, herauszufinden, wie Sie jedes "doSomething" ersetzen (möglicherweise überlastet oder lokal), es sei denn, Sie sind bereit, sie alle identisch zu ersetzen (und Sie können das wahrscheinlich nicht tun, weil einige Symbole verweisen zu Java-Bibliothekselementen).

Unsere DMS Software Reengineering Toolkit könnte verwendet werden, um Ihre Aufgabe zu erfüllen. DMS kann Java zu ASTs verarbeiten (einschließlich Kommentarerfassung), die ASTs auf beliebige Weise durchlaufen, ASTs analysieren und ändern und die modifizierten ASTs als gültigen Quellcode (einschließlich der Kommentare) exportieren.

Grundsätzlich möchten Sie alle Kommentare, Strings und Deklarationen von Bezeichnern auflisten, sie in eine externe "Datenbank" exportieren, um sie (manuell? Von Google Translate?) Auf ein Äquivalent zu mappen. In jedem Fall möchten Sie nicht nur das Element von Interesse, sondern seine genaue Position (Quelldatei, Zeile, gerade Spalte) notieren, da Elemente, die im Originaltext identisch geschrieben werden, im geänderten Text möglicherweise unterschiedliche Schreibweisen benötigen.

Enumeration von Strings ist ziemlich einfach, wenn Sie den AST haben; Durchsuchen Sie einfach den Baum und suchen Sie nach Baumknoten, die Zeichenfolgenliterale enthalten. (ANTLR und Eclipse können das sicher auch).

Enumeration von Kommentaren ist auch einfach, wenn der Parser Sie Kommentare erfasst hat. DMS tut es. Ich bin mir nicht ganz sicher, ob die Java-Grammatik von ANTLR oder die Eclipse-AST-Engine funktioniert. Ich vermute, dass sie beide fähig sind.

Enumeration von Deklarationen (Klassen, Methoden, Felder, Locals) ist relativ einfach; Es gibt mehr Fälle, über die Sie sich Gedanken machen müssen (z. B. anonyme Klassen mit Erweiterungen der Basisklassen). Sie können eine Prozedur codieren, um die AST zu durchlaufen und die Baumstrukturen anzupassen, aber hier ist der Ort, an dem DMS einen Unterschied macht: Sie können Oberflächen-Syntax-Muster schreiben, die wie der Quellcode aussehen, den Sie abgleichen möchten. Zum Beispiel:

pattern local_for_loop_index(i: IDENTIFIER, t: type, e: expression, e2: expression, e3:expression): for_loop_header 
     = "for (\t \i = \e,\e2,\e3)" 

wird für Schleifenvariablen Erklärungen von lokalen übereinstimmen, und das Rückteilbäume für den Identifikator, der Typ und die verschiedenen Ausdrucksformen; Sie möchten nur den Bezeichner (und seinen Speicherort) erfassen, indem Sie einfach aus der Quellposition Informationen entnehmen, die DMS auf jedem Baumknoten speichert. Sie würden wahrscheinlich 10-20 solcher Muster benötigen, um die Fälle aller verschiedenen Arten von Identifikatoren abzudecken.

Erfassungsschritt abgeschlossen, etwas muss alle erfassten Entitäten in Ihre Zielsprache übersetzen. Das überlasse ich dir. Was übrig bleibt, ist, die übersetzten Entitäten zurück zu legen.

Der Schlüssel dazu ist die genaue Quellenposition. Eine Zeilennummer ist in der Praxis nicht gut genug; Sie können mehrere übersetzte Entitäten in der gleichen Zeile haben, im schlimmsten Fall einige mit unterschiedlichen Bereichen (stellen Sie sich zum Beispiel geschachtelt für Schleifen vor). Der Ersetzungsprozess für Kommentare, Strings und Deklarationen ist unkompliziert; Durchsuchen Sie den Baum erneut nach Knoten, die mit den identifizierten Positionen übereinstimmen, und ersetzen Sie die dort gefundene Entität durch ihre Übersetzung. (Sie können dies mit DMS und ANTLR tun. Ich denke Eclipse ADT erfordert, dass Sie einen "Patch" generieren, aber ich denke, das würde funktionieren.).

Der Spaß Teil kommt in der Ersetzung der Kennung verwendet.Dazu müssen Sie zwei Dinge wissen:

  • für jede Verwendung einer Kennung, was ist die Erklärung zwecken; Wenn Sie das wissen, können Sie es durch den neuen Namen für die Deklaration ersetzen; DMS bietet vollständige Namen und Typ-Auflösung sowie eine Nutzungsliste, so dass dies ziemlich einfach ist, und
  • Do benannte Bezeichner Schatten einander in Bereichen anders als die Originale? Dies ist im Allgemeinen schwieriger zu tun. Für die Java-Sprache haben wir jedoch eine "Shadowing" -Überprüfung, so dass Sie zumindest nach dem Umbenennen entscheiden können, dass Sie Probleme haben. (Es gibt sogar eine Umbenennung Prozedur, die verwendet werden können, solche Abschattung zu lösen Konflikte

Nachdem die Bäume Patchen Sie einfach den gepatchten Baum umschreiben wieder aus wie eine Quelldatei DMS eingebauten in Pretty verwenden. Ich denke, AST Eclipse kann schreibe seinen Baum plus Patches aus.Ich bin mir nicht sicher, ob ANTLR irgendwelche Möglichkeiten zur Neugenerierung von Quellcode von ASTs bietet, obwohl jemand möglicherweise einen für die Java-Grammatik codiert hat.Dies ist harder to do than it sounds, wegen all der wählerischen Details.YMM.

In Anbetracht Ihres Ziels bin ich ein wenig überrascht, dass Sie nicht möchten, dass eine Quelldatei "foo.java", die "class foo {...}" enthält, in .java umbenannt wird. Dazu müsste nicht nur der transformierte Baum geschrieben werden zu den übersetzten Dateiname (ziemlich einfach), aber vielleicht sogar den Verzeichnisbaum rekonstruieren (DMS bietet auch Möglichkeiten für Verzeichnisaufbau und Dateikopien).

Wenn Sie dies für viele Sprachen tun möchten, müssen Sie den Prozess einmal pro Sprache ausführen. Wenn Sie dies nur für Strings (den klassischen Fall der Internationalisierung) tun möchten, ersetzen Sie jede Zeichenfolge (die geändert werden muss, nicht alle) durch einen Aufruf eines Ressourcenzugriffs mit einer eindeutigen Ressourcen-ID. Eine Laufzeittabelle würde die verschiedenen Strings enthalten.

+0

Danke, du bringst viele nützliche Bits auf. Es stimmt, dass es bei der Lösung nicht nur um das Parsen, sondern um das Transformieren geht. Ich denke, ich werde mich für eine einfache Lösung zum Suchen und Ersetzen entscheiden, da es sich anhört, als würde ich mit diesen Parser-Übersetzern über meinen Kopf kommen und mein Anwendungsfall war für ziemlich einfaches Zeug. Ich werde meine offizielle Antwort unten veröffentlichen. – bdery

0

Sie könnten Ihren Code unter Verwendung von freemarker Vorlagen (oder einer anderen Vorlagensprache wie velocity) schreiben.

doSomething.tml

/** ${lang['doSomething.comment']} */ 
public String ${lang['doSomething.methodName']}() { 
    System.out.println("${lang['doSomething.message']}"); 
} 

lang_en.prop

doSomething.comment=A comment 
doSomething.methodName=doSomething 
doSomething.message=Something was done successfully 

Und dann mit jeder Sprache prop-Datei während der Build die Vorlage fusionieren (mit Ant/Gradle/Maven etc.)