[{"data":1,"prerenderedAt":284},["ShallowReactive",2],{"docs-\u002Fmodules\u002Flang":3},{"id":4,"title":5,"body":6,"description":274,"extension":275,"meta":276,"navTitle":277,"navigation":278,"path":279,"rawbody":280,"seo":281,"stem":282,"__hash__":283},"docs\u002Fmodules\u002Flang.md","Lang",{"type":7,"value":8,"toc":258},"minimark",[9,13,17,22,25,28,35,46,52,58,62,65,71,74,78,85,105,115,119,125,143,148,158,164,171,175,181,199,203,206,212,215,219,225,232,236,239,245,249,255],[10,11,5],"h1",{"id":12},"lang",[14,15,16],"p",{},"The lang module manages localisation files, custom messages, and per-player\nlanguage overrides.",[18,19,21],"h2",{"id":20},"why-a-language-manager","Why a language manager",[14,23,24],{},"Hardcoded strings mean one language for everyone and a redeploy for every typo.\nRolling your own localisation means a file per language, a lookup with a\nfallback when a key is missing, argument substitution, and somehow tracking\nwhich language each player actually speaks.",[14,26,27],{},"MagicUtils lang does that for you: message catalogs per scope, a fallback\nlanguage, MiniMessage formatting, argument and placeholder substitution, and\nper-player locale resolution that can follow the player's client language. You\nreference a key; the right translation for the right audience comes back as an\nAdventure component.",[14,29,30,34],{},[31,32,33],"strong",{},"Before"," (hardcoded, one language, manual formatting):",[36,37,43],"pre",{"className":38,"code":40,"language":41,"meta":42},[39],"language-java","player.sendMessage(ChatColor.GREEN + \"You have \" + balance + \" coins\");\n","java","",[44,45,40],"code",{"__ignoreMap":42},[14,47,48,51],{},[31,49,50],{},"After"," (keyed message, per-player language, MiniMessage):",[36,53,56],{"className":54,"code":55,"language":41,"meta":42},[39],"\u002F\u002F lang\u002Fen.yml:  myplugin.balance: \"\u003Cgreen>You have {0} coins\u003C\u002Fgreen>\"\n\u002F\u002F lang\u002Fde.yml:  myplugin.balance: \"\u003Cgreen>Du hast {0} Münzen\u003C\u002Fgreen>\"\nmessages.send(player, \"myplugin.balance\", balance);\n",[44,57,55],{"__ignoreMap":42},[18,59,61],{"id":60},"setup","Setup",[14,63,64],{},"Manual setup:",[36,66,69],{"className":67,"code":68,"language":41,"meta":42},[39],"LanguageManager languageManager = new LanguageManager(platform, configManager);\nlanguageManager.init(\"en\");\nlanguageManager.setFallbackLanguage(\"en\");\nlanguageManager.addMagicUtilsMessages();\n\nMessages.register(\"myplugin\", languageManager);\nlogger.setLanguageManager(languageManager);\n",[44,70,68],{"__ignoreMap":42},[14,72,73],{},"Bootstrap helpers perform the same wiring automatically when language support is\nenabled.",[18,75,77],{"id":76},"file-layout-and-formats","File Layout And Formats",[14,79,80,81,84],{},"Language files live under ",[44,82,83],{},"lang\u002F{lang}.{ext}"," inside the platform config\ndirectory.",[86,87,88,96,99],"ul",{},[89,90,91,92,95],"li",{},"YAML is supported when ",[44,93,94],{},"magicutils-config-yaml"," is installed.",[89,97,98],{},"JSON \u002F JSONC work out of the box.",[89,100,101,102,95],{},"TOML works when ",[44,103,104],{},"magicutils-config-toml",[14,106,107,110,111,114],{},[44,108,109],{},"Messages.register(scope, manager)"," keeps each plugin or mod isolated. Use\n",[44,112,113],{},"Messages.setLanguageManager(...)"," only when you need the legacy global\nfallback.",[18,116,118],{"id":117},"resolving-messages","Resolving Messages",[36,120,123],{"className":121,"code":122,"language":41,"meta":42},[39],"MessagesView messages = Messages.view(\"myplugin\");\n\n\u002F\u002F Look up by key. The first argument of the recipient-aware overloads is always\n\u002F\u002F the recipient (used to pick their language); pass null for no specific player.\nComponent title = messages.get(\"myplugin.welcome\");\nmessages.send(playerAudience, \"myplugin.goodbye\");\n\n\u002F\u002F Positional {0}, {1}, ... arguments are passed after the key.\nString raw = messages.getRaw(playerAudience, \"myplugin.balance\", 42);\nComponent rich = messages.get(playerAudience, \"myplugin.balance\", 42);\n",[44,124,122],{"__ignoreMap":42},[14,126,127,130,131,134,135,138,139,142],{},[44,128,129],{},"Messages"," uses MiniMessage for rich output. Positional arguments (",[44,132,133],{},"{0}",", ",[44,136,137],{},"{1}",",\n...) are substituted from the trailing ",[44,140,141],{},"Object..."," args. When you need to pin a\nlanguage explicitly or control escaping, use the query builder (see below).",[144,145,147],"h3",{"id":146},"query-builder","Query builder",[14,149,150,153,154,157],{},[44,151,152],{},"Messages.query(...)"," (and ",[44,155,156],{},"MessagesView.query(...)",") gives fine-grained control\nover recipient, language, arguments, and escaping:",[36,159,162],{"className":160,"code":161,"language":41,"meta":42},[39],"Component c = Messages.query(\"myplugin.balance\")\n        .audience(playerAudience)   \u002F\u002F picks the recipient's language\n        .language(\"uk\")             \u002F\u002F or pin a language explicitly\n        .args(42)\n        .component();               \u002F\u002F or .raw() for the plain string\n\n\u002F\u002F Resolve and send in one call:\nMessages.query(\"myplugin.welcome\").audience(playerAudience).send();\n",[44,163,161],{"__ignoreMap":42},[14,165,166,167,170],{},"Call ",[44,168,169],{},".escaped()"," to treat argument values as literal text (MiniMessage tags in\nthem are not parsed).",[18,172,174],{"id":173},"per-player-languages","Per-Player Languages",[36,176,179],{"className":177,"code":178,"language":41,"meta":42},[39],"languageManager.setPlayerLanguage(playerUuid, \"uk\");\nString msg = languageManager.getMessageFor(audience, \"myplugin.welcome\");\n",[44,180,178],{"__ignoreMap":42},[14,182,183,186,187,190,191,194,195,198],{},[44,184,185],{},"setPlayerLanguage(...)"," accepts UUIDs, ",[44,188,189],{},"Audience",", or player objects that\nexpose ",[44,192,193],{},"getUniqueId()",". ",[44,196,197],{},"getMessageFor(audience, key)"," resolves a message in the\nrecipient's language.",[144,200,202],{"id":201},"following-the-client-locale","Following the client locale",[14,204,205],{},"Instead of setting each player's language by hand, you can let MagicUtils track\nthe client's own locale. The bootstrap helpers enable this by default; to wire\nit manually, bind the language manager to the platform:",[36,207,210],{"className":208,"code":209,"language":41,"meta":42},[39],"languageManager.bindClientLocaleSync(platform);\n",[44,211,209],{"__ignoreMap":42},[14,213,214],{},"Each player then sees messages in the language their client reports (falling\nback to the fallback language when it is not available).",[18,216,218],{"id":217},"custom-messages","Custom Messages",[36,220,223],{"className":221,"code":222,"language":41,"meta":42},[39],"languageManager.putCustomMessage(\"en\", \"myplugin.welcome\", \"\u003Cgreen>Hello\u003C\u002Fgreen>\");\n",[44,224,222],{"__ignoreMap":42},[14,226,227,228,231],{},"Custom messages are persisted under the ",[44,229,230],{},"messages"," section of the active\nlanguage file.",[18,233,235],{"id":234},"async-and-smart-loading","Async And Smart Loading",[14,237,238],{},"Language loading touches disk. Use the async or smart helpers on\nblocking-sensitive threads:",[36,240,243],{"className":241,"code":242,"language":41,"meta":42},[39],"languageManager.loadLanguageAsync(\"en\");\nlanguageManager.setLanguageAsync(\"en\");\nlanguageManager.reloadAsync();\n\nlanguageManager.loadLanguageSmart(\"en\");\nlanguageManager.setLanguageSmart(\"en\");\nlanguageManager.reloadSmart();\n",[44,244,242],{"__ignoreMap":42},[18,246,248],{"id":247},"fallbacks-and-missing-keys","Fallbacks And Missing Keys",[36,250,253],{"className":251,"code":252,"language":41,"meta":42},[39],"languageManager.setFallbackLanguage(\"en\");\nlanguageManager.setLogMissingMessages(true);\n",[44,254,252],{"__ignoreMap":42},[14,256,257],{},"When the current language is missing a key, MagicUtils falls back to the\nconfigured fallback language before logging a missing-message warning.",{"title":42,"searchDepth":259,"depth":259,"links":260},3,[261,263,264,265,268,271,272,273],{"id":20,"depth":262,"text":21},2,{"id":60,"depth":262,"text":61},{"id":76,"depth":262,"text":77},{"id":117,"depth":262,"text":118,"children":266},[267],{"id":146,"depth":259,"text":147},{"id":173,"depth":262,"text":174,"children":269},[270],{"id":201,"depth":259,"text":202},{"id":217,"depth":262,"text":218},{"id":234,"depth":262,"text":235},{"id":247,"depth":262,"text":248},"The MagicUtils language manager: message catalogs, per-player locales, translation helpers, and MiniMessage-style formatting.","md",{},null,true,"\u002Fmodules\u002Flang","---\ntitle: Lang\ndescription: 'The MagicUtils language manager: message catalogs, per-player locales, translation helpers, and MiniMessage-style formatting.'\n---\n\n# Lang\n\nThe lang module manages localisation files, custom messages, and per-player\nlanguage overrides.\n\n## Why a language manager\n\nHardcoded strings mean one language for everyone and a redeploy for every typo.\nRolling your own localisation means a file per language, a lookup with a\nfallback when a key is missing, argument substitution, and somehow tracking\nwhich language each player actually speaks.\n\nMagicUtils lang does that for you: message catalogs per scope, a fallback\nlanguage, MiniMessage formatting, argument and placeholder substitution, and\nper-player locale resolution that can follow the player's client language. You\nreference a key; the right translation for the right audience comes back as an\nAdventure component.\n\n**Before** (hardcoded, one language, manual formatting):\n\n```java\nplayer.sendMessage(ChatColor.GREEN + \"You have \" + balance + \" coins\");\n```\n\n**After** (keyed message, per-player language, MiniMessage):\n\n```java\n\u002F\u002F lang\u002Fen.yml:  myplugin.balance: \"\u003Cgreen>You have {0} coins\u003C\u002Fgreen>\"\n\u002F\u002F lang\u002Fde.yml:  myplugin.balance: \"\u003Cgreen>Du hast {0} Münzen\u003C\u002Fgreen>\"\nmessages.send(player, \"myplugin.balance\", balance);\n```\n\n## Setup\n\nManual setup:\n\n```java\nLanguageManager languageManager = new LanguageManager(platform, configManager);\nlanguageManager.init(\"en\");\nlanguageManager.setFallbackLanguage(\"en\");\nlanguageManager.addMagicUtilsMessages();\n\nMessages.register(\"myplugin\", languageManager);\nlogger.setLanguageManager(languageManager);\n```\n\nBootstrap helpers perform the same wiring automatically when language support is\nenabled.\n\n## File Layout And Formats\n\nLanguage files live under `lang\u002F{lang}.{ext}` inside the platform config\ndirectory.\n\n- YAML is supported when `magicutils-config-yaml` is installed.\n- JSON \u002F JSONC work out of the box.\n- TOML works when `magicutils-config-toml` is installed.\n\n`Messages.register(scope, manager)` keeps each plugin or mod isolated. Use\n`Messages.setLanguageManager(...)` only when you need the legacy global\nfallback.\n\n## Resolving Messages\n\n```java\nMessagesView messages = Messages.view(\"myplugin\");\n\n\u002F\u002F Look up by key. The first argument of the recipient-aware overloads is always\n\u002F\u002F the recipient (used to pick their language); pass null for no specific player.\nComponent title = messages.get(\"myplugin.welcome\");\nmessages.send(playerAudience, \"myplugin.goodbye\");\n\n\u002F\u002F Positional {0}, {1}, ... arguments are passed after the key.\nString raw = messages.getRaw(playerAudience, \"myplugin.balance\", 42);\nComponent rich = messages.get(playerAudience, \"myplugin.balance\", 42);\n```\n\n`Messages` uses MiniMessage for rich output. Positional arguments (`{0}`, `{1}`,\n...) are substituted from the trailing `Object...` args. When you need to pin a\nlanguage explicitly or control escaping, use the query builder (see below).\n\n### Query builder\n\n`Messages.query(...)` (and `MessagesView.query(...)`) gives fine-grained control\nover recipient, language, arguments, and escaping:\n\n```java\nComponent c = Messages.query(\"myplugin.balance\")\n        .audience(playerAudience)   \u002F\u002F picks the recipient's language\n        .language(\"uk\")             \u002F\u002F or pin a language explicitly\n        .args(42)\n        .component();               \u002F\u002F or .raw() for the plain string\n\n\u002F\u002F Resolve and send in one call:\nMessages.query(\"myplugin.welcome\").audience(playerAudience).send();\n```\n\nCall `.escaped()` to treat argument values as literal text (MiniMessage tags in\nthem are not parsed).\n\n## Per-Player Languages\n\n```java\nlanguageManager.setPlayerLanguage(playerUuid, \"uk\");\nString msg = languageManager.getMessageFor(audience, \"myplugin.welcome\");\n```\n\n`setPlayerLanguage(...)` accepts UUIDs, `Audience`, or player objects that\nexpose `getUniqueId()`. `getMessageFor(audience, key)` resolves a message in the\nrecipient's language.\n\n### Following the client locale\n\nInstead of setting each player's language by hand, you can let MagicUtils track\nthe client's own locale. The bootstrap helpers enable this by default; to wire\nit manually, bind the language manager to the platform:\n\n```java\nlanguageManager.bindClientLocaleSync(platform);\n```\n\nEach player then sees messages in the language their client reports (falling\nback to the fallback language when it is not available).\n\n## Custom Messages\n\n```java\nlanguageManager.putCustomMessage(\"en\", \"myplugin.welcome\", \"\u003Cgreen>Hello\u003C\u002Fgreen>\");\n```\n\nCustom messages are persisted under the `messages` section of the active\nlanguage file.\n\n## Async And Smart Loading\n\nLanguage loading touches disk. Use the async or smart helpers on\nblocking-sensitive threads:\n\n```java\nlanguageManager.loadLanguageAsync(\"en\");\nlanguageManager.setLanguageAsync(\"en\");\nlanguageManager.reloadAsync();\n\nlanguageManager.loadLanguageSmart(\"en\");\nlanguageManager.setLanguageSmart(\"en\");\nlanguageManager.reloadSmart();\n```\n\n## Fallbacks And Missing Keys\n\n```java\nlanguageManager.setFallbackLanguage(\"en\");\nlanguageManager.setLogMissingMessages(true);\n```\n\nWhen the current language is missing a key, MagicUtils falls back to the\nconfigured fallback language before logging a missing-message warning.\n",{"title":5,"description":274},"modules\u002Flang","sMfxtZAVXYhyPXh41ZiZh6cnK-6KKv2OsmyriYPxZAg",1783944487327]