Class LanguageManager

java.lang.Object
com.enhancedechest.lang.LanguageManager

public final class LanguageManager extends Object
Loads the plugin's language files and exposes them as Adventure Components.

Per-viewer localization. Every message/label returned here is a locale-free translatable Component; the actual text is resolved by EnhancedEchestTranslator (registered on the GlobalTranslator) against the recipient client's own locale at send time. So a single shared inventory title, or one broadcast, renders in each viewer's language with no Locale threaded through call sites. All bundled locales (en_US, vi_VN) plus any the operator drops under language/ are loaded up front.

At load each raw YAML value is normalized once into an equivalent MiniMessage string: legacy & strings are converted, {prefix} is inlined, and {placeholder} tokens become <placeholder> argument tags so Argument.string(java.lang.String, java.lang.String) substitutions resolve at render time. Because substitutions are passed as arguments (not spliced into the raw string), a value such as a player-supplied chest name can never inject formatting into a surrounding message.

  • Constructor Details

    • LanguageManager

      public LanguageManager(org.bukkit.plugin.java.JavaPlugin plugin, PluginConfig config, String locale)
  • Method Details

    • reload

      public void reload(String locale)
    • translator

      public EnhancedEchestTranslator translator()
      The Adventure translator to register on the GlobalTranslator (once, in the plugin).
    • get

      public net.kyori.adventure.text.Component get(String key, String... replacements)
      Resolves a message key. Optional replacements are name/value pairs bound to <name> argument tags in the string. The {prefix} is baked in at load time.
    • getGui

      public net.kyori.adventure.text.Component getGui(String key, String... replacements)
      Resolves a GUI/dialog label from gui.yml (no prefix). Same {placeholder} → argument substitution as get(java.lang.String, java.lang.String...). Used for the /ec list dialog and inventory-menu labels.
    • getRich

      public net.kyori.adventure.text.Component getRich(String key, String name, net.kyori.adventure.text.ComponentLike value)
      Like get(java.lang.String, java.lang.String...) but binds a single argument to a ready-made ComponentLike rather than a plain string — for values that must carry their own formatting or interactivity (e.g. the update download link, whose click event a plain-text argument could not hold).
    • getArgs

      public net.kyori.adventure.text.Component getArgs(String key, net.kyori.adventure.text.ComponentLike... args)
      Deferred message with an arbitrary mix of arguments — pass ready-made Argument.string(java.lang.String, java.lang.String) / Argument.component(java.lang.String, net.kyori.adventure.text.ComponentLike) objects. Used when at least one argument is itself a Component that must localize per viewer (e.g. a duration), which the plain-string get(java.lang.String, java.lang.String...) can't carry.
    • getGuiArgs

      public net.kyori.adventure.text.Component getGuiArgs(Locale locale, String key, net.kyori.adventure.text.ComponentLike... args)
      Eager, locale-rendered GUI label taking the same arbitrary Argument mix as getArgs(java.lang.String, net.kyori.adventure.text.ComponentLike...). For Dialog-API / inventory-item surfaces (which Paper does not run through the GlobalTranslator), so callers pass the viewer's player.locale(). A component argument's own nested translatables are resolved by this same render pass, so a duration inserted here localizes too.
    • duration

      public net.kyori.adventure.text.Component duration(long millis)
      A remaining duration ("6d 23h", "6 ngày 23 giờ", ...) as a per-viewer translatable Component: the two most significant units, each rendered from enhancedechest.msg.duration.<unit> (template {count}<unit-label>) so operators localize the unit labels and number/label spacing in messages.yml. Insert it into a message with getRich(java.lang.String, java.lang.String, net.kyori.adventure.text.ComponentLike)/getArgs(java.lang.String, net.kyori.adventure.text.ComponentLike...) (chat) or getGuiArgs(java.util.Locale, java.lang.String, net.kyori.adventure.text.ComponentLike...) (dialogs/inventory), never get(java.lang.String, java.lang.String...) (which would flatten it to a key).
      See Also:
    • get

      public net.kyori.adventure.text.Component get(Locale locale, String key, String... replacements)
      Locale-resolved variants of get(java.lang.String, java.lang.String...)/getGui(java.lang.String, java.lang.String...)/getChestLabel(java.util.Locale, int, java.lang.String, com.enhancedechest.model.ChestKind), returning a component already rendered for locale instead of a deferred translatable.

      Needed for surfaces Paper does not run through the GlobalTranslator on the way to the client — the Dialog API and inventory item names/lore — where a raw translatable would reach the client and show as its literal key. Chat and inventory titles are rendered by Paper per-viewer, so those keep using the deferred get(java.lang.String, java.lang.String...)/getChestLabel(java.util.Locale, int, java.lang.String, com.enhancedechest.model.ChestKind) directly. Rendering here is per-viewer, so callers must pass the specific viewer's player.locale().

    • getGui

      public net.kyori.adventure.text.Component getGui(Locale locale, String key, String... replacements)
    • getChestLabel

      public net.kyori.adventure.text.Component getChestLabel(Locale locale, int index, @Nullable @Nullable String customName, ChestKind kind)
    • getChestTitle

      public net.kyori.adventure.text.Component getChestTitle(int index, @Nullable @Nullable String customName)
      Resolves the inventory/display title for a chest. A non-blank custom name is shown verbatim (player-supplied formatting via chestName(java.lang.String)). Otherwise chest #1 uses the un-numbered base title and chests 2+ use the numbered template — both localized per viewer.
    • chestName

      public net.kyori.adventure.text.Component chestName(String name)
      Renders a player-supplied chest name to a display Component. When enderchest.features.rename-colors is on, colour/hex/gradient formatting is applied — MiniMessage when the name contains < (via the restricted NAME_MINI, so no interactive tags), otherwise legacy &/&#RRGGBB codes. When off, the name is shown verbatim. Any parse error falls back to plain text, so a malformed name is never fatal.
    • plainChestName

      public String plainChestName(String name)
      The plain, formatting-stripped text a chest name would display as — used to match against the rename blacklist so colour codes or MiniMessage tags can't be used to smuggle a banned word past the filter (e.g. ad<red>min or ad&cmin).
    • getChestLabel

      public net.kyori.adventure.text.Component getChestLabel(int index, @Nullable @Nullable String customName, ChestKind kind)
      Resolves a chest's display label. Temporary chests get their own dedicated title (enderchest.title-temp) rather than the numbered "Ender Chest N". Used for inventory window titles and dialog buttons where a chest's kind should be visible.