feat(i18n): admin gui

This commit is contained in:
ineanto 2023-09-15 22:15:00 +02:00
parent f436c7db3a
commit 8838961f37
12 changed files with 131 additions and 54 deletions

View file

@ -22,16 +22,17 @@ public class AdminGUI {
final HomeGUI parent = new HomeGUI(player);
final GoBackItem backItem = new GoBackItem(player);
final UnavailableItem unavailableItem = new UnavailableItem(player);
final ManagePlayerItem managePlayerItem = new ManagePlayerItem(i18n, player);
this.gui = Gui.normal()
.setStructure(
"# # # # # # # # #",
"# # # S C U # # #",
"# # # S C X # # #",
"B # # # # # # # #"
)
.addIngredient('S', new ManageCacheItem())
.addIngredient('S', new ManageCacheItem(i18n))
.addIngredient('C', managePlayerItem.get())
.addIngredient('U', unavailableItem.get())
.addIngredient('C', new ManagePlayerItem())
.addIngredient('B', backItem.get(parent.getGUI(), parent.getTitle()))
.build();
this.player = player;

View file

@ -1,24 +1,25 @@
package xyz.atnrch.nicko.gui.items.admin;
import xyz.xenondevs.invui.item.builder.ItemBuilder;
import xyz.xenondevs.invui.item.builder.SkullBuilder;
import xyz.xenondevs.invui.item.impl.AsyncItem;
import xyz.atnrch.nicko.gui.CacheManagementGUI;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.jetbrains.annotations.NotNull;
import xyz.atnrch.nicko.gui.CacheManagementGUI;
import xyz.atnrch.nicko.gui.items.common.LoadingItem;
import xyz.atnrch.nicko.i18n.I18N;
import xyz.atnrch.nicko.i18n.I18NDict;
import xyz.atnrch.nicko.i18n.ItemTranslation;
import xyz.xenondevs.invui.item.builder.SkullBuilder;
import xyz.xenondevs.invui.item.impl.AsyncItem;
public class ManageCacheItem extends AsyncItem {
public ManageCacheItem() {
super(new ItemBuilder(Material.PAINTING)
.setDisplayName("Manage §6skin §fcache...")
.addLoreLines("§7Access the skin cache management panel."),
public ManageCacheItem(I18N i18n) {
super(new LoadingItem(i18n).get(),
() -> {
final SkullBuilder builder = new SkullBuilder("Notch");
builder.setDisplayName("Manage §6skin §fcache...");
builder.addLoreLines("§7Access the skin cache management panel.");
final ItemTranslation translation = i18n.translateItem(I18NDict.GUI.Admin.MANAGE_CACHE);
builder.setDisplayName(translation.getName());
translation.getLore().forEach(builder::addLoreLines);
return builder;
});
}

View file

@ -2,30 +2,32 @@ package xyz.atnrch.nicko.gui.items.admin;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.jetbrains.annotations.NotNull;
import xyz.atnrch.nicko.gui.PlayerCheckGUI;
import xyz.atnrch.nicko.i18n.I18N;
import xyz.atnrch.nicko.i18n.I18NDict;
import xyz.atnrch.nicko.i18n.ItemTranslation;
import xyz.xenondevs.invui.item.builder.ItemBuilder;
import xyz.xenondevs.invui.item.impl.SuppliedItem;
public class ManagePlayerItem extends SuppliedItem {
public ManagePlayerItem() {
super(() -> {
final ItemBuilder builder = new ItemBuilder(Material.WRITABLE_BOOK);
builder.setDisplayName("Check a player...");
builder.addLoreLines("§7See players' disguise information.");
return builder;
},
click -> true);
public class ManagePlayerItem {
private final Player player;
private final I18N i18n;
public ManagePlayerItem(I18N i18n, Player player) {
this.i18n = i18n;
this.player = player;
}
@Override
public void handleClick(@NotNull ClickType clickType, @NotNull Player player, @NotNull InventoryClickEvent
event) {
if (clickType.isLeftClick() || clickType.isRightClick()) {
event.getView().close();
public SuppliedItem get() {
return new SuppliedItem(() -> {
final ItemBuilder builder = new ItemBuilder(Material.WRITABLE_BOOK);
final ItemTranslation translation = i18n.translateItem(I18NDict.GUI.Admin.MANAGE_PLAYER);
builder.setDisplayName(translation.getName());
translation.getLore().forEach(builder::addLoreLines);
return builder;
}, click -> {
new PlayerCheckGUI(player).open();
}
return true;
});
}
}

View file

@ -31,7 +31,6 @@ public class CacheStatisticsItem {
stats.requestCount(),
Math.round(cache.size())
);
translation.getLore().forEach(System.out::println);
// TODO (Ineanto, 9/11/23): This doesn't work.
builder.setDisplayName(translation.getName());
translation.getLore().forEach(builder::addLoreLines);

View file

@ -0,0 +1,27 @@
package xyz.atnrch.nicko.gui.items.common;
import org.bukkit.Material;
import xyz.atnrch.nicko.i18n.I18N;
import xyz.atnrch.nicko.i18n.I18NDict;
import xyz.atnrch.nicko.i18n.ItemTranslation;
import xyz.xenondevs.invui.item.ItemProvider;
import xyz.xenondevs.invui.item.builder.ItemBuilder;
import xyz.xenondevs.invui.item.impl.SuppliedItem;
public class LoadingItem {
private final I18N i18n;
public LoadingItem(I18N i18n) {
this.i18n = i18n;
}
public ItemProvider get() {
return new SuppliedItem(() -> {
final ItemBuilder builder = new ItemBuilder(Material.PAINTING);
final ItemTranslation translation = i18n.translateItem(I18NDict.GUI.LOADING);
builder.setDisplayName(translation.getName());
translation.getLore().forEach(builder::addLoreLines);
return builder;
}, (click -> true)).getItemProvider();
}
}

View file

@ -12,7 +12,6 @@ import xyz.xenondevs.invui.item.builder.ItemBuilder;
import xyz.xenondevs.invui.item.impl.SuppliedItem;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicBoolean;
public class ResetItem {
private final I18N i18n;
@ -33,25 +32,23 @@ public class ResetItem {
final ClickType clickType = event.getClickType();
if (clickType.isLeftClick() || clickType.isRightClick()) {
final Optional<NickoProfile> optionalProfile = NickoProfile.get(player);
final AtomicBoolean result = new AtomicBoolean(false);
optionalProfile.ifPresent(profile -> {
if (!profile.hasData()) {
player.sendMessage(i18n.translate(I18NDict.Event.Appearance.Remove.MISSING));
event.getEvent().getView().close();
result.set(true);
return;
}
final AppearanceManager appearanceManager = new AppearanceManager(player);
if (!appearanceManager.reset().isError()) {
player.sendMessage(i18n.translate(I18NDict.Event.Appearance.Remove.OK));
result.set(false);
} else {
player.sendMessage(i18n.translate(I18NDict.Event.Appearance.Remove.ERROR));
result.set(true);
profile.setSkin(null);
profile.setName(null);
}
});
return result.get();
return true;
}
return false;
});

View file

@ -18,7 +18,7 @@ public class I18N {
private final MessageFormat formatter = new MessageFormat("");
private final Logger logger = Logger.getLogger("I18N");
private final NickoBukkit instance = NickoBukkit.getInstance();
private final Pattern replacementPattern = Pattern.compile("\\{\\d+}");
private final Pattern replacementPattern = Pattern.compile("\\{\\d+}$", Pattern.DOTALL);
private final YamlConfig yamlConfig;
private final Player player;
private final Locale playerLocale;
@ -67,14 +67,13 @@ public class I18N {
// If the line doesn't contain {i}, skip it
final Matcher matcher = replacementPattern.matcher(currentLine);
if (!matcher.matches()) {
if (!matcher.find()) {
lineIndex++;
continue;
}
// If it does, replace the content with the args at position replacementIndex
if (replacementIndex < args.length && args[replacementIndex] != null) {
System.out.println("replacing...");
// Replace with the corresponding varargs index
toTranslate.set(lineIndex, currentLine.replace("{" + replacementIndex + "}", args[replacementIndex].toString()));
replacementIndex++;

View file

@ -67,8 +67,9 @@ public class I18NDict {
private static final String GUI_KEY = "gui.";
public static final String EXIT = GUI_KEY + "exit";
public static final String UNAVAILABLE = GUI_KEY + "unavailable";
public static final String GO_BACK = GUI_KEY + "go_back";
public static final String UNAVAILABLE = GUI_KEY + "unavailable";
public static final String LOADING = GUI_KEY + "loading";
public static class Choice {
private static final String CHOICE_KEY = GUI_KEY + "choice.";

View file

@ -36,6 +36,8 @@ gui:
name: "Unavailable"
lore:
- "§7§oThis button is disabled."
loading:
name: "§7§oLoading..."
choice:
confirm:
name: "§aConfirm"
@ -68,7 +70,7 @@ gui:
manage_cache:
name: "Manage §6skin §fcache..."
lore:
- "§7Access the skin cache management panel."
- "§7View and manage the skin cache."
manage_player:
name: "Check a player..."
lore:

View file

@ -13,14 +13,14 @@ event:
error: "§cImpossible de mettre à jour vos paramètres. §7§o({0})"
appearance:
set:
error: "§cImpossible d'appliquer votre déguisement. §7§o({0})"
error: "§cImpossible d''appliquer votre déguisement. §7§o({0})"
ok: "§fDéguisement appliqué."
restore:
error: "§cImpossible d'appliquer votre précédent déguisement. §7§o({0})"
error: "§cImpossible d''appliquer votre précédent déguisement. §7§o({0})"
ok: "§aVotre précédent déguisement a été appliqué."
remove:
error: "§cImpossible de retirer votre déguisement. Il sera réinitialisé à votre prochaine reconnexion."
missing: "§cVous n'avez pas de déguisement."
missing: "§cVous n''avez pas de déguisement."
ok: "§fDéguisement retiré."
admin:
cache:
@ -36,6 +36,8 @@ gui:
name: "Indisponible"
lore:
- "§7§oCe boutton est désactivé."
loading:
name: "§7§oChargement..."
choice:
confirm:
name: "§aConfirmer"
@ -66,9 +68,9 @@ gui:
admin:
title: "Nicko > Administration"
manage_cache:
name: "Gérer le cache d'§6skin..."
name: "Gérer le cache de §6skin..."
lore:
- "§7Accédez à la gestion du cache de skin."
- "§7Consultez et gérez le cache de skin."
manage_player:
name: "Vérifier un joueur..."
lore:

View file

@ -14,10 +14,9 @@ import xyz.atnrch.nicko.i18n.I18NDict;
import xyz.atnrch.nicko.i18n.ItemTranslation;
import xyz.atnrch.nicko.i18n.Locale;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.*;
public class I18NItemTranslationTest {
public class ItemTranslationTest {
private static PlayerMock player;
@BeforeAll
@ -44,8 +43,11 @@ public class I18NItemTranslationTest {
@DisplayName("Translate Item")
public void translateItemLore() {
final I18N i18n = new I18N(Locale.FRENCH);
final String translation = i18n.translatePrefixless(I18NDict.Event.Settings.ERROR, "Test!");
assertEquals("§cImpossible de mettre à jour vos paramètres. §7§o(Test!)", translation);
final ItemTranslation translation = i18n.translateItem(I18NDict.GUI.Admin.Cache.STATISTICS, "1", "1");
assertFalse(translation.getLore().isEmpty());
assertEquals("§fNombre de requêtes: §b1", translation.getLore().get(0));
assertEquals("§fNb. de skin dans le cache: §b1", translation.getLore().get(1));
assertEquals("§8§oLe cache est vidé toutes les 24 heures.", translation.getLore().get(2));
}
@AfterAll

View file

@ -0,0 +1,44 @@
package xyz.atnrch.nicko.test.i18n;
import be.seeseemelk.mockbukkit.MockBukkit;
import be.seeseemelk.mockbukkit.entity.PlayerMock;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import xyz.atnrch.nicko.NickoBukkit;
import xyz.atnrch.nicko.config.Configuration;
import xyz.atnrch.nicko.config.DataSourceConfiguration;
import xyz.atnrch.nicko.i18n.I18N;
import xyz.atnrch.nicko.i18n.I18NDict;
import xyz.atnrch.nicko.i18n.Locale;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class TranslationTest {
private static PlayerMock player;
@BeforeAll
public static void setup() {
final Configuration config = new Configuration(
DataSourceConfiguration.SQL_EMPTY,
DataSourceConfiguration.REDIS_EMPTY,
"",
false);
MockBukkit.mock();
MockBukkit.load(NickoBukkit.class, config);
}
@Test
@DisplayName("Translate Line With Replacement")
public void translateItemTranslationWithoutLore() {
final I18N i18n = new I18N(Locale.FRENCH);
final String translation = i18n.translatePrefixless(I18NDict.Event.Settings.ERROR, "Test");
assertEquals("§cImpossible de mettre à jour vos paramètres. §7§o(Test)", translation);
}
@AfterAll
public static void shutdown() {
MockBukkit.unmock();
}
}