Fix locales to show correctly based on GameMode and locations

Fixes console translations too.

https://github.com/BentoBoxWorld/BentoBox/issues/519
This commit is contained in:
tastybento 2019-02-04 23:02:07 -08:00
parent fd882c018b
commit 3ccd19bf9c
5 changed files with 77 additions and 28 deletions

View File

@ -18,9 +18,9 @@ import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.PluginIdentifiableCommand;
import org.bukkit.entity.Player;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.Settings;
import world.bentobox.bentobox.api.addons.Addon;
@ -241,6 +241,8 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
if (event.isCancelled()) {
return false;
}
// Set the user's addon context
user.setAddon(addon);
// Execute and trim args
return cmd.execute(user, (cmd.subCommandLevel > 0) ? args[cmd.subCommandLevel-1] : label, Arrays.asList(args).subList(cmd.subCommandLevel, args.length));
}

View File

@ -21,6 +21,7 @@ import org.bukkit.permissions.PermissionAttachmentInfo;
import org.bukkit.util.Vector;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.addons.Addon;
/**
* Combines {@link Player}, {@link OfflinePlayer} and {@link CommandSender} to provide convenience methods related to
@ -104,6 +105,8 @@ public class User {
private final UUID playerUUID;
private final CommandSender sender;
private Addon addon;
private User(CommandSender sender) {
player = null;
playerUUID = null;
@ -235,6 +238,21 @@ public class User {
return value;
}
/**
* Gets a translation for a specific world
* @param world - world of translation
* @param reference - reference found in a locale file
* @param variables - variables to insert into translated string. Variables go in pairs, for example
* "[name]", "tastybento"
* @return Translated string with colors converted, or the reference if nothing has been found
*/
public String getTranslation(World world, String reference, String... variables) {
// Get translation.
String addonPrefix = plugin.getIWM()
.getAddon(world).map(a -> a.getDescription().getName().toLowerCase() + ".").orElse("");
return translate(addonPrefix, reference, variables);
}
/**
* Gets a translation of this reference for this user. Translations may be overridden by Addons
* by using the same reference prefixed by the addon name (from the Addon Description) in lower case.
@ -244,9 +262,12 @@ public class User {
* @return Translated string with colors converted, or the reference if nothing has been found
*/
public String getTranslation(String reference, String... variables) {
// Get translation.
String addonPrefix = plugin.getIWM()
.getAddon(getWorld()).map(a -> a.getDescription().getName().toLowerCase() + ".").orElse("");
// Get addonPrefix
String addonPrefix = addon == null ? "" : addon.getDescription().getName().toLowerCase() + ".";
return translate(addonPrefix, reference, variables);
}
private String translate(String addonPrefix, String reference, String[] variables) {
String translation = plugin.getLocalesManager().get(this, addonPrefix + reference);
if (translation == null) {
@ -315,6 +336,21 @@ public class User {
}
}
/**
* Sends a message to sender if message is not empty and if the same wasn't sent within the previous {@link Notifier#NOTIFICATION_DELAY} seconds.
* @param world - the world the translation should come from
* @param reference - language file reference
* @param variables - CharSequence target, replacement pairs
*
* @see Notifier
*/
public void notify(World world, String reference, String... variables) {
String message = getTranslation(world, reference, variables);
if (!ChatColor.stripColor(message).trim().isEmpty() && sender != null) {
plugin.getNotifier().notify(this, message);
}
}
/**
* Sets the user's game mode
* @param mode - GameMode
@ -452,4 +488,13 @@ public class User {
return other.playerUUID == null;
} else return playerUUID.equals(other.playerUUID);
}
/**
* Set the addon context when a command is executed
* @param addon - the addon executing the command
*/
public void setAddon(Addon addon) {
this.addon = addon;
}
}

View File

@ -71,12 +71,13 @@ public class EnterExitListener extends FlagListener {
// Send message if island is owned by someone
if (i.getOwner() != null) {
user.notify("protection.flags.ENTER_EXIT_MESSAGES.now-leaving", TextVariables.NAME, (i.getName() != null) ? i.getName() :
user.getTranslation("protection.flags.ENTER_EXIT_MESSAGES.island", TextVariables.NAME, getPlugin().getPlayers().getName(i.getOwner())));
// Leave messages are always specific to this world
user.notify(i.getWorld(), "protection.flags.ENTER_EXIT_MESSAGES.now-leaving", TextVariables.NAME, (i.getName() != null) ? i.getName() :
user.getTranslation(i.getWorld(), "protection.flags.ENTER_EXIT_MESSAGES.island", TextVariables.NAME, getPlugin().getPlayers().getName(i.getOwner())));
}
// Send message if island is unowned, but has a name
else if (i.getName() != null) {
user.notify("protection.flags.ENTER_EXIT_MESSAGES.now-leaving", TextVariables.NAME, i.getName());
user.notify(i.getWorld(), "protection.flags.ENTER_EXIT_MESSAGES.now-leaving", TextVariables.NAME, i.getName());
}
});

View File

@ -67,13 +67,13 @@ public class FlagTest {
when(iwm.getWorldSettings(Mockito.any())).thenReturn(ws);
Map<String, Boolean> worldFlags = new HashMap<>();
when(ws.getWorldFlags()).thenReturn(worldFlags);
PowerMockito.mockStatic(Bukkit.class);
ItemFactory itemF = mock(ItemFactory.class);
ItemMeta im = mock(ItemMeta.class);
when(itemF.getItemMeta(Mockito.any())).thenReturn(im);
when(Bukkit.getItemFactory()).thenReturn(itemF);
}
@Test
@ -129,9 +129,9 @@ public class FlagTest {
assertTrue(id.isSetForWorld(mock(World.class)));
id.setDefaultSetting(false);
assertFalse(id.isSetForWorld(mock(World.class)));
}
@Test
public void testIsDefaultSetting_World_Setting() {
Type type = Type.WORLD_SETTING;
@ -162,31 +162,31 @@ public class FlagTest {
public void testEqualsObject() {
Flag flag1 = null;
Flag flag2 = new Flag(null, null, null, null, 0, null, false);
assertFalse(flag2.equals(null));
int i = 45;
assertFalse(flag2.equals(i));
flag1 = new Flag(null, null, null, null, 0, null, false);
flag2 = flag1;
assertTrue(flag1.equals(flag2));
assertTrue(flag2.equals(flag1));
flag2 = new Flag("id", Material.ACACIA_DOOR, null, Flag.Type.PROTECTION, 0, null, false);
assertFalse(flag1.equals(flag2));
assertFalse(flag2.equals(flag1));
}
@Test
public void testToPanelItem() throws Exception {
BentoBox plugin = mock(BentoBox.class);
IslandsManager im = mock(IslandsManager.class);
Island island = mock(Island.class);
when(island.getFlag(Mockito.any())).thenReturn(RanksManager.VISITOR_RANK);
User user = mock(User.class);
when(user.getUniqueId()).thenReturn(UUID.randomUUID());
Answer<String> answer = invocation -> {
@ -195,30 +195,29 @@ public class FlagTest {
sb.append("mock");
return sb.toString();
};
when(user.getTranslation(Mockito.anyVararg())).thenAnswer(answer);
when(user.getTranslation(Mockito.any(),Mockito.any(),Mockito.any())).thenAnswer(answer);
when(user.getTranslation(Mockito.any(String.class),Mockito.any(),Mockito.any())).thenAnswer(answer);
when(im.getIsland(Mockito.any(), Mockito.any(UUID.class))).thenReturn(island);
when(im.getIsland(Mockito.any(), Mockito.any(User.class))).thenReturn(island);
Optional<Island> oL = Optional.of(island);
when(im.getIslandAt(Mockito.any(Location.class))).thenReturn(oL);
when(plugin.getIslands()).thenReturn(im);
RanksManager rm = mock(RanksManager.class);
when(plugin.getRanksManager()).thenReturn(rm);
when(rm.getRank(Mockito.eq(RanksManager.VISITOR_RANK))).thenReturn("Visitor");
when(rm.getRank(Mockito.eq(RanksManager.OWNER_RANK))).thenReturn("Owner");
Flag id = new Flag("id", Material.ACACIA_DOOR, null, Flag.Type.PROTECTION, 0, null, false);
PanelItem pi = id.toPanelItem(plugin, user);
verify(user).getTranslation(Mockito.eq("protection.flags.id.name"));
verify(user).getTranslation(Mockito.eq("protection.panel.flag-item.name-layout"), Mockito.anyVararg());
assertEquals(Material.ACACIA_DOOR, pi.getItem().getType());
}
@Test

View File

@ -261,6 +261,8 @@ public class UserTest {
GameModeAddon addon = mock(GameModeAddon.class);
AddonDescription desc = new AddonDescription.Builder("mock", "name", "1.0").build();
when(addon.getDescription()).thenReturn(desc);
// Set addon context
user.setAddon(addon);
Optional<GameModeAddon> optionalAddon = Optional.of(addon);
when(iwm .getAddon(any())).thenReturn(optionalAddon);
when(lm.get(any(), Mockito.eq("name.a.reference"))).thenReturn("mockmockmock");