TwasiDocs

TwasiDocs

  • Developers
  • Users
  • Changelogs
  • Blog
  • Languages iconEnglish
    • Deutsch

›Getting started

Welcome

  • Home

Core concepts

  • The Twasi-Plugin
  • The Twasi-Command
  • The Twasi-Variable

Getting started

  • Local Twasi setup
  • Plugin Base
  • Plugin commands
  • Plugin translations
  • Plugin variables
  • Plugin permissions

Adding translations to a Twasi-Plugin

Twasi-Plugins can (and should) be multilingual. That's why we introduced a translation system into the plugin-framework.

The TwasiTranslation (old system)

The first version of our translation system used the benefits of the String.format() function that ships with the JDK:

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!

And in 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
            )
        );
    }

This works fine in most cases, but languages can be very different in their structure. This system enforces the same sequence of parameters across all languages, which can cause ugly sentences. Also the translations are not very readable.

This is why we created the TranslationRenderer 🙌

The TranslationRenderer (new system)

The main goal of the TranslationRenderer is to keep translations readable and flexible for the developers and the translators. It is powered by parameter binding and object mapping to be as simple as possible.

How does it work?

The translation system in general stays the same. Language files containing the translation keys and their translations are stored in the 'resource/translations' directory. Instead of '%d' or '%s' there are now parameters with useful names that do not have to fit the same sequence across all languages.

Example

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!

And in 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');
    }

Don't be confused about not binding 'sender.displayName', just keep reading...

Static binding

Static binding is the most simple binding method for the TranslationRenderer. You define what to bind and give it a name.

Example

    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");
    }

Object mapping

The TranslationRenderer supports object mapping. That means that we could bind any object to it and can get the values of either functions or fields of the object by selecting them with dots.

'sender' is the default binding of the TwitchAccount-Object of the command executor. The TwitchAccount-class has a function called getDisplayName() that returns (obviously) the display name of the user who executed the command.

This works with public functions and public fields. It also works on multiple levels so you could render something like {object.subObject.subSubObject}.

The TranslationRenderer is also kinda smart resolving those bindings. You don't have to worry about upper- or lowercase and also you can ignore the function prefixes 'get', 'is' and 'has'. All of this is possible thanks to Java Reflections 。◕‿◕。

Example

    public boolean execute(TwasiCustomCommandEvent event) {
        TranslationRenderer renderer = event.getRenderer();

        renderer.bindObject("sender", sender);
        renderer.multiBind(user.getTwitchAccount(), "user", "streamer");
    }

Dynamic binding

Example

Will be documented soon. Promised!

Default bindings

You get the renderer directly from the incoming command event. This allows Twasi to bind variables and objects that are used very often, in the background.

The following default bindings are available:

nametypedata typedescription
senderobjectTwitchAccountThe TwitchAccount of the user who executed the command.
commandstaticStringThe command name.
argsstaticStringAll command arguments as one string.
args.(x)staticStringA specific argument (args.1 for the first arg).
user/streamerobjectTwitchAccountThe streamer's TwitchAccount.
lang/languagestaticStringThe name of the used language.
ver/versionstaticStringThe current Twasi-Core version.
datedynamicStringLocalized date string.
time/clocktimedynamicStringThe current time (24hr format HH:mm).

Nesting translation bindings

The TranslationRenderer supports nesting bindings. The inner bindings will always be resolved first.

Example

{sender.{field}}

If there was a binding called 'field' with the value 'userName', the renderer would first parse {field}:

{sender.userName}

And then resolve the outer binding.

This can be done on multiple levels without limitations.

Random translations

If your plugin should return a random sentence, you can declare your syntax key multiple times and call the renderRandom(String key)-function.

Example

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}!

And in 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 translations

No matter if you use the old or the new system, the EN_GB.lang file is always the fallback language file that will be used if either the used key is not available in the requested language or the language file doesn't exist at all.

This is why all plugins should contain a complete English translation.

Default translation keys

Some translation keys are reserved and should not be used for anything else.

Plugin information keys

To localize your plugin information you can use the following translation keys:

keydescription
plugin.nameThe plugin name that is shown in the plugin store of Twasi-Panel.
plugin.descriptionThe plugin description that is shown in the plugin store of Twasi-Panel.
plugin.helptextThe plugin helptext that is shown in the plugin store of Twasi-Panel.

Plugin permission descriptions

This is not implemented yet but will be implemented soon!

It's not always clear which permissions a permission key exactly grants. You should give all of your translation keys a clear name to make everyone understand them. These should also be localized, so we add them to our translation files with a leading '§'.

Example

If you want to describe the following permission key:

commands.add

your translation should look like this:

§commands.add=Add new commands to the channel

Continue

In the next part of the "Getting started" series you will learn how to add variables to your plugin!

← Plugin commandsPlugin variables →
  • The TwasiTranslation (old system)
  • The TranslationRenderer (new system)
    • How does it work?
    • Static binding
    • Object mapping
    • Dynamic binding
    • Default bindings
    • Nesting translation bindings
    • Random translations
  • Fallback translations
  • Default translation keys
    • Plugin information keys
    • Plugin permission descriptions
  • Continue
TwasiDocs
Docs
User DocumentationDeveloper DocumentationAPI Reference
Community
DiscordTwitter
More
BlogGitHub
Legals
PrivacyTerms of UseImprint
Copyright © 2019 Twasi | Twasi.NET | Docs.Twasi.NET