feat: translate random skin setting

This commit is contained in:
ineanto 2023-12-22 01:56:38 +01:00
parent fdada8f44f
commit 83bc00aebe
26 changed files with 99 additions and 75 deletions

View file

@ -115,9 +115,9 @@ public class AnvilManager {
final I18N i18n = new I18N(player);
final ActionResult actionResult = appearanceManager.updatePlayer(skinChange, false);
if (!actionResult.isError()) {
player.sendMessage(i18n.translate(I18NDict.Event.Appearance.Set.OK));
player.sendMessage(i18n.translateString(I18NDict.Event.Appearance.Set.OK));
} else {
player.sendMessage(i18n.translate(I18NDict.Event.Appearance.Set.ERROR, i18n.translatePrefixless(actionResult.getErrorKey())));
player.sendMessage(i18n.translateString(I18NDict.Event.Appearance.Set.ERROR, i18n.translateStringWithoutPrefix(actionResult.getErrorKey())));
}
return Collections.singletonList(AnvilGUI.ResponseAction.close());
}

View file

@ -17,7 +17,7 @@ public class NickoCommand implements CommandExecutor {
new HomeGUI(player).open();
} else {
final I18N i18N = new I18N(player);
player.sendMessage(i18N.translate(I18NDict.Error.PERMISSION));
player.sendMessage(i18N.translateString(I18NDict.Error.PERMISSION));
}
return false;
}

View file

@ -45,9 +45,9 @@ public class PlayerJoinListener implements Listener {
final boolean needsASkinChange = profile.getSkin() != null && !profile.getSkin().equals(player.getName());
final ActionResult actionResult = appearanceManager.updatePlayer(needsASkinChange, false);
if (!actionResult.isError()) {
player.sendMessage(i18n.translate(I18NDict.Event.Appearance.Restore.OK));
player.sendMessage(i18n.translateString(I18NDict.Event.Appearance.Restore.OK));
} else {
player.sendMessage(i18n.translate(I18NDict.Event.Appearance.Restore.ERROR, i18n.translatePrefixless(actionResult.getErrorKey())));
player.sendMessage(i18n.translateString(I18NDict.Event.Appearance.Restore.ERROR, i18n.translateStringWithoutPrefix(actionResult.getErrorKey())));
}
}
});

View file

@ -18,7 +18,7 @@ public class AdminGUI {
public AdminGUI(Player player) {
final I18N i18n = new I18N(player);
this.title = i18n.translatePrefixless(I18NDict.GUI.Titles.ADMIN);
this.title = i18n.translateStringWithoutPrefix(I18NDict.GUI.Titles.ADMIN);
final HomeGUI parent = new HomeGUI(player);
final GoBackItem backItem = new GoBackItem(player);

View file

@ -17,7 +17,7 @@ public class CacheManagementGUI {
public CacheManagementGUI(Player player) {
final I18N i18n = new I18N(player);
this.title = i18n.translatePrefixless(I18NDict.GUI.Titles.CACHE);
this.title = i18n.translateStringWithoutPrefix(I18NDict.GUI.Titles.CACHE);
final AdminGUI parent = new AdminGUI(player);
final GoBackItem backItem = new GoBackItem(player);

View file

@ -22,7 +22,7 @@ public class ChoiceGUI {
final ConfirmItem confirmItem = new ConfirmItem(player, callback);
final CancelItem cancelItem = new CancelItem(player, callback);
this.title = i18n.translatePrefixless(I18NDict.GUI.Titles.CONFIRM);
this.title = i18n.translateStringWithoutPrefix(I18NDict.GUI.Titles.CONFIRM);
this.gui = Gui.normal()
.setStructure(
"@ @ @ @ % & & & &",

View file

@ -29,7 +29,7 @@ public class HomeGUI {
}
final I18N i18n = new I18N(player);
this.title = i18n.translatePrefixless(I18NDict.GUI.Titles.HOME);
this.title = i18n.translateStringWithoutPrefix(I18NDict.GUI.Titles.HOME);
final ExitItem exitItem = new ExitItem(player);
final ResetItem resetItem = new ResetItem(player);

View file

@ -28,7 +28,7 @@ public class InvalidateSkinGUI {
public InvalidateSkinGUI(Player player) {
final I18N i18n = new I18N(player);
this.title = i18n.translatePrefixless(I18NDict.GUI.Titles.INVALIDATE_SKIN);
this.title = i18n.translateStringWithoutPrefix(I18NDict.GUI.Titles.INVALIDATE_SKIN);
final ConcurrentMap<String, Optional<MojangSkin>> skins = NickoBukkit.getInstance().getMojangAPI().getSkinCache().asMap();
final List<String> loadedSkins = skins.entrySet().stream()

View file

@ -27,7 +27,7 @@ public class PlayerCheckGUI {
public PlayerCheckGUI(Player player, Collection<? extends Player> players) {
final I18N i18n = new I18N(player);
this.title = i18n.translatePrefixless(I18NDict.GUI.Titles.CHECK);
this.title = i18n.translateStringWithoutPrefix(I18NDict.GUI.Titles.CHECK);
final List<Item> items = players.stream()
.map(Entity::getUniqueId)

View file

@ -22,7 +22,7 @@ public class SettingsGUI {
};
final I18N i18n = new I18N(player);
this.title = i18n.translatePrefixless(I18NDict.GUI.Titles.SETTINGS);
this.title = i18n.translateStringWithoutPrefix(I18NDict.GUI.Titles.SETTINGS);
final HomeGUI parent = new HomeGUI(player);
final LanguageCyclingItem languageItem = new LanguageCyclingItem(player);

View file

@ -50,7 +50,7 @@ public class CacheEntryItem extends AsyncItem {
@Override
public void onConfirm() {
final I18N i18n = new I18N(player);
player.sendMessage(i18n.translate(I18NDict.Event.Admin.Cache.INVALIDATE_ENTRY, name));
player.sendMessage(i18n.translateString(I18NDict.Event.Admin.Cache.INVALIDATE_ENTRY, name));
mojangAPI.eraseFromCache(uuid);
}

View file

@ -27,7 +27,7 @@ public class InvalidateCacheItem {
final Player player = click.getPlayer();
final I18N i18n = new I18N(player);
player.sendMessage(i18n.translate(I18NDict.Event.Admin.Cache.INVALIDATE_CACHE));
player.sendMessage(i18n.translateString(I18NDict.Event.Admin.Cache.INVALIDATE_CACHE));
NickoBukkit.getInstance().getMojangAPI().getSkinCache().invalidateAll();
return true;
}

View file

@ -78,7 +78,7 @@ public class PlayerInformationItem extends AsyncItem {
public void onConfirm() {
final AppearanceManager appearanceManager = new AppearanceManager(target);
appearanceManager.reset();
player.sendMessage(i18n.translate(I18NDict.Event.Admin.Check.REMOVE_SKIN, target.getName()));
player.sendMessage(i18n.translateString(I18NDict.Event.Admin.Check.REMOVE_SKIN, target.getName()));
}
@Override

View file

@ -3,7 +3,7 @@ package xyz.ineanto.nicko.gui.items.common;
import org.bukkit.Material;
import xyz.ineanto.nicko.i18n.I18N;
import xyz.ineanto.nicko.i18n.I18NDict;
import xyz.ineanto.nicko.i18n.ItemTranslation;
import xyz.ineanto.nicko.i18n.Translation;
import xyz.xenondevs.invui.gui.ScrollGui;
import xyz.xenondevs.invui.item.ItemProvider;
import xyz.xenondevs.invui.item.builder.ItemBuilder;
@ -20,7 +20,7 @@ public class ScrollDownItem extends ScrollItem {
@Override
public ItemProvider getItemProvider(ScrollGui gui) {
final ItemBuilder builder = new ItemBuilder(Material.GREEN_STAINED_GLASS_PANE);
final ItemTranslation translation = i18n.fetchTranslation(I18NDict.GUI.SCROLL_DOWN);
final Translation translation = i18n.translate(I18NDict.GUI.SCROLL_DOWN);
builder.setDisplayName(translation.name());
if (!gui.canScroll(1)) translation.lore().forEach(builder::addLoreLines);
return builder;

View file

@ -3,7 +3,7 @@ package xyz.ineanto.nicko.gui.items.common;
import org.bukkit.Material;
import xyz.ineanto.nicko.i18n.I18N;
import xyz.ineanto.nicko.i18n.I18NDict;
import xyz.ineanto.nicko.i18n.ItemTranslation;
import xyz.ineanto.nicko.i18n.Translation;
import xyz.xenondevs.invui.gui.ScrollGui;
import xyz.xenondevs.invui.item.ItemProvider;
import xyz.xenondevs.invui.item.builder.ItemBuilder;
@ -20,7 +20,7 @@ public class ScrollUpItem extends ScrollItem {
@Override
public ItemProvider getItemProvider(ScrollGui gui) {
final ItemBuilder builder = new ItemBuilder(Material.RED_STAINED_GLASS_PANE);
final ItemTranslation translation = i18n.fetchTranslation(I18NDict.GUI.SCROLL_UP);
final Translation translation = i18n.translate(I18NDict.GUI.SCROLL_UP);
builder.setDisplayName(translation.name());
if (!gui.canScroll(-1)) translation.lore().forEach(builder::addLoreLines);
return builder;

View file

@ -30,16 +30,16 @@ public class ResetItem {
final Optional<NickoProfile> optionalProfile = NickoProfile.get(player);
optionalProfile.ifPresent(profile -> {
if (!profile.hasData()) {
player.sendMessage(i18n.translate(I18NDict.Event.Appearance.Remove.MISSING));
player.sendMessage(i18n.translateString(I18NDict.Event.Appearance.Remove.MISSING));
event.getEvent().getView().close();
return;
}
final AppearanceManager appearanceManager = new AppearanceManager(player);
if (!appearanceManager.reset().isError()) {
player.sendMessage(i18n.translate(I18NDict.Event.Appearance.Remove.OK));
player.sendMessage(i18n.translateString(I18NDict.Event.Appearance.Remove.OK));
} else {
player.sendMessage(i18n.translate(I18NDict.Event.Appearance.Remove.ERROR));
player.sendMessage(i18n.translateString(I18NDict.Event.Appearance.Remove.ERROR));
profile.setSkin(null);
profile.setName(null);
}

View file

@ -7,7 +7,7 @@ import xyz.ineanto.nicko.NickoBukkit;
import xyz.ineanto.nicko.gui.SettingsGUI;
import xyz.ineanto.nicko.i18n.I18N;
import xyz.ineanto.nicko.i18n.I18NDict;
import xyz.ineanto.nicko.i18n.ItemTranslation;
import xyz.ineanto.nicko.i18n.Translation;
import xyz.ineanto.nicko.i18n.Locale;
import xyz.ineanto.nicko.profile.NickoProfile;
import xyz.ineanto.nicko.storage.PlayerDataStore;
@ -44,7 +44,7 @@ public class LanguageCyclingItem {
nickoProfile.setLocale(Locale.values()[integer]);
player.getOpenInventory().close();
if (dataStore.updateCache(player.getUniqueId(), nickoProfile).isError()) {
player.sendMessage(i18n.translate(I18NDict.Event.Settings.ERROR));
player.sendMessage(i18n.translateString(I18NDict.Event.Settings.ERROR));
} else {
new SettingsGUI(player).open();
}
@ -56,7 +56,8 @@ public class LanguageCyclingItem {
private ItemProvider generateItem(Locale locale, List<Locale> locales) {
final ItemBuilder builder = new ItemBuilder(Material.OAK_SIGN);
final ItemTranslation translation = i18n.fetchTranslation(I18NDict.GUI.Settings.LANGUAGE);
final Translation translation = i18n.translate(I18NDict.GUI.Settings.LANGUAGE);
final Translation cyclingChoicesTranslation = i18n.translate(I18NDict.GUI.Settings.CYCLING_CHOICES);
builder.setDisplayName(translation.name());
for (Locale value : locales) {
@ -66,7 +67,7 @@ public class LanguageCyclingItem {
builder.addLoreLines("§6§l> §f" + value.getName());
}
}
translation.lore().forEach(builder::addLoreLines);
cyclingChoicesTranslation.lore().forEach(builder::addLoreLines);
return builder;
}

View file

@ -5,7 +5,7 @@ import org.bukkit.entity.Player;
import xyz.ineanto.nicko.NickoBukkit;
import xyz.ineanto.nicko.i18n.I18N;
import xyz.ineanto.nicko.i18n.I18NDict;
import xyz.ineanto.nicko.i18n.ItemTranslation;
import xyz.ineanto.nicko.i18n.Translation;
import xyz.ineanto.nicko.profile.NickoProfile;
import xyz.ineanto.nicko.storage.PlayerDataStore;
import xyz.xenondevs.invui.item.ItemProvider;
@ -40,7 +40,7 @@ public class RandomSkinCyclingItem {
observer.playSound(player, Sound.UI_BUTTON_CLICK, 1f, 0.707107f); // 0.707107 ~= C
nickoProfile.setRandomSkin(integer != 1);
if (dataStore.updateCache(player.getUniqueId(), nickoProfile).isError()) {
player.sendMessage(i18n.translate(I18NDict.Event.Settings.ERROR));
player.sendMessage(i18n.translateString(I18NDict.Event.Settings.ERROR));
player.getOpenInventory().close();
}
}, localeOrdinal, providers);
@ -52,13 +52,16 @@ public class RandomSkinCyclingItem {
private ItemProvider getItemProviderForValue(boolean enabled) {
final SkullBuilder.HeadTexture texture = new SkullBuilder.HeadTexture("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzgzMTEzOGMyMDYxMWQzMDJjNDIzZmEzMjM3MWE3NDNkMTc0MzdhMTg5NzNjMzUxOTczNDQ3MGE3YWJiNCJ9fX0=");
final SkullBuilder builder = new SkullBuilder(texture);
final ItemTranslation translation = i18n.fetchTranslation(I18NDict.GUI.Settings.RANDOM_SKIN,
(enabled ? "§7> §cDisabled" : "§6§l> §c§lDisabled"),
(enabled ? "§6§l> §a§lEnabled" : "§7> §aEnabled")
final Translation randomSkinTranslation = i18n.translate(I18NDict.GUI.Settings.RANDOM_SKIN);
final Translation toggleableTranslation = i18n.translate(I18NDict.GUI.Settings.TOGGLEABLE_BUTTON,
(enabled ? "§7>§c" : "§6§l>§c§l"),
(enabled ? "§6§l>§a§l" : "§7>§a")
);
final Translation cyclingChoicesTranslation = i18n.translate(I18NDict.GUI.Settings.CYCLING_CHOICES);
builder.setDisplayName(translation.name());
translation.lore().forEach(builder::addLoreLines);
builder.setDisplayName(randomSkinTranslation.name());
toggleableTranslation.lore().forEach(builder::addLoreLines);
cyclingChoicesTranslation.lore().forEach(builder::addLoreLines);
return builder;
}
}

View file

@ -8,9 +8,7 @@ import xyz.xenondevs.invui.item.builder.AbstractItemBuilder;
import java.io.InputStream;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Optional;
import java.util.*;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -19,7 +17,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+}$", Pattern.DOTALL);
private final Pattern replacementPattern = Pattern.compile("(?ms)\\{\\d+}");
private final YamlConfig yamlConfig;
private final Player player;
private final Locale playerLocale;
@ -37,28 +35,28 @@ public class I18N {
}
public AbstractItemBuilder<?> translateItem(AbstractItemBuilder<?> item, String key, Object... args) {
final ItemTranslation translation = fetchTranslation(key, args);
final Translation translation = translate(key, args);
item.setDisplayName(translation.name());
translation.lore().forEach(item::addLoreLines);
return item;
}
public ItemTranslation fetchTranslation(String key, Object... args) {
public Translation translate(String key, Object... args) {
final String nameKey = key + ".name";
final String loreKey = key + ".lore";
final String name = readString(nameKey);
final ArrayList<String> lore = readList(loreKey);
if (name == null) {
if (name == null && lore == null) {
logger.warning(nameKey + " doesn't exists! Is your language file outdated?");
return new ItemTranslation(nameKey, new ArrayList<>() {{
add(loreKey);
}});
return new Translation(nameKey, new ArrayList<>(List.of(loreKey)));
}
// Add all elements to a list
final ArrayList<String> toTranslate = new ArrayList<>();
toTranslate.add(name);
if (name != null) {
toTranslate.add(name);
}
if (lore != null && !lore.isEmpty()) {
toTranslate.addAll(lore);
}
@ -91,13 +89,19 @@ public class I18N {
lineIndex++;
}
if (lore == null || lore.isEmpty()) {
return new ItemTranslation(toTranslate.get(0), new ArrayList<>());
if (name == null && !lore.isEmpty()) {
// Empty name, valid lore
return new Translation(null, toTranslate);
} else if (name != null && (lore == null || lore.isEmpty())) {
// Valid name, empty lore
return new Translation(toTranslate.get(0), new ArrayList<>(Collections.emptyList()));
} else {
// Valid name, valid lore
return new Translation(toTranslate.get(0), new ArrayList<>(toTranslate.subList(1, toTranslate.size())));
}
return new ItemTranslation(toTranslate.get(0), new ArrayList<>(toTranslate.subList(1, toTranslate.size())));
}
public String translate(String key, Object... arguments) {
public String translateString(String key, Object... arguments) {
final String translation = readString(key);
try {
formatter.applyPattern(translation);
@ -107,7 +111,7 @@ public class I18N {
}
}
public String translatePrefixless(String key, Object... arguments) {
public String translateStringWithoutPrefix(String key, Object... arguments) {
final String translation = readString(key);
try {
formatter.applyPattern(translation);

View file

@ -111,6 +111,9 @@ public class I18NDict {
public static class Settings {
private static final String SETTINGS_KEY = GUI_KEY + "settings.";
public static final String CYCLING_CHOICES = SETTINGS_KEY + "cycling_choices";
public static final String TOGGLEABLE_BUTTON = SETTINGS_KEY + "toggleable_button";
public static final String LANGUAGE = SETTINGS_KEY + "language";
public static final String RANDOM_SKIN = SETTINGS_KEY + "random_skin";
}

View file

@ -1,5 +0,0 @@
package xyz.ineanto.nicko.i18n;
import java.util.ArrayList;
public record ItemTranslation(String name, ArrayList<String> lore) {}

View file

@ -0,0 +1,5 @@
package xyz.ineanto.nicko.i18n;
import java.util.ArrayList;
public record Translation(String name, ArrayList<String> lore) {}

View file

@ -39,6 +39,11 @@ gui:
cache: "Nicko > Admin... > Cache"
invalidate_skin: "... > Cache > Invalidate"
cycling_choices:
name: "IGNOREME"
lore:
- "§7§oGet through the values"
- "§7§oby left or right clicking."
exit:
name: "Exit"
go_back:
@ -128,15 +133,18 @@ gui:
lore:
- "§7Click to invalidate..."
settings:
toggleable_button:
name: "IGNORE_ME"
lore:
# {0}/{1} represents the carets that shows the current selected option.
- "§b{0} Disabled"
- "§b{1} Enabled"
cycling_choices:
name: "IGNORE_ME"
lore:
- "§7§oCycle through the values"
- "§7§oby left or right clicking."
language:
name: "Language"
lore:
- "§7§oGet through the values"
- "§7§oby left or right clicking."
random_skin:
name: "Random skin on join"
lore:
- "{0}"
- "{1}"
- "§7§oGet through the values"
- "§7§oby left or right clicking."
name: "Random skin on login"

View file

@ -125,15 +125,15 @@ gui:
lore:
- "§7Cliquez pour invalider..."
settings:
language:
name: "Langage"
toggleable_button:
lore:
- "{0} Désactivé"
- "{1} Activé"
cycling_choices:
lore:
- "§7§oParcourez les valeurs"
- "§7§oavec un clique gauche/droit."
language:
name: "Langage"
random_skin:
name: "Apparence aléatoire à la connexion"
lore:
- "{0}"
- "{1}"
- "§7§oParcourez les valeurs"
- "§7§oavec un clique gauche/droit."
name: "Apparence aléatoire à la connexion"

View file

@ -10,7 +10,7 @@ import xyz.ineanto.nicko.NickoBukkit;
import xyz.ineanto.nicko.config.Configuration;
import xyz.ineanto.nicko.i18n.I18N;
import xyz.ineanto.nicko.i18n.I18NDict;
import xyz.ineanto.nicko.i18n.ItemTranslation;
import xyz.ineanto.nicko.i18n.Translation;
import xyz.ineanto.nicko.i18n.Locale;
import static org.junit.jupiter.api.Assertions.*;
@ -29,7 +29,7 @@ public class ItemTranslationTest {
@DisplayName("Translate Item Without Lore")
public void translateItemTranslationWithoutLore() {
final I18N i18n = new I18N(Locale.FRENCH);
final ItemTranslation translation = i18n.fetchTranslation(I18NDict.GUI.GO_BACK);
final Translation translation = i18n.translate(I18NDict.GUI.GO_BACK);
assertTrue(translation.lore().isEmpty());
assertEquals(translation.name(), "Retour");
}
@ -38,7 +38,12 @@ public class ItemTranslationTest {
@DisplayName("Translate Item")
public void translateItemLore() {
final I18N i18n = new I18N(Locale.FRENCH);
final ItemTranslation translation = i18n.fetchTranslation(I18NDict.GUI.Admin.Cache.STATISTICS, "1", "1");
final Translation test = i18n.translate(I18NDict.GUI.Settings.TOGGLEABLE_BUTTON, "EST", "EST");
test.lore().forEach(System.out::println);
final Translation translation = i18n.translate(I18NDict.GUI.Admin.Cache.STATISTICS, "1", "1");
translation.lore().forEach(System.out::println);
assertFalse(translation.lore().isEmpty());
assertEquals("§fNombre de requêtes: §b1", translation.lore().get(0));
assertEquals("§fNb. de skin dans le cache: §b1", translation.lore().get(1));

View file

@ -25,7 +25,7 @@ public class TranslationTest {
@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");
final String translation = i18n.translateStringWithoutPrefix(I18NDict.Event.Settings.ERROR, "Test");
assertEquals("§cImpossible de mettre à jour vos paramètres. §7§o(Test)", translation);
}