From ef2352d38150c99708a9bfe5959612d25d2d5229 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20M=C3=BCller?= Date: Fri, 24 Jul 2026 16:06:20 +0200 Subject: [PATCH] Added localization support with translatable components, centralized translations, and replaced hardcoded strings across commands and messages. --- .../eu/mhsl/minecraft/pixelblocks/Main.java | 2 + .../minecraft/pixelblocks/PixelBlockItem.java | 19 +++++---- .../minecraft/pixelblocks/Translations.java | 39 +++++++++++++++++++ .../commands/CreateSubCommand.java | 4 +- .../commands/DestroyAllSubCommand.java | 4 +- .../pixelblocks/commands/ExitSubCommand.java | 6 +-- .../pixelblocks/commands/GiveSubCommand.java | 8 ++-- .../commands/PixelBlocksCommand.java | 9 +++-- .../pixelblocks/commands/SubCommand.java | 10 ++--- .../listeners/CraftPixelBlockListener.java | 8 +++- .../listeners/PlacePixelBlockListener.java | 4 +- .../pixelblocks/pixelblock/PixelBlock.java | 8 ++-- .../resources/i18n/messages_de.properties | 22 +++++++++++ .../resources/i18n/messages_en.properties | 22 +++++++++++ 14 files changed, 131 insertions(+), 34 deletions(-) create mode 100644 src/main/java/eu/mhsl/minecraft/pixelblocks/Translations.java create mode 100644 src/main/resources/i18n/messages_de.properties create mode 100644 src/main/resources/i18n/messages_en.properties diff --git a/src/main/java/eu/mhsl/minecraft/pixelblocks/Main.java b/src/main/java/eu/mhsl/minecraft/pixelblocks/Main.java index f864ddf..58d4d58 100644 --- a/src/main/java/eu/mhsl/minecraft/pixelblocks/Main.java +++ b/src/main/java/eu/mhsl/minecraft/pixelblocks/Main.java @@ -52,6 +52,7 @@ public final class Main extends JavaPlugin { @Override public void onEnable() { + Translations.register(); Main.taskFactory = BukkitTaskChainFactory.create(this); getLogger().info("Start constructing blocks from Database..."); database.loadPixelBlocks(); @@ -94,6 +95,7 @@ public final class Main extends JavaPlugin { Bukkit.getOnlinePlayers().forEach(QuitWhileInPixelBlockListener::kickPlayerOutOfWorld); taskFactory.shutdown(5, TimeUnit.SECONDS); database.close(); + Translations.unregister(); } public static Main plugin() { diff --git a/src/main/java/eu/mhsl/minecraft/pixelblocks/PixelBlockItem.java b/src/main/java/eu/mhsl/minecraft/pixelblocks/PixelBlockItem.java index 4360cc9..fa5ff65 100644 --- a/src/main/java/eu/mhsl/minecraft/pixelblocks/PixelBlockItem.java +++ b/src/main/java/eu/mhsl/minecraft/pixelblocks/PixelBlockItem.java @@ -17,6 +17,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.List; +import java.util.Locale; import java.util.Objects; import java.util.Optional; import java.util.UUID; @@ -52,7 +53,7 @@ public class PixelBlockItem { return new BlockInfo(blockId, ownerId); } - public static @NotNull ItemStack getBlockAsItem(@NotNull PixelBlock block) { + public static @NotNull ItemStack getBlockAsItem(@NotNull PixelBlock block, @NotNull Locale locale) { String ownerName = Optional.ofNullable(Bukkit.getOfflinePlayer(block.getOwnerUUID()).getName()).orElseGet(() -> block.getOwnerUUID().toString()); ItemStack itemStack = HeadUtil.getCustomTextureHead(itemTexture); @@ -60,10 +61,10 @@ public class PixelBlockItem { meta.setMaxStackSize(1); meta.getPersistentDataContainer().set(idProperty, PersistentDataType.STRING, block.getBlockUUID().toString()); meta.getPersistentDataContainer().set(ownerProperty, PersistentDataType.STRING, block.getOwnerUUID().toString()); - meta.displayName(Component.text("Pixelblock von " + ownerName)); + meta.displayName(Translations.render(Component.translatable("pixelblocks.item.name.owned", Component.text(ownerName)), locale)); meta.lore(List.of( - Component.text(ownerName + " ist der Besitzer dieses Blocks."), - Component.text("Klicke auf den gesetzten Block, um diesen zu bearbeiten!"), + Translations.render(Component.translatable("pixelblocks.item.lore.owner", Component.text(ownerName)), locale), + Translations.render(Component.translatable("pixelblocks.item.lore.edit-hint"), locale), Component.text(block.getBlockUUID().toString()).color(NamedTextColor.DARK_GRAY) )); itemStack.setItemMeta(meta); @@ -72,13 +73,17 @@ public class PixelBlockItem { } public static @NotNull ItemStack getEmptyPixelBlock() { + return getEmptyPixelBlock(Translations.defaultLocale); + } + + public static @NotNull ItemStack getEmptyPixelBlock(@NotNull Locale locale) { ItemStack item = HeadUtil.getCustomTextureHead(itemTexture); ItemMeta meta = item.getItemMeta(); meta.setMaxStackSize(1); - meta.displayName(Component.text("Leerer Pixelblock")); + meta.displayName(Translations.render(Component.translatable("pixelblocks.item.name.empty"), locale)); meta.lore(List.of( - Component.text("Der erste Spieler, der den Block platziert wird zum Besitzer des Blocks."), - Component.text("Klicke auf den gesetzten Block, um diesen zu bearbeiten!") + Translations.render(Component.translatable("pixelblocks.item.lore.first-placer"), locale), + Translations.render(Component.translatable("pixelblocks.item.lore.edit-hint"), locale) )); meta.getPersistentDataContainer().set(idProperty, PersistentDataType.STRING, emptyBlockUUID.toString()); item.setItemMeta(meta); diff --git a/src/main/java/eu/mhsl/minecraft/pixelblocks/Translations.java b/src/main/java/eu/mhsl/minecraft/pixelblocks/Translations.java new file mode 100644 index 0000000..2a55345 --- /dev/null +++ b/src/main/java/eu/mhsl/minecraft/pixelblocks/Translations.java @@ -0,0 +1,39 @@ +package eu.mhsl.minecraft.pixelblocks; + +import net.kyori.adventure.key.Key; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.translation.GlobalTranslator; +import net.kyori.adventure.translation.TranslationStore; +import org.jetbrains.annotations.NotNull; + +import java.text.MessageFormat; +import java.util.List; +import java.util.Locale; +import java.util.ResourceBundle; + +public class Translations { + public static final Locale defaultLocale = Locale.ENGLISH; + private static final List supportedLocales = List.of(Locale.ENGLISH, Locale.GERMAN); + + private static TranslationStore.StringBased store; + + public static void register() { + store = TranslationStore.messageFormat(Key.key("pixelblocks", "translations")); + store.defaultLocale(defaultLocale); + for(Locale locale : supportedLocales) { + ResourceBundle bundle = ResourceBundle.getBundle("i18n.messages", locale, Translations.class.getClassLoader()); + store.registerAll(locale, bundle, true); + } + GlobalTranslator.translator().addSource(store); + } + + public static void unregister() { + if(store != null) GlobalTranslator.translator().removeSource(store); + } + + // Für Texte, die persistiert werden (z. B. Item-Namen) und daher nicht + // automatisch pro Empfänger übersetzt werden können + public static @NotNull Component render(@NotNull Component component, @NotNull Locale locale) { + return GlobalTranslator.render(component, locale); + } +} diff --git a/src/main/java/eu/mhsl/minecraft/pixelblocks/commands/CreateSubCommand.java b/src/main/java/eu/mhsl/minecraft/pixelblocks/commands/CreateSubCommand.java index 2c64427..ec81fe0 100644 --- a/src/main/java/eu/mhsl/minecraft/pixelblocks/commands/CreateSubCommand.java +++ b/src/main/java/eu/mhsl/minecraft/pixelblocks/commands/CreateSubCommand.java @@ -12,13 +12,13 @@ import java.util.UUID; public class CreateSubCommand extends SubCommand { public CreateSubCommand() { - super("create", "pixelblocks.command.create", "Erstellt einen neuen Pixelblock an deiner Position."); + super("create", "pixelblocks.command.create", "pixelblocks.command.create.description"); } @Override public void execute(@NotNull Player player, @NotNull String[] args) { if(PixelBlockWorld.isPixelWorld(player.getWorld())) { - player.sendMessage(Component.text("Pixelblöcke können nicht innerhalb anderer Pixelblöcke erstellt werden.", NamedTextColor.RED)); + player.sendMessage(Component.translatable("pixelblocks.error.create-inside").color(NamedTextColor.RED)); return; } diff --git a/src/main/java/eu/mhsl/minecraft/pixelblocks/commands/DestroyAllSubCommand.java b/src/main/java/eu/mhsl/minecraft/pixelblocks/commands/DestroyAllSubCommand.java index d166c51..f50bea6 100644 --- a/src/main/java/eu/mhsl/minecraft/pixelblocks/commands/DestroyAllSubCommand.java +++ b/src/main/java/eu/mhsl/minecraft/pixelblocks/commands/DestroyAllSubCommand.java @@ -11,13 +11,13 @@ import java.util.List; public class DestroyAllSubCommand extends SubCommand { public DestroyAllSubCommand() { - super("destroyall", "pixelblocks.command.destroyall", "Zerstört alle Pixelblöcke auf dem Server."); + super("destroyall", "pixelblocks.command.destroyall", "pixelblocks.command.destroyall.description"); } @Override public void execute(@NotNull Player player, @NotNull String[] args) { List blocksToDestroy = List.copyOf(Main.pixelBlocks); blocksToDestroy.forEach(pixelBlock -> pixelBlock.destroy(player, true)); - player.sendMessage(Component.text(String.format("%d Pixelblöcke werden zerstört.", blocksToDestroy.size()), NamedTextColor.GREEN)); + player.sendMessage(Component.translatable("pixelblocks.command.destroyall.success", Component.text(blocksToDestroy.size())).color(NamedTextColor.GREEN)); } } diff --git a/src/main/java/eu/mhsl/minecraft/pixelblocks/commands/ExitSubCommand.java b/src/main/java/eu/mhsl/minecraft/pixelblocks/commands/ExitSubCommand.java index 8027d33..71b53b7 100644 --- a/src/main/java/eu/mhsl/minecraft/pixelblocks/commands/ExitSubCommand.java +++ b/src/main/java/eu/mhsl/minecraft/pixelblocks/commands/ExitSubCommand.java @@ -9,19 +9,19 @@ import org.jetbrains.annotations.NotNull; public class ExitSubCommand extends SubCommand { public ExitSubCommand() { - super("exit", "pixelblocks.command.exit", "Verlässt den Pixelblock, in dem du dich befindest."); + super("exit", "pixelblocks.command.exit", "pixelblocks.command.exit.description"); } @Override public void execute(@NotNull Player player, @NotNull String[] args) { if(!PixelBlockWorld.isPixelWorld(player.getWorld())) { - player.sendMessage(Component.text("Du befindest dich nicht in einem Pixelblock.", NamedTextColor.RED)); + player.sendMessage(Component.translatable("pixelblocks.error.not-in-pixelblock").color(NamedTextColor.RED)); return; } PixelBlock pixelBlock = PixelBlock.getPixelBlockFromBlockWorld(player.getWorld()); if(pixelBlock == null) { - player.sendMessage(Component.text("Dieser Pixelblock konnte nicht gefunden werden.", NamedTextColor.RED)); + player.sendMessage(Component.translatable("pixelblocks.error.block-not-found").color(NamedTextColor.RED)); return; } diff --git a/src/main/java/eu/mhsl/minecraft/pixelblocks/commands/GiveSubCommand.java b/src/main/java/eu/mhsl/minecraft/pixelblocks/commands/GiveSubCommand.java index 3fd12b5..83ff3a9 100644 --- a/src/main/java/eu/mhsl/minecraft/pixelblocks/commands/GiveSubCommand.java +++ b/src/main/java/eu/mhsl/minecraft/pixelblocks/commands/GiveSubCommand.java @@ -12,7 +12,7 @@ import java.util.UUID; public class GiveSubCommand extends SubCommand { public GiveSubCommand() { - super("give", "pixelblocks.command.give", "Gibt dir ein Pixelblock-Item, optional mit fester UUID."); + super("give", "pixelblocks.command.give", "pixelblocks.command.give.description"); } @Override @@ -24,16 +24,16 @@ public class GiveSubCommand extends SubCommand { try { blockId = UUID.fromString(args[0]); } catch(IllegalArgumentException e) { - player.sendMessage(Component.text(String.format("'%s' ist keine gültige UUID.", args[0]), NamedTextColor.RED)); + player.sendMessage(Component.translatable("pixelblocks.error.invalid-uuid", Component.text(args[0])).color(NamedTextColor.RED)); return; } } - ItemStack item = PixelBlockItem.getEmptyPixelBlock(); + ItemStack item = PixelBlockItem.getEmptyPixelBlock(player.locale()); PixelBlockItem.setBlockId(item, blockId); player.getInventory().addItem(item); - player.sendMessage(Component.text(String.format("Pixelblock '%s' erhalten.", blockId), NamedTextColor.GREEN)); + player.sendMessage(Component.translatable("pixelblocks.command.give.success", Component.text(blockId.toString())).color(NamedTextColor.GREEN)); } @Override diff --git a/src/main/java/eu/mhsl/minecraft/pixelblocks/commands/PixelBlocksCommand.java b/src/main/java/eu/mhsl/minecraft/pixelblocks/commands/PixelBlocksCommand.java index e1f3d4a..82d7895 100644 --- a/src/main/java/eu/mhsl/minecraft/pixelblocks/commands/PixelBlocksCommand.java +++ b/src/main/java/eu/mhsl/minecraft/pixelblocks/commands/PixelBlocksCommand.java @@ -25,7 +25,7 @@ public class PixelBlocksCommand implements CommandExecutor, TabCompleter { @Override public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { if(!(sender instanceof Player player)) { - sender.sendMessage(Component.text("Dieser Befehl kann nur von Spielern ausgeführt werden.", NamedTextColor.RED)); + sender.sendMessage(Component.translatable("pixelblocks.command.players-only").color(NamedTextColor.RED)); return true; } @@ -39,7 +39,7 @@ public class PixelBlocksCommand implements CommandExecutor, TabCompleter { } if(!player.hasPermission(subCommand.get().permission())) { - player.sendMessage(Component.text("Dazu hast du keine Berechtigung.", NamedTextColor.RED)); + player.sendMessage(Component.translatable("pixelblocks.command.no-permission").color(NamedTextColor.RED)); return true; } @@ -68,12 +68,13 @@ public class PixelBlocksCommand implements CommandExecutor, TabCompleter { } private void sendUsage(@NotNull Player player) { - player.sendMessage(Component.text("PixelBlocks-Befehle:", NamedTextColor.GOLD)); + player.sendMessage(Component.translatable("pixelblocks.command.usage.header").color(NamedTextColor.GOLD)); this.subCommands.stream() .filter(sub -> player.hasPermission(sub.permission())) .forEach(sub -> player.sendMessage(Component.text() .append(Component.text("/pixelblocks " + sub.name(), NamedTextColor.YELLOW)) - .append(Component.text(" - " + sub.description(), NamedTextColor.GRAY)) + .append(Component.text(" - ", NamedTextColor.GRAY)) + .append(Component.translatable(sub.descriptionKey()).color(NamedTextColor.GRAY)) .build())); } } diff --git a/src/main/java/eu/mhsl/minecraft/pixelblocks/commands/SubCommand.java b/src/main/java/eu/mhsl/minecraft/pixelblocks/commands/SubCommand.java index 6d60336..a37608f 100644 --- a/src/main/java/eu/mhsl/minecraft/pixelblocks/commands/SubCommand.java +++ b/src/main/java/eu/mhsl/minecraft/pixelblocks/commands/SubCommand.java @@ -8,12 +8,12 @@ import java.util.List; public abstract class SubCommand { private final String name; private final String permission; - private final String description; + private final String descriptionKey; - protected SubCommand(@NotNull String name, @NotNull String permission, @NotNull String description) { + protected SubCommand(@NotNull String name, @NotNull String permission, @NotNull String descriptionKey) { this.name = name; this.permission = permission; - this.description = description; + this.descriptionKey = descriptionKey; } public final @NotNull String name() { @@ -24,8 +24,8 @@ public abstract class SubCommand { return permission; } - public final @NotNull String description() { - return description; + public final @NotNull String descriptionKey() { + return descriptionKey; } public abstract void execute(@NotNull Player player, @NotNull String[] args); diff --git a/src/main/java/eu/mhsl/minecraft/pixelblocks/listeners/CraftPixelBlockListener.java b/src/main/java/eu/mhsl/minecraft/pixelblocks/listeners/CraftPixelBlockListener.java index 25f6806..be7c07c 100644 --- a/src/main/java/eu/mhsl/minecraft/pixelblocks/listeners/CraftPixelBlockListener.java +++ b/src/main/java/eu/mhsl/minecraft/pixelblocks/listeners/CraftPixelBlockListener.java @@ -1,11 +1,14 @@ package eu.mhsl.minecraft.pixelblocks.listeners; import eu.mhsl.minecraft.pixelblocks.PixelBlockItem; +import eu.mhsl.minecraft.pixelblocks.Translations; +import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.inventory.CraftItemEvent; import org.bukkit.inventory.ItemStack; +import java.util.Locale; import java.util.UUID; public class CraftPixelBlockListener implements Listener { @@ -17,6 +20,9 @@ public class CraftPixelBlockListener implements Listener { PixelBlockItem.BlockInfo info = PixelBlockItem.getBlockInfo(result); if(info == null || !info.id().equals(PixelBlockItem.emptyBlockUUID)) return; - PixelBlockItem.setBlockId(result, UUID.randomUUID()); + Locale locale = event.getWhoClicked() instanceof Player player ? player.locale() : Translations.defaultLocale; + ItemStack localizedResult = PixelBlockItem.getEmptyPixelBlock(locale); + PixelBlockItem.setBlockId(localizedResult, UUID.randomUUID()); + event.getInventory().setResult(localizedResult); } } diff --git a/src/main/java/eu/mhsl/minecraft/pixelblocks/listeners/PlacePixelBlockListener.java b/src/main/java/eu/mhsl/minecraft/pixelblocks/listeners/PlacePixelBlockListener.java index 67e3943..d4a0a21 100644 --- a/src/main/java/eu/mhsl/minecraft/pixelblocks/listeners/PlacePixelBlockListener.java +++ b/src/main/java/eu/mhsl/minecraft/pixelblocks/listeners/PlacePixelBlockListener.java @@ -24,13 +24,13 @@ public class PlacePixelBlockListener implements Listener { World playerWorld = event.getPlayer().getWorld(); if(PixelBlockWorld.isPixelWorld(playerWorld)) { - event.getPlayer().sendMessage(Component.text("In Pixelblöcken kann kein Pixelblock platziert werden.", NamedTextColor.RED)); + event.getPlayer().sendMessage(Component.translatable("pixelblocks.error.place-inside").color(NamedTextColor.RED)); event.setCancelled(true); return; } if(PixelBlock.exists(info.id())) { - event.getPlayer().sendMessage(Component.text("Dieser Pixelblock existiert bereits in der Welt!", NamedTextColor.RED)); + event.getPlayer().sendMessage(Component.translatable("pixelblocks.error.already-exists").color(NamedTextColor.RED)); event.setCancelled(true); return; } diff --git a/src/main/java/eu/mhsl/minecraft/pixelblocks/pixelblock/PixelBlock.java b/src/main/java/eu/mhsl/minecraft/pixelblocks/pixelblock/PixelBlock.java index c77615e..94dd4cf 100644 --- a/src/main/java/eu/mhsl/minecraft/pixelblocks/pixelblock/PixelBlock.java +++ b/src/main/java/eu/mhsl/minecraft/pixelblocks/pixelblock/PixelBlock.java @@ -124,7 +124,7 @@ public class PixelBlock { public void enterBlock(@NotNull Player player) { if(Main.configuration().onlyEditableByOwner() && !player.getUniqueId().equals(ownerUUID)) { - player.sendMessage(Component.text("Dieser Pixelblock gehört nicht dir!", NamedTextColor.RED)); + player.sendMessage(Component.translatable("pixelblocks.error.not-owner").color(NamedTextColor.RED)); return; } @@ -171,13 +171,13 @@ public class PixelBlock { public void destroy(Player destroyedBy, boolean force) { if(!this.isAccessible) return; if(!force && Main.configuration().onlyBreakableByOwner() && !destroyedBy.getUniqueId().equals(ownerUUID)) { - destroyedBy.sendMessage(Component.text("Dieser Pixelblock gehört nicht dir!", NamedTextColor.RED)); + destroyedBy.sendMessage(Component.translatable("pixelblocks.error.not-owner").color(NamedTextColor.RED)); return; } Location returnLocation = this.getReturnLocation(); this.pixelWorld.getPlayersInWorld().forEach(p -> { - p.sendMessage(Component.text("Der Pixelblock wurde von einem anderen Spieler abgebaut!", NamedTextColor.RED)); + p.sendMessage(Component.translatable("pixelblocks.info.destroyed-by-other").color(NamedTextColor.RED)); p.teleport(returnLocation); }); @@ -193,7 +193,7 @@ public class PixelBlock { this.removeEntities(); World world = this.pixelBlockLocation.getWorld(); world.playSound(this.pixelBlockLocation, Sound.BLOCK_COPPER_BULB_BREAK, 1.0F, 2.0F); - world.dropItem(this.getPixelBlockLocation().add(new Vector(0.5, 0.5, 0.5)), PixelBlockItem.getBlockAsItem(this)); + world.dropItem(this.getPixelBlockLocation().add(new Vector(0.5, 0.5, 0.5)), PixelBlockItem.getBlockAsItem(this, destroyedBy.locale())); }) .execute(); diff --git a/src/main/resources/i18n/messages_de.properties b/src/main/resources/i18n/messages_de.properties new file mode 100644 index 0000000..9f06ce4 --- /dev/null +++ b/src/main/resources/i18n/messages_de.properties @@ -0,0 +1,22 @@ +pixelblocks.command.players-only=Dieser Befehl kann nur von Spielern ausgeführt werden. +pixelblocks.command.no-permission=Dazu hast du keine Berechtigung. +pixelblocks.command.usage.header=PixelBlocks-Befehle: +pixelblocks.command.create.description=Erstellt einen neuen Pixelblock an deiner Position. +pixelblocks.command.give.description=Gibt dir ein Pixelblock-Item, optional mit fester UUID. +pixelblocks.command.give.success=Pixelblock '{0}' erhalten. +pixelblocks.command.exit.description=Verlässt den Pixelblock, in dem du dich befindest. +pixelblocks.command.destroyall.description=Zerstört alle Pixelblöcke auf dem Server. +pixelblocks.command.destroyall.success={0} Pixelblöcke werden zerstört. +pixelblocks.error.not-owner=Dieser Pixelblock gehört nicht dir! +pixelblocks.error.create-inside=Pixelblöcke können nicht innerhalb anderer Pixelblöcke erstellt werden. +pixelblocks.error.place-inside=In Pixelblöcken kann kein Pixelblock platziert werden. +pixelblocks.error.already-exists=Dieser Pixelblock existiert bereits in der Welt! +pixelblocks.error.invalid-uuid='{0}' ist keine gültige UUID. +pixelblocks.error.not-in-pixelblock=Du befindest dich nicht in einem Pixelblock. +pixelblocks.error.block-not-found=Dieser Pixelblock konnte nicht gefunden werden. +pixelblocks.info.destroyed-by-other=Der Pixelblock wurde von einem anderen Spieler abgebaut! +pixelblocks.item.name.owned=Pixelblock von {0} +pixelblocks.item.name.empty=Leerer Pixelblock +pixelblocks.item.lore.owner={0} ist der Besitzer dieses Blocks. +pixelblocks.item.lore.edit-hint=Klicke auf den gesetzten Block, um diesen zu bearbeiten! +pixelblocks.item.lore.first-placer=Der erste Spieler, der den Block platziert, wird zum Besitzer des Blocks. diff --git a/src/main/resources/i18n/messages_en.properties b/src/main/resources/i18n/messages_en.properties new file mode 100644 index 0000000..0c53b67 --- /dev/null +++ b/src/main/resources/i18n/messages_en.properties @@ -0,0 +1,22 @@ +pixelblocks.command.players-only=This command can only be used by players. +pixelblocks.command.no-permission=You don't have permission to do that. +pixelblocks.command.usage.header=PixelBlocks commands: +pixelblocks.command.create.description=Creates a new pixel block at your position. +pixelblocks.command.give.description=Gives you a pixel block item, optionally with a fixed UUID. +pixelblocks.command.give.success=Received pixel block '{0}'. +pixelblocks.command.exit.description=Leaves the pixel block you are currently in. +pixelblocks.command.destroyall.description=Destroys all pixel blocks on the server. +pixelblocks.command.destroyall.success={0} pixel blocks are being destroyed. +pixelblocks.error.not-owner=This pixel block does not belong to you! +pixelblocks.error.create-inside=Pixel blocks cannot be created inside other pixel blocks. +pixelblocks.error.place-inside=Pixel blocks cannot be placed inside pixel blocks. +pixelblocks.error.already-exists=This pixel block already exists in the world! +pixelblocks.error.invalid-uuid='{0}' is not a valid UUID. +pixelblocks.error.not-in-pixelblock=You are not inside a pixel block. +pixelblocks.error.block-not-found=This pixel block could not be found. +pixelblocks.info.destroyed-by-other=The pixel block was destroyed by another player! +pixelblocks.item.name.owned=Pixel block of {0} +pixelblocks.item.name.empty=Empty pixel block +pixelblocks.item.lore.owner={0} is the owner of this block. +pixelblocks.item.lore.edit-hint=Click the placed block to edit it! +pixelblocks.item.lore.first-placer=The first player to place this block becomes its owner.