# Languages

URL: https://zerodev.ca/docs/kora/developer-documentation/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/`:

```js title="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" }
        };
    }
}
```

| Type     | Editor                                         |
| -------- | ---------------------------------------------- |
| `phrase` | One line. The default when `type` is left out. |
| `text`   | Several lines.                                 |

`section` entries group fields under a heading, the same as in [config classes](/docs/kora/developer-documentation/configuration#sections). 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:

```text
resources/lang/
├── en/
│   ├── common.json
│   └── messages.js
├── de/
│   ├── common.json
│   └── messages.json
└── fr/
    ├── common.json
    └── messages.json
```

```json title="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:

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

## Reading Text

```js
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:

```json title="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"
}
```

| Key                                            | Translates                                      |
| ---------------------------------------------- | ----------------------------------------------- |
| `name`                                         | The module name in the sidebar and module list. |
| `description`                                  | The module description.                         |
| `schema.<module>.config.<group>.label`         | A config group's heading.                       |
| `schema.<module>.config.<group>.<field>.label` | A config field's label.                         |
| `schema.<module>.lang.<group>.<field>.label`   | A field's label on the Lang page.               |

Any other key is added to the dashboard dictionary as is, so your [pages](/docs/kora/developer-documentation/pages) can use it. Kora's own dashboard text lives in `src/dashboard/lang/<code>/common.json` and is not part of a module.
