diff --git a/src/main/resources/messages/messages_es.yml b/src/main/resources/messages/messages_es.yml index 91c49cd..b285676 100644 --- a/src/main/resources/messages/messages_es.yml +++ b/src/main/resources/messages/messages_es.yml @@ -227,7 +227,6 @@ player-shops: price-prefix: "&6" price-suffix: " &7por &6{price}" out-of-stock-line: "&cAgotado" - messages: messages: menu: inventory-title: "&2Configuración de Player Shop" diff --git a/src/main/resources/messages/messages_nl.yml b/src/main/resources/messages/messages_nl.yml index 08eda17..014c42b 100644 --- a/src/main/resources/messages/messages_nl.yml +++ b/src/main/resources/messages/messages_nl.yml @@ -248,6 +248,56 @@ player-shops: unknown-item: singular: "&bItem" plural: "&bItems" + # Player shop message keys (Dutch) + no-permission-create: "&cJe hebt geen toestemming om winkels te maken." + sign-requires-chest: "&cWinkelschilden moeten aan een kist bevestigd zijn." + enter-quantity: "&cVoer de hoeveelheid in op de tweede regel." + quantity-prompt: "&cAantal?" + enter-price: "&cVoer de prijs in op de derde regel." + price-prompt: "&cPrijs?" + using-saved-settings: "&aGebruikt je opgeslagen /playershop instellingen." + chest-access-denied: "&cJe kunt de kist van een andere speler niet openen." + break-denied: "&cJe kunt de winkel van iemand anders niet slopen." + shop-removed: "&eWinkel verwijderd." + creation-invalid-configuration: "&cOngeldige winkelconfiguratie." + creation-quantity-positive: "&cHoeveelheid moet groter zijn dan nul." + creation-quantity-min: "&cHoeveelheid moet minimaal &b{min}&c zijn." + creation-quantity-max: "&cHoeveelheid mag niet meer zijn dan &b{max}&c." + creation-price-positive: "&cPrijs moet groter zijn dan nul." + creation-price-min: "&cPrijs moet minimaal &6{min}&c zijn." + creation-price-max: "&cPrijs mag niet meer zijn dan &6{max}&c." + creation-sign-in-use: "&cEr is al een winkel op dit bord." + creation-chest-unresolved: "&cWinkelkisten konden niet worden gevonden." + creation-chest-in-use: "&cEen winkel gebruikt die kist al." + creation-chest-inaccessible: "&cKan geen toegang krijgen tot de kist." + creation-selected-item-missing: "&cDe kist bevat het geselecteerde item uit /playershop niet." + creation-item-missing: "&cPlaats het item dat je wilt verkopen in de kist." + creation-insufficient-stock: "&cDe kist bevat niet genoeg items om de winkel te starten." + creation-success: "&aWinkel succesvol aangemaakt!" + purchase-invalid: "&cOngeldige winkel aankoop poging." + purchase-no-permission: "&cJe hebt geen toestemming om bij winkels te kopen." + purchase-no-economy: "&cDe winkel is momenteel niet beschikbaar omdat er geen economyleverancier is geconfigureerd." + purchase-own-shop: "&cJe kunt niet bij je eigen winkel kopen." + purchase-missing-chest: "&cDe winkelkist ontbreekt. De aanbieding is verwijderd." + purchase-out-of-stock: "&cDeze winkel is momenteel uitverkocht." + purchase-no-space: "&cJe hebt niet genoeg ruimte in je inventaris." + purchase-transaction-failed: "&cTransactie mislukt: {error}" + purchase-owner-notify: "&b{buyer} &aheeft &b{item}&a gekocht voor &6{price}&a." + purchase-buyer-success: "&a{item}&a gekocht van &b{seller}&a voor &6{price}&a." + unknown-seller-name: "de verkoper" + setup-open: "&aConfigureer je spelerswinkel instellingen en bevestig om op te slaan." + setup-item-selected: "&aGeselecteerd &b{item}&a om te verkopen." + setup-item-cleared: "&eGeselecteerd item gewist. De inhoud van de kist bepaalt wat de winkel verkoopt." + setup-select-item: "&eKlik op een item in je inventaris om te kiezen wat je wilt verkopen." + setup-saved: "&aSpelerswinkel instellingen opgeslagen. Plaats een [playershop] bord op een kist om ze te gebruiken." + setup-quantity-chat-prompt: "&eTyp de hoeveelheid om te verkopen in de chat, of typ cancel om te stoppen." + setup-price-chat-prompt: "&eTyp de prijs in de chat, of typ cancel om te stoppen." + setup-chat-cancelled: "&eInvoer geannuleerd. Vorige waarde behouden." + setup-chat-invalid-number: "&cVoer een geldig nummer in." + setup-quantity-updated: "&aHoeveelheid ingesteld op &b{amount}&a." + setup-price-updated: "&aPrijs ingesteld op &6{price}&a." + command-players-only: "&cAlleen spelers kunnen dit commando gebruiken." + command-disabled: "&cSpelerswinkels zijn momenteel uitgeschakeld." # English fallback keys added from messages_en.yml to ensure full key coverage # (keep existing translations above; these are used when a translation is missing) @@ -262,6 +312,7 @@ shop: cannot-sell-line: "&7This item cannot be sold." buy-only-shift-line: "&7Shift-click {bulk_amount}: &a{buy_bulk_total}" spawner-display-name: "&f{spawner}" + prices-may-change: "&7Prices may change over time." categories: building: name: "&eBuilding Blocks" @@ -353,9 +404,6 @@ shop: menu: title: "&aWood & Nature" - common: - prices-may-change: "&7Prices may change over time." - menu: main: title: "&aServer Shop" @@ -377,11 +425,22 @@ shop: filter-label: "&eFilter: {filter}" no-stocks: "&cNo tradable stocks found." item-format: "&e{item} &7- &6{price}" + item-price-format: "&7Current Price: &6{price}" + item-blocked: "&cBlocked" + item-frozen: "&bFrozen" + no-items: "&cNo items match the current filter." + filters: + all: "All Items" + blocks: "Blocks" + items: "Items" + pagination: + previous: "&aPrevious Page" + next: "&aNext Page" see-all: display-name: "&bSee All Stocks" lore: - - "&7View all available stocks in the market." - - "&eClick to browse everything!" + line1: "&7View all available stocks in the market." + line2: "&eClick to browse everything!" all-stocks: title: "&bAll Stocks" back-display-name: "&cBack to My Stocks" @@ -404,88 +463,37 @@ shop: item-frozen: "&bFrozen" no-items: "&cNo items match the current filter." - shop: - rotations: - daily_specials: - farming_frenzy: - display-name: "&aDaily Special: Farming Frenzy" - lore: "&7Staple crops on sale for islands stocking up." - menu-title: "&aDaily Special: Farming Frenzy" - monster_madness: - display-name: "&cDaily Special: Monster Madness" - lore: "&7Overstocked mob drops priced to move." - menu-title: "&cDaily Special: Monster Madness" - harvest_bundle: - display-name: "&cRotten Flesh Bundle" - note: "&7Fresh from tonight's mob farm cleanup." - seasonal_treats: - display-name: "&cExplosive Care Package" - note: "&7Perfect for crafting rockets or TNT." - premium_pick: - display-name: "&cBlaze Rod Stash" - note: "&7Stockpile rods for brewing stands and fuel." - miner_mania: - display-name: "&bDaily Special: Miner Mania" - lore: "&7Premium ore shipments delivered overnight." - menu-title: "&bDaily Special: Miner Mania" - harvest_bundle: - display-name: "&bBulk Iron Ingot Shipment" - note: "&7Perfect for hoppers, anvils, and tools." - seasonal_treats: - display-name: "&bRefined Gold Ingot Batch" - note: "&7Ideal for beacons, apples, and rails." - premium_pick: - display-name: "&bShimmering Diamond Parcel" - note: "&7Treat yourself or resell at a premium." + rotations: + daily_specials: + farming_frenzy: + display-name: "&aDaily Special: Farming Frenzy" + lore: "&7Staple crops on sale for islands stocking up." + menu-title: "&aDaily Special: Farming Frenzy" + monster_madness: + display-name: "&cDaily Special: Monster Madness" + lore: "&7Overstocked mob drops priced to move." + menu-title: "&cDaily Special: Monster Madness" + harvest_bundle: + display-name: "&cRotten Flesh Bundle" + note: "&7Fresh from tonight's mob farm cleanup." + seasonal_treats: + display-name: "&cExplosive Care Package" + note: "&7Perfect for crafting rockets or TNT." + premium_pick: + display-name: "&cBlaze Rod Stash" + note: "&7Stockpile rods for brewing stands and fuel." + miner_mania: + display-name: "&bDaily Special: Miner Mania" + lore: "&7Premium ore shipments delivered overnight." + menu-title: "&bDaily Special: Miner Mania" + harvest_bundle: + display-name: "&bBulk Iron Ingot Shipment" + note: "&7Perfect for hoppers, anvils, and tools." + seasonal_treats: + display-name: "&bRefined Gold Ingot Batch" + note: "&7Ideal for beacons, apples, and rails." + premium_pick: + display-name: "&bShimmering Diamond Parcel" + note: "&7Treat yourself or resell at a premium." hooks: player-lacking-permission-message: "&cJe hebt geen toestemming om winkelhook-commando's uit te voeren." - # Player shop message keys (Dutch) - no-permission-create: "&cJe hebt geen toestemming om winkels te maken." - sign-requires-chest: "&cWinkelschilden moeten aan een kist bevestigd zijn." - enter-quantity: "&cVoer de hoeveelheid in op de tweede regel." - quantity-prompt: "&cAantal?" - enter-price: "&cVoer de prijs in op de derde regel." - price-prompt: "&cPrijs?" - using-saved-settings: "&aGebruikt je opgeslagen /playershop instellingen." - chest-access-denied: "&cJe kunt de kist van een andere speler niet openen." - break-denied: "&cJe kunt de winkel van iemand anders niet slopen." - shop-removed: "&eWinkel verwijderd." - creation-invalid-configuration: "&cOngeldige winkelconfiguratie." - creation-quantity-positive: "&cHoeveelheid moet groter zijn dan nul." - creation-quantity-min: "&cHoeveelheid moet minimaal &b{min}&c zijn." - creation-quantity-max: "&cHoeveelheid mag niet meer zijn dan &b{max}&c." - creation-price-positive: "&cPrijs moet groter zijn dan nul." - creation-price-min: "&cPrijs moet minimaal &6{min}&c zijn." - creation-price-max: "&cPrijs mag niet meer zijn dan &6{max}&c." - creation-sign-in-use: "&cEr is al een winkel op dit bord." - creation-chest-unresolved: "&cWinkelkisten konden niet worden gevonden." - creation-chest-in-use: "&cEen winkel gebruikt die kist al." - creation-chest-inaccessible: "&cKan geen toegang krijgen tot de kist." - creation-selected-item-missing: "&cDe kist bevat het geselecteerde item uit /playershop niet." - creation-item-missing: "&cPlaats het item dat je wilt verkopen in de kist." - creation-insufficient-stock: "&cDe kist bevat niet genoeg items om de winkel te starten." - creation-success: "&aWinkel succesvol aangemaakt!" - purchase-invalid: "&cOngeldige winkel aankoop poging." - purchase-no-permission: "&cJe hebt geen toestemming om bij winkels te kopen." - purchase-no-economy: "&cDe winkel is momenteel niet beschikbaar omdat er geen economyleverancier is geconfigureerd." - purchase-own-shop: "&cJe kunt niet bij je eigen winkel kopen." - purchase-missing-chest: "&cDe winkelkist ontbreekt. De aanbieding is verwijderd." - purchase-out-of-stock: "&cDeze winkel is momenteel uitverkocht." - purchase-no-space: "&cJe hebt niet genoeg ruimte in je inventaris." - purchase-transaction-failed: "&cTransactie mislukt: {error}" - purchase-owner-notify: "&b{buyer} &aheeft &b{item}&a gekocht voor &6{price}&a." - purchase-buyer-success: "&a{item}&a gekocht van &b{seller}&a voor &6{price}&a." - unknown-seller-name: "de verkoper" - setup-open: "&aConfigureer je spelerswinkel instellingen en bevestig om op te slaan." - setup-item-selected: "&aGeselecteerd &b{item}&a om te verkopen." - setup-item-cleared: "&eGeselecteerd item gewist. De inhoud van de kist bepaalt wat de winkel verkoopt." - setup-select-item: "&eKlik op een item in je inventaris om te kiezen wat je wilt verkopen." - setup-saved: "&aSpelerswinkel instellingen opgeslagen. Plaats een [playershop] bord op een kist om ze te gebruiken." - setup-quantity-chat-prompt: "&eTyp de hoeveelheid om te verkopen in de chat, of typ cancel om te stoppen." - setup-price-chat-prompt: "&eTyp de prijs in de chat, of typ cancel om te stoppen." - setup-chat-cancelled: "&eInvoer geannuleerd. Vorige waarde behouden." - setup-chat-invalid-number: "&cVoer een geldig nummer in." - setup-quantity-updated: "&aHoeveelheid ingesteld op &b{amount}&a." - setup-price-updated: "&aPrijs ingesteld op &6{price}&a." - command-players-only: "&cAlleen spelers kunnen dit commando gebruiken." - command-disabled: "&cSpelerswinkels zijn momenteel uitgeschakeld." diff --git a/src/main/resources/messages/messages_zh.yml b/src/main/resources/messages/messages_zh.yml index c4f148a..fef2dbf 100644 --- a/src/main/resources/messages/messages_zh.yml +++ b/src/main/resources/messages/messages_zh.yml @@ -10,6 +10,9 @@ commands: invalid-amount: "&c数量无效:{amount}" amount-positive: "&c数量必须为正数。" unknown-category: "&c未知的商店分类:{category}" + reload-no-permission: "&c你没有权限重载 EzShops。" + reload-success: "&aEzShops 配置已成功重载。" + reload-failed: "&c重载 EzShops 失败:{error}" sell-hand: players-only: "&c只有玩家可以出售物品。" must-hold-item: "&c你必须拿着一个物品才能使用此指令。" @@ -47,6 +50,16 @@ commands: list-header: "&6价格列表 - 第 {page}/{total} 页" list-entry: "&e{key} &7- 购买: {buy} 出售: {sell}" + stock-admin: + usage: "&e用法:/stockadmin ..." + no-permission: "&c你没有权限使用此命令。" + lack-permission: "&c你缺少权限:{perm}" + set-success: "&a已将 {item} 的价格设置为 {price}" + reset-success: "&a已将 {item} 的价格重置为基础价格" + freeze-success: "&a已由 {by} 在 {when} 冻结 {item}" + unfreeze-success: "&a已解冻 {item}" + reload-success: "&a已从磁盘重新加载冻结状态。" + sign-shop-scan: players-only: "&c只有玩家可以扫描商店告示牌。" no-permission: "&c你没有权限扫描商店告示牌。" @@ -192,47 +205,47 @@ signs: buy-label: "&a购买" sell-label: "&c出售" display: - header: "&2[Shop]" - buy-prefix: "&aBuy &7x" - buy-suffix: " &7for &6{price}" - sell-prefix: "&cSell &7x" - sell-suffix: " &7for &6{price}" + header: "&2[商店]" + buy-prefix: "&a购买 &7x" + buy-suffix: " &7价格 &6{price}" + sell-prefix: "&c出售 &7x" + sell-suffix: " &7价格 &6{price}" item-format: "&b{item}" price-format: "&6{price}" - unavailable-format: "&cUnavailable" + unavailable-format: "&c不可用" player-shops: sign-format: - available-header: "&2[PlayerShop]" - out-of-stock-header: "&c[PlayerShop]" + available-header: "&2[玩家商店]" + out-of-stock-header: "&c[玩家商店]" owner-prefix: "&7" - owner-suffix: "'s" - unknown-owner-name: "Owner" + owner-suffix: "&7的" + unknown-owner-name: "未知店主" item-prefix: "&b" item-middle: "&7x &b" item-suffix: " -" price-prefix: "&6" - price-suffix: " &7for &6{price}" - out-of-stock-line: "&cOut of Stock" + price-suffix: " &7价格 &6{price}" + out-of-stock-line: "&c缺货" messages: menu: - inventory-title: "&2Player Shop Setup" + inventory-title: "&2玩家商店设置" confirm-button: - name: "&aSave Settings" + name: "&a保存设置" lore: - - "&7Apply these values to your next shop." + - "&7将这些值应用到你的下一个商店。" select-item: - name: "&eSelect Item" + name: "&e选择物品" lore: - - "&7Click an item in your inventory to choose it." - - "&7Current: None" - - "&7Click this slot to clear the selection." - item-selected-clear-hint: "&7Click to clear this selection." + - "&7点击背包中的物品来选择它。" + - "&7当前:无" + - "&7点击此槽位以清除选择。" + item-selected-clear-hint: "&7点击清除此选择。" quantity-display: - name: "&bQuantity" + name: "&b数量" value-format: "&ex{amount}" price-display: - name: "&6Price" + name: "&6价格" value-format: "&e{price}" quantity-adjust: minus-one: "&c-1" @@ -246,197 +259,207 @@ player-shops: plus-one: "&a+1" item-description-format: "&b{amount}&7x {item}" unknown-item: - singular: "&bItem" - plural: "&bItems" + singular: "&b物品" + plural: "&b物品" -# English fallback keys added from messages_en.yml to ensure full key coverage -# (keep existing translations above; these are used when a translation is missing) +# ================= 商店界面 ================= +# 分类 / 主菜单 / 股票市场 / 每日特惠 的展示文本。 shop: common: menu: fill-display-name: "&7 " item-display-name: "&f{material}" - buy-line: "&7Buy {amount}: &a{buy_total}" - sell-line: "&7Sell {amount}: &c{sell_total}" - shift-click-line: "&7Shift-click {bulk_amount}: &a{buy_bulk_total} &7/ &c{sell_bulk_total}" - cannot-sell-line: "&7This item cannot be sold." - buy-only-shift-line: "&7Shift-click {bulk_amount}: &a{buy_bulk_total}" + buy-line: "&7购买 {amount} 个:&a{buy_total}" + sell-line: "&7出售 {amount} 个:&c{sell_total}" + shift-click-line: "&7潜行点击 {bulk_amount} 个:&a{buy_bulk_total} &7/ &c{sell_bulk_total}" + cannot-sell-line: "&7该物品无法出售。" + buy-only-shift-line: "&7潜行点击 {bulk_amount} 个:&a{buy_bulk_total}" spawner-display-name: "&f{spawner}" + prices-may-change: "&7价格可能会随时间变化。" categories: building: - name: "&eBuilding Blocks" - icon-display-name: "&eBuilding Blocks" - icon-lore: "&7Blocks for construction projects." + name: "&e建筑方块" + icon-display-name: "&e建筑方块" + icon-lore: "&7用于建筑工程的方块。" menu: - title: "&eBuilding Blocks" + title: "&e建筑方块" farming: - name: "&aFarming Supplies" - icon-display-name: "&aFarming Supplies" - icon-lore: "&7Common crops and farming goods." + name: "&a农业用品" + icon-display-name: "&a农业用品" + icon-lore: "&7常见农作物与农业用品。" menu: - title: "&aFarming Supplies" + title: "&a农业用品" food: - name: "&eFood & Meals" - icon-display-name: "&eFood & Meals" - icon-lore: "&7Everyday meals and snacks." + name: "&e食物与餐点" + icon-display-name: "&e食物与餐点" + icon-lore: "&7日常餐点和零食。" menu: - title: "&eFood & Meals" + title: "&e食物与餐点" + item-note: "&7美味餐点与易腐食品。" daily_specials: - name: "&dDaily Specials" - icon-display-name: "&dDaily Specials" - icon-lore: "&7Hand-picked deals that change throughout the day." + name: "&d每日特惠" + icon-display-name: "&d每日特惠" + icon-lore: "&7全天轮换的精选商品。" menu: - title: "&dDaily Specials" + title: "&d每日特惠" rotation-defaults: - visit-lore: "&7Visit often to catch the featured option." - admin-hint: "&7Admins can swap options manually by editing shop-rotations.yml." - item-note: "&7Limited-time special - grab it while it lasts!" + visit-lore: "&7常来看看,抓住精选特惠。" + admin-hint: "&7管理员可通过编辑 shop-rotations.yml 手动更换选项。" + item-note: "&7限时特惠——机不可失!" decorations: - name: "&dDecorations & Lighting" - icon-display-name: "&dDecorations & Lighting" - icon-lore: "&7Ornamental blocks and lighting." + name: "&d装饰与照明" + icon-display-name: "&d装饰与照明" + icon-lore: "&7装饰性方块和照明。" menu: - title: "&dDecorations & Lighting" + title: "&d装饰与照明" enchantments: - name: "&5Enchantment Books" - icon-display-name: "&5Enchantment Books" - icon-lore: "&7Powerful books for upgrading your gear." + name: "&5附魔书" + icon-display-name: "&5附魔书" + icon-lore: "&7升级装备的强力书籍。" menu: - title: "&5Enchantment Books" - item-display-name: "&d{enchantments} Book" - contains-line: "&7Contains: &b{enchantments}" + title: "&5附魔书" + item-display-name: "&d{enchantments} 附魔书" + contains-line: "&7包含:&b{enchantments}" fishing: - name: "&bFishing Gear" - icon-display-name: "&bFishing Gear" - icon-lore: "&7Fishing essentials and bait." + name: "&b钓鱼装备" + icon-display-name: "&b钓鱼装备" + icon-lore: "&7钓鱼必备品和鱼饵。" menu: - title: "&bFishing Gear" - item-note: "&7Freshly stocked for anglers." + title: "&b钓鱼装备" + item-note: "&7为垂钓者新鲜上架。" mining: - name: "&bMining Resources" - icon-display-name: "&bMining Resources" - icon-lore: "&7Ores, ingots, and stone." + name: "&b采矿资源" + icon-display-name: "&b采矿资源" + icon-lore: "&7矿石、锭和石头。" menu: - title: "&bMining Resources" - item-note: "&7Trusted by miners everywhere." + title: "&b采矿资源" + item-note: "&7备受矿工信赖。" mob_drops: - name: "&cMob Drops & Combat" - icon-display-name: "&cMob Drops & Combat" - icon-lore: "&7Mob drops and combat gear." + name: "&c生物掉落与战斗" + icon-display-name: "&c生物掉落与战斗" + icon-lore: "&7生物掉落物和战斗装备。" menu: - title: "&cMob Drops & Combat" - item-note: "&7Favored by hunters and warriors." + title: "&c生物掉落与战斗" + item-note: "&7深受猎人和战士的青睐。" redstone: - name: "&cRedstone & Utility" - icon-display-name: "&cRedstone & Utility" - icon-lore: "&7Automation components and wiring." + name: "&c红石与机关" + icon-display-name: "&c红石与机关" + icon-lore: "&7自动化组件和线路。" menu: - title: "&cRedstone & Utility" + title: "&c红石与机关" spawners: - name: "&6Mob Spawners" - icon-display-name: "&6Mob Spawners" - icon-lore: "&7Purchase mob spawners to power your island grinders." + name: "&6生物刷怪笼" + icon-display-name: "&6生物刷怪笼" + icon-lore: "&7购买刷怪笼来给你的岛屿刷怪塔供能。" menu: - title: "&6Mob Spawners" - spawns-line: "&7Spawns: &b{spawner_name}" + title: "&6生物刷怪笼" + spawns-line: "&7生成:&b{spawner_name}" valuables: - name: "&bValuables & Rares" - icon-display-name: "&bValuables & Rares" - icon-lore: "&7Rare and valuable items." + name: "&b贵重品与稀有物" + icon-display-name: "&b贵重品与稀有物" + icon-lore: "&7稀有且有价值的物品。" menu: - title: "&bValuables & Rares" - item-note: "&7Guaranteed by the shopkeeper." + title: "&b贵重品与稀有物" + item-note: "&7由店主保证。" + experience-bottle-display-name: "&b经验瓶" wood: - name: "&aWood & Nature" - icon-display-name: "&aWood & Nature" - icon-lore: "&7Raw lumber and forestry goods." + name: "&a木材与自然" + icon-display-name: "&a木材与自然" + icon-lore: "&7原木和林业产品。" menu: - title: "&aWood & Nature" - - common: - prices-may-change: "&7Prices may change over time." + title: "&a木材与自然" menu: main: - title: "&aServer Shop" + title: "&a服务器商店" category: - back-display-name: "&eBack" - back-lore: "&7Return to the main shop menu." + back-display-name: "&e返回" + back-lore: "&7返回商店主菜单。" stock: gui: overview: - title: "&6Stock Market Overview" + title: "&6股市总览" filter: - all: "All Stocks" - category: "By Category" - price: "By Price" + all: "全部股票" + category: "按分类" + price: "按价格" localization: - next-page: "&aNext Page" - prev-page: "&cPrevious Page" - filter-label: "&eFilter: {filter}" - no-stocks: "&cNo tradable stocks found." + next-page: "&a下一页" + prev-page: "&c上一页" + filter-label: "&e筛选:{filter}" + no-stocks: "&c未找到可交易的股票。" item-format: "&e{item} &7- &6{price}" + item-price-format: "&7当前价格:&6{price}" + item-blocked: "&c已封锁" + item-frozen: "&b已冻结" + no-items: "&c没有匹配当前筛选的物品。" + filters: + all: "全部物品" + blocks: "方块" + items: "物品" + pagination: + previous: "&a上一页" + next: "&a下一页" see-all: - display-name: "&bSee All Stocks" + display-name: "&b查看全部股票" lore: - - "&7View all available stocks in the market." - - "&eClick to browse everything!" + line1: "&7查看市场中所有可用的股票。" + line2: "&e点击浏览全部!" all-stocks: - title: "&bAll Stocks" - back-display-name: "&cBack to My Stocks" - back-lore: "&7Return to your stock overview" - filter-button-display: "&aFilter: {filter}" + title: "&b全部股票" + back-display-name: "&c返回我的股票" + back-lore: "&7返回你的股票总览" + filter-button-display: "&a筛选:{filter}" filter-button: lore: - click: "&7Click to cycle filters" - current: "&eCurrent: {filter}" + click: "&7点击切换筛选条件" + current: "&e当前:{filter}" filters: - all: "All Items" - blocks: "Blocks" - items: "Items" + all: "全部物品" + blocks: "方块" + items: "物品" pagination: - previous: "&aPrevious Page" - next: "&aNext Page" + previous: "&a上一页" + next: "&a下一页" localization: - item-price-format: "&7Current Price: &6{price}" - item-blocked: "&cBlocked" - item-frozen: "&bFrozen" - no-items: "&cNo items match the current filter." + item-price-format: "&7当前价格:&6{price}" + item-blocked: "&c已封锁" + item-frozen: "&b已冻结" + no-items: "&c没有匹配当前筛选的物品。" - shop: - rotations: - daily_specials: - farming_frenzy: - display-name: "&aDaily Special: Farming Frenzy" - lore: "&7Staple crops on sale for islands stocking up." - menu-title: "&aDaily Special: Farming Frenzy" - monster_madness: - display-name: "&cDaily Special: Monster Madness" - lore: "&7Overstocked mob drops priced to move." - menu-title: "&cDaily Special: Monster Madness" - harvest_bundle: - display-name: "&cRotten Flesh Bundle" - note: "&7Fresh from tonight's mob farm cleanup." - seasonal_treats: - display-name: "&cExplosive Care Package" - note: "&7Perfect for crafting rockets or TNT." - premium_pick: - display-name: "&cBlaze Rod Stash" - note: "&7Stockpile rods for brewing stands and fuel." - miner_mania: - display-name: "&bDaily Special: Miner Mania" - lore: "&7Premium ore shipments delivered overnight." - menu-title: "&bDaily Special: Miner Mania" - harvest_bundle: - display-name: "&bBulk Iron Ingot Shipment" - note: "&7Perfect for hoppers, anvils, and tools." - seasonal_treats: - display-name: "&bRefined Gold Ingot Batch" - note: "&7Ideal for beacons, apples, and rails." - premium_pick: - display-name: "&bShimmering Diamond Parcel" - note: "&7Treat yourself or resell at a premium." + rotations: + daily_specials: + farming_frenzy: + display-name: "&a每日特惠:丰收狂潮" + lore: "&7为囤货的岛屿准备的常规作物特卖。" + menu-title: "&a每日特惠:丰收狂潮" + monster_madness: + display-name: "&c每日特惠:怪物狂欢" + lore: "&7积压的生物掉落物,降价促销。" + menu-title: "&c每日特惠:怪物狂欢" + harvest_bundle: + display-name: "&c腐肉礼包" + note: "&7今晚刷怪场清理的新鲜产物。" + seasonal_treats: + display-name: "&c爆炸补给包" + note: "&7适合制作烟花或 TNT。" + premium_pick: + display-name: "&c烈焰棒囤货" + note: "&7囤积烈焰棒用于酿造台和燃料。" + miner_mania: + display-name: "&b每日特惠:矿工狂热" + lore: "&7隔夜送达的优质矿石运输。" + menu-title: "&b每日特惠:矿工狂热" + harvest_bundle: + display-name: "&b大捆铁锭装运" + note: "&7非常适合漏斗、铁砧和工具。" + seasonal_treats: + display-name: "&b精炼金锭批次" + note: "&7适合信标、金苹果和铁轨。" + premium_pick: + display-name: "&b闪烁钻石包裹" + note: "&7犒劳自己或高价转售。" hooks: - player-lacking-permission-message: "&cYou do not have permission to run shop hook commands." + player-lacking-permission-message: "&c你没有权限执行商店相关的钩子命令。" diff --git a/src/test/java/com/skyblockexp/ezshops/config/MessageFilesDuplicateKeyTest.java b/src/test/java/com/skyblockexp/ezshops/config/MessageFilesDuplicateKeyTest.java new file mode 100644 index 0000000..16c7a4f --- /dev/null +++ b/src/test/java/com/skyblockexp/ezshops/config/MessageFilesDuplicateKeyTest.java @@ -0,0 +1,46 @@ +package com.skyblockexp.ezshops.config; + +import org.junit.jupiter.api.Test; +import org.yaml.snakeyaml.LoaderOptions; +import org.yaml.snakeyaml.Yaml; + +import java.io.IOException; +import java.io.InputStream; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.fail; + +/** + * Guards the bundled {@code messages/*.yml} files against duplicate YAML keys. + * + *

SnakeYAML (and therefore Bukkit's YamlConfiguration) silently keeps the last + * duplicate mapping key and discards the first, which once silently dropped the + * {@code shop.common} sub-keys in {@code messages_zh.yml} / {@code messages_nl.yml} + * and logged {@code duplicate keys found : common} at startup.

+ * + *

Parsing in strict mode ({@code allowDuplicateKeys = false}) makes any duplicate + * key throw, so a regression re-introduced by an upstream merge fails this test.

+ */ +class MessageFilesDuplicateKeyTest { + + private static final List MESSAGE_FILES = List.of( + "messages_en.yml", "messages_es.yml", "messages_nl.yml", "messages_zh.yml"); + + @Test + void messageFilesContainNoDuplicateKeys() throws IOException { + for (String file : MESSAGE_FILES) { + LoaderOptions options = new LoaderOptions(); + options.setAllowDuplicateKeys(false); + Yaml yaml = new Yaml(options); + + try (InputStream in = getClass().getResourceAsStream("/messages/" + file)) { + if (in == null) { + fail("Missing bundled resource /messages/" + file); + } + assertDoesNotThrow(() -> yaml.load(in), + "Duplicate (or invalid) YAML keys in " + file); + } + } + } +}