mirror of
https://github.com/AuthMe/AuthMeReloaded.git
synced 2024-12-26 18:47:37 +01:00
#293 Translatable help messages: basic structure
(work in progress) - Create service that provides localized messages when available for HelpProvider
This commit is contained in:
parent
113a3f346c
commit
f6a2b2b34b
@ -9,7 +9,7 @@ import java.util.List;
|
||||
/**
|
||||
* Helper class for displaying the syntax of a command properly to a user.
|
||||
*/
|
||||
class CommandSyntaxHelper {
|
||||
final class CommandSyntaxHelper {
|
||||
|
||||
private CommandSyntaxHelper() {
|
||||
}
|
||||
|
@ -0,0 +1,49 @@
|
||||
package fr.xephi.authme.command.help;
|
||||
|
||||
/**
|
||||
* Common, non-generic keys for messages used when showing command help.
|
||||
* All keys are prefixed with {@code common}.
|
||||
*/
|
||||
public enum HelpMessageKey {
|
||||
|
||||
SHORT_DESCRIPTION("description.short", "Short description"),
|
||||
|
||||
DETAILED_DESCRIPTION("description.detailed", "Detailed description"),
|
||||
|
||||
USAGE("usage", "Usage"),
|
||||
|
||||
ARGUMENTS("arguments", "Arguments"),
|
||||
|
||||
OPTIONAL("optional", "(Optional)"),
|
||||
|
||||
HAS_PERMISSION("hasPermission", "You have permission"),
|
||||
|
||||
NO_PERMISSION("noPermission", "No permission"),
|
||||
|
||||
ALTERNATIVES("alternatives", "Alternatives"),
|
||||
|
||||
DEFAULT("default", "Default"),
|
||||
|
||||
RESULT("result", "Result"),
|
||||
|
||||
PERMISSIONS("permissions", "Permissions"),
|
||||
|
||||
COMMANDS("commands", "Commands");
|
||||
|
||||
|
||||
private final String key;
|
||||
private final String fallback;
|
||||
|
||||
HelpMessageKey(String key, String fallback) {
|
||||
this.key = "common." + key;
|
||||
this.fallback = fallback;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public String getFallback() {
|
||||
return fallback;
|
||||
}
|
||||
}
|
@ -0,0 +1,113 @@
|
||||
package fr.xephi.authme.command.help;
|
||||
|
||||
import com.google.common.base.CaseFormat;
|
||||
import fr.xephi.authme.command.CommandArgumentDescription;
|
||||
import fr.xephi.authme.command.CommandDescription;
|
||||
import fr.xephi.authme.command.CommandUtils;
|
||||
import fr.xephi.authme.initialization.DataFolder;
|
||||
import fr.xephi.authme.initialization.Reloadable;
|
||||
import fr.xephi.authme.permission.DefaultPermission;
|
||||
import fr.xephi.authme.util.FileUtils;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.io.File;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Manages translatable help messages.
|
||||
*/
|
||||
public class HelpMessagesService implements Reloadable {
|
||||
|
||||
private static final String COMMAND_PREFIX = "command.";
|
||||
private static final String DESCRIPTION_SUFFIX = ".description";
|
||||
private static final String DETAILED_DESCRIPTION_SUFFIX = ".detailedDescription";
|
||||
private static final String DEFAULT_PERMISSIONS_PATH = "common.defaultPermissions.";
|
||||
|
||||
private final File dataFolder;
|
||||
// FIXME: Make configurable
|
||||
private String file = "messages/help_en.yml";
|
||||
private FileConfiguration fileConfiguration;
|
||||
|
||||
@Inject
|
||||
HelpMessagesService(@DataFolder File dataFolder) {
|
||||
File messagesFile = new File(dataFolder, "messages/help_en.yml");
|
||||
if (!FileUtils.copyFileFromResource(messagesFile, file)) {
|
||||
throw new IllegalStateException("Could not copy help message");
|
||||
}
|
||||
this.dataFolder = dataFolder;
|
||||
fileConfiguration = YamlConfiguration.loadConfiguration(messagesFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a copy of the supplied command description with localized messages where present.
|
||||
*
|
||||
* @param command the command to build a localized version of
|
||||
* @return the localized description
|
||||
*/
|
||||
public CommandDescription buildLocalizedDescription(CommandDescription command) {
|
||||
final String path = getCommandPath(command);
|
||||
if (fileConfiguration.get(path) == null) {
|
||||
// Messages file does not have a section for this command - return the provided command
|
||||
return command;
|
||||
}
|
||||
|
||||
CommandDescription.CommandBuilder builder = CommandDescription.builder()
|
||||
.description(getText(path + DESCRIPTION_SUFFIX, command::getDescription))
|
||||
.detailedDescription(getText(path + DETAILED_DESCRIPTION_SUFFIX, command::getDetailedDescription))
|
||||
.executableCommand(command.getExecutableCommand())
|
||||
.parent(command.getParent())
|
||||
.labels(command.getLabels())
|
||||
.permission(command.getPermission());
|
||||
|
||||
int i = 1;
|
||||
for (CommandArgumentDescription argument : command.getArguments()) {
|
||||
String argPath = path + ".arg" + i;
|
||||
String label = getText(argPath + ".label", argument::getName);
|
||||
String description = getText(argPath + ".description", argument::getDescription);
|
||||
builder.withArgument(label, description, argument.isOptional());
|
||||
++i;
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
public String getMessage(HelpMessageKey key) {
|
||||
String message = fileConfiguration.getString(key.getKey());
|
||||
return message == null
|
||||
? key.getFallback()
|
||||
: message;
|
||||
}
|
||||
|
||||
public String getMessage(DefaultPermission defaultPermission) {
|
||||
// e.g. {default_permissions_path}.opOnly for DefaultPermission.OP_ONLY
|
||||
String path = DEFAULT_PERMISSIONS_PATH +
|
||||
CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, defaultPermission.name());
|
||||
String message = fileConfiguration.getString(path);
|
||||
if (message != null) {
|
||||
return message;
|
||||
}
|
||||
return defaultPermission.name(); // FIXME: Default message
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
fileConfiguration = YamlConfiguration.loadConfiguration(new File(dataFolder, "messages/help_en.yml"));
|
||||
}
|
||||
|
||||
private String getText(String path, Supplier<String> defaultTextGetter) {
|
||||
String message = fileConfiguration.getString(path);
|
||||
return message == null
|
||||
? defaultTextGetter.get()
|
||||
: message;
|
||||
}
|
||||
|
||||
private static String getCommandPath(CommandDescription command) {
|
||||
return COMMAND_PREFIX + CommandUtils.constructParentList(command)
|
||||
.stream()
|
||||
.map(cmd -> cmd.getLabels().get(0))
|
||||
.collect(Collectors.joining("."));
|
||||
}
|
||||
}
|
@ -19,6 +19,8 @@ import javax.inject.Inject;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static fr.xephi.authme.command.help.HelpMessageKey.DETAILED_DESCRIPTION;
|
||||
import static fr.xephi.authme.command.help.HelpMessageKey.SHORT_DESCRIPTION;
|
||||
import static java.util.Arrays.asList;
|
||||
import static java.util.Collections.singletonList;
|
||||
|
||||
@ -45,11 +47,13 @@ public class HelpProvider implements SettingsDependent {
|
||||
public static final int ALL_OPTIONS = ~HIDE_COMMAND;
|
||||
|
||||
private final PermissionsManager permissionsManager;
|
||||
private final HelpMessagesService helpMessagesService;
|
||||
private String helpHeader;
|
||||
|
||||
@Inject
|
||||
HelpProvider(PermissionsManager permissionsManager, Settings settings) {
|
||||
HelpProvider(PermissionsManager permissionsManager, HelpMessagesService helpMessagesService, Settings settings) {
|
||||
this.permissionsManager = permissionsManager;
|
||||
this.helpMessagesService = helpMessagesService;
|
||||
reload(settings);
|
||||
}
|
||||
|
||||
@ -61,7 +65,7 @@ public class HelpProvider implements SettingsDependent {
|
||||
List<String> lines = new ArrayList<>();
|
||||
lines.add(ChatColor.GOLD + "==========[ " + helpHeader + " HELP ]==========");
|
||||
|
||||
CommandDescription command = result.getCommandDescription();
|
||||
CommandDescription command = helpMessagesService.buildLocalizedDescription(result.getCommandDescription());
|
||||
List<String> labels = ImmutableList.copyOf(result.getLabels());
|
||||
List<String> correctLabels = ImmutableList.copyOf(filterCorrectLabels(command, labels));
|
||||
|
||||
@ -75,7 +79,7 @@ public class HelpProvider implements SettingsDependent {
|
||||
printArguments(command, lines);
|
||||
}
|
||||
if (hasFlag(SHOW_PERMISSIONS, options) && sender != null) {
|
||||
printPermissions(command, sender, permissionsManager, lines);
|
||||
printPermissions(command, sender, lines);
|
||||
}
|
||||
if (hasFlag(SHOW_ALTERNATIVES, options)) {
|
||||
printAlternatives(command, correctLabels, lines);
|
||||
@ -106,37 +110,40 @@ public class HelpProvider implements SettingsDependent {
|
||||
helpHeader = settings.getProperty(PluginSettings.HELP_HEADER);
|
||||
}
|
||||
|
||||
private static void printDetailedDescription(CommandDescription command, List<String> lines) {
|
||||
lines.add(ChatColor.GOLD + "Short description: " + ChatColor.WHITE + command.getDescription());
|
||||
lines.add(ChatColor.GOLD + "Detailed description:");
|
||||
private void printDetailedDescription(CommandDescription command, List<String> lines) {
|
||||
lines.add(ChatColor.GOLD + helpMessagesService.getMessage(SHORT_DESCRIPTION) + ": "
|
||||
+ ChatColor.WHITE + command.getDescription());
|
||||
|
||||
lines.add(ChatColor.GOLD + helpMessagesService.getMessage(DETAILED_DESCRIPTION) + ":");
|
||||
lines.add(ChatColor.WHITE + " " + command.getDetailedDescription());
|
||||
}
|
||||
|
||||
private static void printArguments(CommandDescription command, List<String> lines) {
|
||||
private void printArguments(CommandDescription command, List<String> lines) {
|
||||
if (command.getArguments().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
lines.add(ChatColor.GOLD + "Arguments:");
|
||||
lines.add(ChatColor.GOLD + helpMessagesService.getMessage(HelpMessageKey.ARGUMENTS) + ":");
|
||||
StringBuilder argString = new StringBuilder();
|
||||
String optionalText = " (" + helpMessagesService.getMessage(HelpMessageKey.OPTIONAL) + ")";
|
||||
for (CommandArgumentDescription argument : command.getArguments()) {
|
||||
argString.setLength(0);
|
||||
argString.append(" ").append(ChatColor.YELLOW).append(ChatColor.ITALIC).append(argument.getName())
|
||||
.append(": ").append(ChatColor.WHITE).append(argument.getDescription());
|
||||
|
||||
if (argument.isOptional()) {
|
||||
argString.append(ChatColor.GRAY).append(ChatColor.ITALIC).append(" (Optional)");
|
||||
argString.append(ChatColor.GRAY).append(ChatColor.ITALIC).append(optionalText);
|
||||
}
|
||||
lines.add(argString.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private static void printAlternatives(CommandDescription command, List<String> correctLabels, List<String> lines) {
|
||||
private void printAlternatives(CommandDescription command, List<String> correctLabels, List<String> lines) {
|
||||
if (command.getLabels().size() <= 1 || correctLabels.size() <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
lines.add(ChatColor.GOLD + "Alternatives:");
|
||||
lines.add(ChatColor.GOLD + helpMessagesService.getMessage(HelpMessageKey.ALTERNATIVES) + ":");
|
||||
// Get the label used
|
||||
final String parentLabel = correctLabels.get(0);
|
||||
final String childLabel = correctLabels.get(1);
|
||||
@ -149,44 +156,53 @@ public class HelpProvider implements SettingsDependent {
|
||||
}
|
||||
}
|
||||
|
||||
private static void printPermissions(CommandDescription command, CommandSender sender,
|
||||
PermissionsManager permissionsManager, List<String> lines) {
|
||||
private void printPermissions(CommandDescription command, CommandSender sender, List<String> lines) {
|
||||
PermissionNode permission = command.getPermission();
|
||||
if (permission == null) {
|
||||
return;
|
||||
}
|
||||
lines.add(ChatColor.GOLD + "Permissions:");
|
||||
lines.add(ChatColor.GOLD + helpMessagesService.getMessage(HelpMessageKey.PERMISSIONS) + ":");
|
||||
|
||||
boolean hasPermission = permissionsManager.hasPermission(sender, permission);
|
||||
final String nodePermsString = "" + ChatColor.GRAY + ChatColor.ITALIC
|
||||
+ (hasPermission ? " (You have permission)" : " (No permission)");
|
||||
lines.add(" " + ChatColor.YELLOW + ChatColor.ITALIC + permission.getNode() + nodePermsString);
|
||||
lines.add(String.format(" " + ChatColor.YELLOW + ChatColor.ITALIC + "%s" + ChatColor.GRAY + " (%s)",
|
||||
permission.getNode(), getLocalPermissionText(hasPermission)));
|
||||
|
||||
// Addendum to the line to specify whether the sender has permission or not when default is OP_ONLY
|
||||
final DefaultPermission defaultPermission = permission.getDefaultPermission();
|
||||
String addendum = "";
|
||||
if (DefaultPermission.OP_ONLY.equals(defaultPermission)) {
|
||||
addendum = defaultPermission.evaluate(sender)
|
||||
? " (You have permission)"
|
||||
: " (No permission)";
|
||||
addendum = " (" + getLocalPermissionText(defaultPermission.evaluate(sender)) + ")";
|
||||
}
|
||||
lines.add(ChatColor.GOLD + "Default: " + ChatColor.GRAY + ChatColor.ITALIC
|
||||
+ defaultPermission.getTitle() + addendum);
|
||||
lines.add(ChatColor.GOLD + helpMessagesService.getMessage(HelpMessageKey.DEFAULT) + ": "
|
||||
+ ChatColor.GRAY + ChatColor.ITALIC + helpMessagesService.getMessage(defaultPermission) + addendum);
|
||||
|
||||
// Evaluate if the sender has permission to the command
|
||||
ChatColor permissionColor;
|
||||
String permissionText;
|
||||
if (permissionsManager.hasPermission(sender, command.getPermission())) {
|
||||
lines.add(ChatColor.GOLD + " Result: " + ChatColor.GREEN + ChatColor.ITALIC + "You have permission");
|
||||
permissionColor = ChatColor.GREEN;
|
||||
permissionText = getLocalPermissionText(true);
|
||||
} else {
|
||||
lines.add(ChatColor.GOLD + " Result: " + ChatColor.DARK_RED + ChatColor.ITALIC + "No permission");
|
||||
permissionColor = ChatColor.DARK_RED;
|
||||
permissionText = getLocalPermissionText(false);
|
||||
}
|
||||
lines.add(String.format(ChatColor.GOLD + " %s: %s" + ChatColor.ITALIC + "%s",
|
||||
helpMessagesService.getMessage(HelpMessageKey.RESULT), permissionColor, permissionText));
|
||||
}
|
||||
|
||||
private static void printChildren(CommandDescription command, List<String> parentLabels, List<String> lines) {
|
||||
private String getLocalPermissionText(boolean hasPermission) {
|
||||
if (hasPermission) {
|
||||
return helpMessagesService.getMessage(HelpMessageKey.HAS_PERMISSION);
|
||||
}
|
||||
return helpMessagesService.getMessage(HelpMessageKey.NO_PERMISSION);
|
||||
}
|
||||
|
||||
private void printChildren(CommandDescription command, List<String> parentLabels, List<String> lines) {
|
||||
if (command.getChildren().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
lines.add(ChatColor.GOLD + "Commands:");
|
||||
lines.add(ChatColor.GOLD + helpMessagesService.getMessage(HelpMessageKey.COMMANDS) + ":");
|
||||
String parentCommandPath = CommandUtils.labelsToString(parentLabels);
|
||||
for (CommandDescription child : command.getChildren()) {
|
||||
lines.add(" /" + parentCommandPath + " " + child.getLabels().get(0)
|
||||
|
@ -8,7 +8,7 @@ import org.bukkit.permissions.ServerOperator;
|
||||
public enum DefaultPermission {
|
||||
|
||||
/** No one has permission. */
|
||||
NOT_ALLOWED("No permission") {
|
||||
NOT_ALLOWED {
|
||||
@Override
|
||||
public boolean evaluate(ServerOperator sender) {
|
||||
return false;
|
||||
@ -16,7 +16,7 @@ public enum DefaultPermission {
|
||||
},
|
||||
|
||||
/** Only players with OP status have permission. */
|
||||
OP_ONLY("OP's only") {
|
||||
OP_ONLY {
|
||||
@Override
|
||||
public boolean evaluate(ServerOperator sender) {
|
||||
return sender != null && sender.isOp();
|
||||
@ -24,24 +24,13 @@ public enum DefaultPermission {
|
||||
},
|
||||
|
||||
/** Everyone is granted permission. */
|
||||
ALLOWED("Everyone allowed") {
|
||||
ALLOWED {
|
||||
@Override
|
||||
public boolean evaluate(ServerOperator sender) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/** Textual representation of the default permission. */
|
||||
private final String title;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param title The textual representation
|
||||
*/
|
||||
DefaultPermission(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluates whether permission is granted to the sender or not.
|
||||
*
|
||||
@ -50,13 +39,4 @@ public enum DefaultPermission {
|
||||
*/
|
||||
public abstract boolean evaluate(ServerOperator sender);
|
||||
|
||||
/**
|
||||
* Return the textual representation.
|
||||
*
|
||||
* @return the textual representation
|
||||
*/
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
}
|
||||
|
30
src/main/resources/messages/help_en.yml
Normal file
30
src/main/resources/messages/help_en.yml
Normal file
@ -0,0 +1,30 @@
|
||||
common:
|
||||
description.short: 'Short description'
|
||||
description.detailed: 'Detailed description'
|
||||
usage: 'Usage'
|
||||
arguments: 'Arguments'
|
||||
permissions: 'Permissions'
|
||||
optional: '(Optional)'
|
||||
hasPermission: 'You have permission'
|
||||
noPermission: 'No permission'
|
||||
default: 'Default'
|
||||
alternatives: 'Alternatives'
|
||||
result: 'Result'
|
||||
commands: 'Commands'
|
||||
defaultPermissions:
|
||||
notAllowed: 'No permission'
|
||||
opOnly: 'OP''s only'
|
||||
allowed: 'Everyone allowed'
|
||||
command:
|
||||
register:
|
||||
description: 'Register with this command'
|
||||
detailedDescription: 'Use /register <pw> <pw>'
|
||||
authme.register:
|
||||
description: 'Admin registration'
|
||||
detailedDescription: 'Used by l33t adminz'
|
||||
arg1:
|
||||
label: 'n4me'
|
||||
description: 'The name to save'
|
||||
arg2:
|
||||
label: 'passw0rd'
|
||||
description: 'Password to use yo'
|
@ -1,5 +1,8 @@
|
||||
package fr.xephi.authme.command.help;
|
||||
|
||||
import ch.jalu.injector.testing.BeforeInjecting;
|
||||
import ch.jalu.injector.testing.DelayedInjectionRunner;
|
||||
import ch.jalu.injector.testing.InjectDelayed;
|
||||
import fr.xephi.authme.command.CommandDescription;
|
||||
import fr.xephi.authme.command.FoundCommandResult;
|
||||
import fr.xephi.authme.command.FoundResultStatus;
|
||||
@ -10,10 +13,12 @@ import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.properties.PluginSettings;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
@ -41,12 +46,21 @@ import static org.mockito.Mockito.verify;
|
||||
/**
|
||||
* Test for {@link HelpProvider}.
|
||||
*/
|
||||
@RunWith(DelayedInjectionRunner.class)
|
||||
public class HelpProviderTest {
|
||||
|
||||
private static final String HELP_HEADER = "Help";
|
||||
private static Set<CommandDescription> commands;
|
||||
|
||||
@InjectDelayed
|
||||
private HelpProvider helpProvider;
|
||||
@Mock
|
||||
private PermissionsManager permissionsManager;
|
||||
@Mock
|
||||
private HelpMessagesService helpMessagesService;
|
||||
@Mock
|
||||
private Settings settings;
|
||||
@Mock
|
||||
private CommandSender sender;
|
||||
|
||||
@BeforeClass
|
||||
@ -54,16 +68,13 @@ public class HelpProviderTest {
|
||||
commands = TestCommandsUtil.generateCommands();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUpHelpProvider() {
|
||||
permissionsManager = mock(PermissionsManager.class);
|
||||
Settings settings = mock(Settings.class);
|
||||
@BeforeInjecting
|
||||
public void setInitialSettings() {
|
||||
given(settings.getProperty(PluginSettings.HELP_HEADER)).willReturn(HELP_HEADER);
|
||||
helpProvider = new HelpProvider(permissionsManager, settings);
|
||||
sender = mock(CommandSender.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore // FIXME: Fix test
|
||||
public void shouldShowLongDescription() {
|
||||
// given
|
||||
CommandDescription command = getCommandWithLabel(commands, "authme", "login");
|
||||
|
Loading…
Reference in New Issue
Block a user