Lang

Lang

The lang module manages localisation files, custom messages, and per-player language overrides.

Why a language manager

Hardcoded strings mean one language for everyone and a redeploy for every typo. Rolling your own localisation means a file per language, a lookup with a fallback when a key is missing, argument substitution, and somehow tracking which language each player actually speaks.

MagicUtils lang does that for you: message catalogs per scope, a fallback language, MiniMessage formatting, argument and placeholder substitution, and per-player locale resolution that can follow the player's client language. You reference a key; the right translation for the right audience comes back as an Adventure component.

Before (hardcoded, one language, manual formatting):

java
player.sendMessage(ChatColor.GREEN + "You have " + balance + " coins");

After (keyed message, per-player language, MiniMessage):

java
// lang/en.yml:  myplugin.balance: "<green>You have {0} coins</green>"// lang/de.yml:  myplugin.balance: "<green>Du hast {0} Münzen</green>"messages.send(player, "myplugin.balance", balance);

Setup

Manual setup:

java
LanguageManager languageManager = new LanguageManager(platform, configManager);languageManager.init("en");languageManager.setFallbackLanguage("en");languageManager.addMagicUtilsMessages();Messages.register("myplugin", languageManager);logger.setLanguageManager(languageManager);

Bootstrap helpers perform the same wiring automatically when language support is enabled.

File Layout And Formats

Language files live under lang/{lang}.{ext} inside the platform config directory.

  • YAML is supported when magicutils-config-yaml is installed.
  • JSON / JSONC work out of the box.
  • TOML works when magicutils-config-toml is installed.

Messages.register(scope, manager) keeps each plugin or mod isolated. Use Messages.setLanguageManager(...) only when you need the legacy global fallback.

Resolving Messages

java
MessagesView messages = Messages.view("myplugin");// Look up by key. The first argument of the recipient-aware overloads is always// the recipient (used to pick their language); pass null for no specific player.Component title = messages.get("myplugin.welcome");messages.send(playerAudience, "myplugin.goodbye");// Positional {0}, {1}, ... arguments are passed after the key.String raw = messages.getRaw(playerAudience, "myplugin.balance", 42);Component rich = messages.get(playerAudience, "myplugin.balance", 42);

Messages uses MiniMessage for rich output. Positional arguments ({0}, {1}, ...) are substituted from the trailing Object... args. When you need to pin a language explicitly or control escaping, use the query builder (see below).

Query builder

Messages.query(...) (and MessagesView.query(...)) gives fine-grained control over recipient, language, arguments, and escaping:

java
Component c = Messages.query("myplugin.balance")        .audience(playerAudience)   // picks the recipient's language        .language("uk")             // or pin a language explicitly        .args(42)        .component();               // or .raw() for the plain string// Resolve and send in one call:Messages.query("myplugin.welcome").audience(playerAudience).send();

Call .escaped() to treat argument values as literal text (MiniMessage tags in them are not parsed).

Per-Player Languages

java
languageManager.setPlayerLanguage(playerUuid, "uk");String msg = languageManager.getMessageFor(audience, "myplugin.welcome");

setPlayerLanguage(...) accepts UUIDs, Audience, or player objects that expose getUniqueId(). getMessageFor(audience, key) resolves a message in the recipient's language.

Following the client locale

Instead of setting each player's language by hand, you can let MagicUtils track the client's own locale. The bootstrap helpers enable this by default; to wire it manually, bind the language manager to the platform:

java
languageManager.bindClientLocaleSync(platform);

Each player then sees messages in the language their client reports (falling back to the fallback language when it is not available).

Custom Messages

java
languageManager.putCustomMessage("en", "myplugin.welcome", "<green>Hello</green>");

Custom messages are persisted under the messages section of the active language file.

Async And Smart Loading

Language loading touches disk. Use the async or smart helpers on blocking-sensitive threads:

java
languageManager.loadLanguageAsync("en");languageManager.setLanguageAsync("en");languageManager.reloadAsync();languageManager.loadLanguageSmart("en");languageManager.setLanguageSmart("en");languageManager.reloadSmart();

Fallbacks And Missing Keys

java
languageManager.setFallbackLanguage("en");languageManager.setLogMissingMessages(true);

When the current language is missing a key, MagicUtils falls back to the configured fallback language before logging a missing-message warning.