Übersetzungen einem Twasi-Plugin hinzufügen
Twasi-Plugins können (und sollten) mehrsprachig sein. Deshalb haben wir ein Übersetzungssystem in das Plugin-Framework eingeführt.
Die TwasiTranslation (altes System)
Die erste Version unseres Übersetzungssystems nutzte die Vorteile der Funktion String.format(), die mit JDK kommt:
EN_GB.lang:
commands.balance=Hello %s, you have already collected %d %s!
DE_DE.lang:
commands.balance=Hallo %s, du hast bereits %d %s gesammelt!
Und im Code:
public boolean execute(TwasiCustomCommandEvent event) {
// Get the parameter values
int money = getBankAccountValue(event.getSender());
String currencyName = getCurrencyName();
// And reply, specifying all paramters
event.reply(getTranslation('commands.balance',
event.getSender().getDisplayName(),
money,
currencyName
)
);
}
Dies funktioniert in den meisten Fällen gut, aber Sprachen können in ihrer Struktur sehr unterschiedlich sein. Dieses System setzt die gleiche Reihenfolge von Parametern in allen Sprachen ein, was hässliche Sätze verursachen kann. Auch die Übersetzungen sind nicht sehr lesbar.
Deshalb haben wir den TranslationRenderer erstellt 🙌
Der TranslationRenderer (neues System)
Das Hauptziel des TranslationRenderer ist es, Übersetzungen lesbar und flexibel für die Entwickler und Übersetzer zu halten. Es wird durch Parameterbindung und Objektmapping unterstützt, um so einfach wie möglich zu sein.
Wie funktioniert es?
Das Übersetzungssystem bleibt gleich im Allgemeinen. Sprachdateien, die die Übersetzungsschlüssel enthalten und deren Übersetzungen werden im Verzeichnis 'resource/translations' gespeichert. Statt '%d' oder '%s' gibt es jetzt Parameter mit nützlichen Namen, die nicht in allen Sprachen in die gleiche Reihenfolge passen müssen.
Beispiel
EN_GB.lang:
commands.balance=Hello {sender.displayName}, you have already collected {amount} {currencyName}!
DE_DE.lang:
commands.balance=Hallo {sender.displayName}, du hast bereits {amount} {currencyName} gesammelt!
Und im Code:
public boolean execute(TwasiCustomCommandEvent event) {
// Get the renderer
TranslationRenderer renderer = event.getRenderer();
// Now bind all parameters
renderer.bind('amount', getBankAccountValue(event.getSender()));
renderer.bind('currencyName', getCurrencyName());
// And send the rendered key back
event.reply(renderer.render('commands.balance');
}
Sei nicht verwirrt, dass 'sender.displayName' nicht bindend ist, lies einfach weiter...
Statische Bindung
Statische Bindung ist die einfachste Bindungsmethode für den TranslationRenderer. Du definierst, was gebunden werden soll und gibst ihm einen Namen.
Beispiel
public boolean execute(TwasiCustomCommandEvent event) {
TranslationRenderer renderer = event.getRenderer();
// This binds "Jeff, my name's Jeff." to {jeff}
renderer.bind("jeff", "Jeff, my name's Jeff.");
// This binds "120" to {value} and {result}
renderer.multiBind("120", "value", "result");
}
Objekt-Zuordnung
Der TranslationRenderer unterstützt die Objektzuordnung. Das bedeutet, dass wir jedes Objekt daran binden können und die Werte von Funktionen oder Feldern des Objekts erhalten können, indem wir sie mit Punkten auswählen.
'sender' ist die Standardverbindung des TwitchAccount-Objekts des Befehlausführers. Die TwitchAccount-Klasse hat eine Funktion namens getDisplayName(), diese gibt (offensichtlich) den Anzeigenamen des Benutzers zurück, der den Befehl ausgeführt hat.
Dies funktioniert mit öffentlichen Funktionen und öffentlichen Bereichen. Es funktioniert auch auf mehreren Ebenen, sodass du etwas wie {object.subObject.subSubObject} rendern könntest.
Der TranslationRenderer ist dabei auch irgendwie intelligent, diese Bindungen zu lösen. Du brauchst dir keine Sorgen um Groß- oder Kleinschreibung zu machen und kannst auch die Funktionspräfixe 'get', 'is' und 'has' ignorieren. All dies ist möglich dank Java Reflections 。◕‿◕。
Beispiel
public boolean execute(TwasiCustomCommandEvent event) {
TranslationRenderer renderer = event.getRenderer();
renderer.bindObject("sender", sender);
renderer.multiBind(user.getTwitchAccount(), "user", "streamer");
}
Dynamische Bindung
Beispiel
Wird bald dokumentiert werden. Versprochen!
Standard-Bindungen
Du bekommst den Renderer direkt vom eingehenden Befehlsereignis. Das ermöglicht Twasi, Variablen und Objekte, die sehr oft verwendet werden, im Hintergrund zu binden.
Die folgenden Standard-Bindungen sind verfügbar:
| Name | Typ | Datentyp | Beschreibung |
|---|---|---|---|
| sender | Objekt | TwitchAccount | Das TwitchAccount des Benutzers, der den Befehl ausgeführt hat. |
| command | Statisch | String | Der Name des Befehls. |
| args | Statisch | String | Alle Befehlsarten als einen String. |
| args.(x) | Statisch | String | Ein spezifisches Argument (args.1 für das erste Argument). |
| user/streamer | Objekt | TwitchAccount | Der TwitchAccount des Streamers. |
| lang/language | Statisch | String | Der Name der verwendeten Sprache. |
| ver/version | Statisch | String | Die aktuelle Twasi-Core Version. |
| date | Dynamisch | String | Lokalisierter Datumsstring. |
| time/clocktime | Dynamisch | String | Die aktuelle Zeit (24hr Format HH:mm). |
Verschachtelung von Übersetzungsbindungen
Der TranslationRenderer unterstützt die Verschachtelung. Die inneren Bindungen werden immer zuerst gelöst.
Beispiel
{sender.{field}}
Wenn es ein Bindeglied namens 'Feld' mit dem Wert 'userName' gab, würde der Renderer zuerst {field} parsen:
{sender.userName}
Und dann die äußere Bindung lösen.
Dies kann auf mehreren Ebenen ohne Einschränkungen geschehen.
Zufällige Übersetzungen
Wenn dein Plugin einen zufälligen Satz zurückgeben sollte, kannst du den Syntax-Schlüssel mehrfach deklarieren und die Funktion renderRandom(String key)-aufrufen.
Beispiel
EN_GB.lang:
my.translation.key=Hello {user.displayNmame}
my.translation.key=Hey, {user.displayName}. How are you?
my.translation.key=I say hi to {user.displayName}!
Und im Code:
public boolean execute(TwasiCustomCommandEvent event) {
TranslationRenderer renderer = event.getRenderer();
// This always returns the first sentence
String translation = renderer.render("my.translation.key");
// But this always picks a random one of the three sentences
String randomTranslation = renderer.renderRandom("my.translation.key");
}
Fallback-Übersetzungen
Egal ob du das alte oder das neue System verwendest, die Datei EN_GB.lang ist immer die Fallback-Sprachdatei, die verwendet wird, wenn der verwendete Schlüssel nicht in der gewünschten Sprache verfügbar ist oder die Sprachdatei überhaupt nicht existiert.
Deshalb sollten alle Plugins eine vollständige englische Übersetzung enthalten.
Standard-Übersetzungsschlüssel
Einige Übersetzungsschlüssel sind reserviert und sollten nicht für irgendetwas anderes verwendet werden.
Plugin-Informationen-Schlüssel
Um deine Plugin-Informationen zu lokalisieren, kannst du die folgenden Übersetzungsschlüssel verwenden:
| Schlüssel | Beschreibung |
|---|---|
| plugin.name | Der Plugin-Name, der im Plugin-Store vom Twasi-Panel angezeigt wird. |
| plugin.description | Die Plugin-Beschreibung, die im Plugin-Store vom Twasi-Panel angezeigt wird. |
| plugin.helptext | Der Plugin-Helpdext, der im Plugin-Shop vom Twasi-Panel angezeigt wird. |
Plugin-Berechtigungsbeschreibungen
Das ist noch nicht umgesetzt, wird aber bald umgesetzt!
Es ist nicht immer klar, welche Berechtigungen ein Berechtigungsschlüssel genau gewährt. Du solltest allen deinen Übersetzungsschlüsseln einen klaren Namen geben, damit sie jeder versteht. Diese sollten auch lokalisiert werden, sodass wir sie mit einem führenden '§' in unsere Übersetzungsdateien aufnehmen.
Beispiel
Wenn du den folgenden Berechtigungsschlüssel beschreiben möchtest:
commands.add
Deine Übersetzung sollte wie folgt aussehen:
§commands.add=Add new commands to the channel
Fortfahren
Im nächsten Teil der "Getting started" Serie wirst du lernen, wie du Variablen zu deinem Plugin hinzufügen kannst!