Skip to content

Migrate locale formatting from legacy & codes to MiniMessage (#2888)#2894

Merged
tastybento merged 12 commits intodevelopfrom
minimessage-migration
Apr 1, 2026
Merged

Migrate locale formatting from legacy & codes to MiniMessage (#2888)#2894
tastybento merged 12 commits intodevelopfrom
minimessage-migration

Conversation

@tastybento
Copy link
Copy Markdown
Member

@tastybento tastybento commented Apr 1, 2026

Summary

  • Replace Bungee TextComponent messaging with Adventure API MiniMessage throughout the codebase
  • Convert all 23 locale YAML files from legacy & codes to MiniMessage tags (e.g., &c<red>)
  • Add new Component-based public API methods: User.sendMessage(Component), getTranslationAsComponent(), sendMiniMessage()
  • Migrate Panel system to Component-based displayName()/lore()/createInventory()
  • Fix all Bukkit Conversation prompts to render MiniMessage formatting
  • Add Util.parseMiniMessageOrLegacy() auto-detection for backwards compatibility with legacy addon locale files
  • Handle mixed MiniMessage + legacy & code content (from addon variables substituted into MiniMessage locale strings)
  • Add translated missing keys (40 per file) to all 22 non-English locale files
  • Deprecate Util.translateColorCodes() and stripSpaceAfterColorCodes() (kept for addon compat)

Closes #2888

Test plan

  • All 2660 unit tests pass
  • Verify flag settings panels show correct green/red rank colors when cycling
  • Verify panel clicks work (don't close inventory)
  • Verify island creation panel shows bundle names without raw MiniMessage tags
  • Verify Blueprint management conversations show formatted text
  • Verify /bbox reload reloads new MiniMessage locale files correctly
  • Verify legacy addon locale files with & codes still display correctly (auto-detection)

🤖 Generated with Claude Code

tastybento and others added 12 commits April 1, 2026 10:45
Replace Bungee TextComponent messaging with Adventure API MiniMessage
throughout the codebase. This modernizes the locale/translation system
while maintaining backwards compatibility with legacy addon locale files
that still use & color codes (auto-detected and converted at runtime).

Key changes:
- Add MiniMessage infrastructure to Util (parse, convert, detect legacy)
- Refactor User.sendRawMessage() from Bungee to Adventure Components
- Add User.sendMessage(Component), getTranslationAsComponent() methods
- Convert all 23 locale YAML files from &-codes to MiniMessage tags
- Migrate Panel system to Component-based displayName/lore/title
- Fix LocalesManager.analyzeLocales() NamedTextColor string concat bug
- Deprecate Util.translateColorCodes() and stripSpaceAfterColorCodes()
- Update test infrastructure (checkSpigotMessage captures Components)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… migration

Two bugs introduced by the MiniMessage migration:

1. Rank lore colors: locale strings had empty color tags (e.g. <red></red>)
   with the rank name concatenated after the closing tag, so it rendered
   without color. Fixed by adding [rank] placeholder inside the color tags
   and using TextVariables.RANK substitution in Flag, IslandTeamGUI, and
   CommandRankClickListener.

2. Panel click closing inventory: PanelListenerManager compared the rendered
   view title (plain text) against the raw panel name (containing MiniMessage
   tags) using Util.stripColor() which only strips § codes. The mismatch
   caused every click to hit the "wrong name" branch and close the inventory.
   Fixed by parsing the panel name to plain text via MiniMessage before
   comparing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ted text

After converting locale files to MiniMessage format, getTranslation()
still only handled legacy & codes via Util.translateColorCodes(). Strings
with MiniMessage tags like <green>text</green> passed through unprocessed,
causing raw tags to appear in contexts expecting legacy §-coded strings
(e.g., Bukkit conversation prompts in SettingsTab reset-to-default).

Fixed by auto-detecting the format in getTranslation(): legacy strings
go through translateColorCodes() as before; MiniMessage strings are
parsed to Component then serialized back to legacy § format.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
YAML block scalars (|) produce strings with literal \n newlines.
When getTranslation() parsed these through MiniMessage → Component →
LegacyComponentSerializer, the newlines were not preserved, causing
multi-line lore (e.g., Blueprint cost icon instructions) to render
as a single line with unicode LF characters.

Fixed by splitting multi-line strings on \n, processing each line
independently through MiniMessage, then rejoining with \n so that
PanelItemBuilder.description() can split them into separate lore lines.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…name lore

Two issues fixed:

1. Bukkit's Conversation API sends prompt text via Player.sendRawMessage()
   which does not parse MiniMessage or legacy § codes in modern Paper.
   All 9 conversation prompt classes now send formatted messages via
   User.sendRawMessage() (which parses through MiniMessage) and return
   empty string to the conversation API.

2. PanelItemBuilder.name() now splits multi-line strings (from YAML block
   scalars) on \n — first line becomes the item name, remaining lines are
   added as description/lore entries, since Minecraft item names cannot
   contain newlines.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Added 40 missing keys per locale file that existed only in en-US.yml:
- prefixes.Islands
- commands.help.page
- commands.admin.blueprint.management.{edit-commands,no-commands,commands.*}
- commands.bentobox.{placeholders,dump-placeholders}.*
- panels.placeholder.* and panels.placeholder-list.*

All keys translated into their respective languages: cs, de, es, fr,
hr, hu, id, it, ja, ko, lv, nl, pl, pt-BR, pt, ro, ru, tr, uk, vi,
zh-CN, zh-HK.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…tags

When a MiniMessage locale string (e.g., <bold>[name]</bold>) had a
variable substituted with a legacy &-coded value from an addon (e.g.,
&eThe Original SkyBlock), getTranslation() detected legacy codes and
took the legacy-only path, leaving MiniMessage tags like </yellow>
as literal text in the output.

Fixed by detecting mixed content (both legacy & codes AND MiniMessage
<tags> present) and converting legacy codes to MiniMessage first before
parsing everything through MiniMessage. Refactored both getTranslation()
overloads to use a shared convertToLegacy()/convertLineToLegacy() path.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…lder name()

PanelItemBuilder.name() and PanelBuilder.name() called
Util.translateColorCodes() which processes strings through
LegacyComponentSerializer with '&' as its format character. When
getTranslation() returns §-coded strings, translateColorCodes doesn't
recognize § codes (it only handles &), corrupting the formatting and
causing MiniMessage closing tags like </yellow> to appear as literal
text in panel item names.

The translateColorCodes() call was redundant — PanelItem.setName()
already calls Util.parseMiniMessageOrLegacy() which properly handles
both MiniMessage tags and legacy §/& codes. Removing the intermediate
processing fixes the double-conversion corruption.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…MM content

Root cause: legacyToMiniMessage() produced wrong tag nesting when existing
MiniMessage tags were present. For input <bold>&eText</bold>, it generated
<bold><yellow>Text</bold></yellow> — the </yellow> came after </bold>,
which MiniMessage couldn't match, rendering it as literal text.

Fix: Added Util.replaceLegacyCodesInline() which replaces &/§ codes with
MiniMessage opening tags only (no closing tags). MiniMessage handles
unclosed tags correctly — they apply until overridden. This avoids the
nesting conflict entirely.

Applied in both User.convertLineToLegacy() (for getTranslation) and
Util.parseMiniMessageOrLegacy() (for PanelItem.setName), plus removed
debug logging from the investigation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Legacy addon locale files use rank format strings like '&a- &2' without
a [rank] placeholder. The MiniMessage migration changed the Java code to
use TextVariables.RANK substitution, but when the locale string doesn't
contain [rank], the rank name never appears.

Fixed by adding getRankTranslation() helpers that try [rank] substitution
first, and fall back to concatenation (the original behavior) when the
rank name is not found in the result.

Applied to Flag.java, IslandTeamGUI.java, and CommandRankClickListener.java.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud bot commented Apr 1, 2026

@tastybento tastybento merged commit 6fbb97e into develop Apr 1, 2026
3 checks passed
@tastybento tastybento deleted the minimessage-migration branch April 1, 2026 21:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Minimessage format

1 participant