Kora/developer documentation/Languages

Languages

Give your module's text a default, translations and an editor on the Lang page.

A lang class lists the text your module sends, such as API messages or bot replies. Admins can reword any of it on the Lang page, per language, and your code reads the result.

Supported Languages

en, fr, es-ES, de, pt-BR, it, nl, pl, ru, uk, tr, sv-SE, ja, ko, zh-CN, zh-TW

English is the base. Kora looks up text in the server's Language, then its Secondary Language, then English, and uses the first one that has the key.

Defining Text

Put the English class in resources/lang/en/:

modules/example/resources/lang/en/messages.js
import { Langs } from "#kora/modules";

export class ExampleMessages extends Langs {
    constructor(kora) {
        super(kora, { name: "messages", label: "Messages", description: "Text sent by the example API" });
    }

    schema() {
        return {
            replies: {
                type: "section",
                label: "Replies",
                fields: {
                    synced: { type: "phrase", default: "Synced %count% licenses.", label: "Synced" },
                    failed: { type: "phrase", default: "Sync failed: %reason%", label: "Failed" }
                }
            },
            footer: { type: "text", default: "Thanks for buying from us.", label: "Footer" }
        };
    }
}
TypeEditor
phraseOne line. The default when type is left out.
textSeveral lines.

section entries group fields under a heading, the same as in config classes. A field can also be a bare string, such as synced: "Synced %count% licenses.".

Translations

Every other language is a JSON file named after the group, holding only the keys you translate:

resources/lang/
├── en/
│   ├── common.json
│   └── messages.js
├── de/
│   ├── common.json
│   └── messages.json
└── fr/
    ├── common.json
    └── messages.json
modules/example/resources/lang/de/messages.json
{
    "synced": "%count% Lizenzen synchronisiert.",
    "failed": "Synchronisierung fehlgeschlagen: %reason%"
}

Missing keys fall back through the chain above. Folders for languages Kora does not support are skipped.

You can also put every language in one resources/lang/translations.json, keyed by language and then group:

{
    "de": { "messages": { "synced": "%count% Lizenzen synchronisiert." } },
    "fr": { "messages": { "synced": "%count% licences synchronisées." } }
}

Reading Text

this.kora.modules.lang.phrase("example", "messages", "synced", { count: 12 });
this.kora.modules.lang.value("example", "messages", "footer");
this.kora.modules.lang.values("example", "messages");

phrase replaces each %token% with the value you pass. If the key does not exist it returns the key itself, so a typo shows up instead of an empty message.

All three use the server's language and include anything an admin changed on the Lang page.

Admin Edits

The Lang page lists every module with a lang class. An admin picks a language and changes any field. Edits are saved per language under lang:<module> in Kora's settings and win over your defaults and JSON files. When editing another language, the English text is shown under each field.

Dashboard Text

common.json holds the text the dashboard shows for your module, in each language:

modules/example/resources/lang/de/common.json
{
    "name": "Beispiel",
    "description": "Synchronisiert Lizenzen mit einem anderen Dienst",
    "schema.example.config.settings.label": "Beispiel",
    "schema.example.config.settings.token.label": "API-Token"
}
KeyTranslates
nameThe module name in the sidebar and module list.
descriptionThe module description.
schema.<module>.config.<group>.labelA config group's heading.
schema.<module>.config.<group>.<field>.labelA config field's label.
schema.<module>.lang.<group>.<field>.labelA field's label on the Lang page.

Any other key is added to the dashboard dictionary as is, so your pages can use it. Kora's own dashboard text lives in src/dashboard/lang/<code>/common.json and is not part of a module.