Merge pull request #155 from Dreeam-qwq/feat/i18n
i18n messages sending support
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
package fr.xephi.authme.listener.protocollib;
|
||||
|
||||
import com.comphenix.protocol.PacketType;
|
||||
import com.comphenix.protocol.ProtocolLibrary;
|
||||
import com.comphenix.protocol.events.ListenerPriority;
|
||||
import com.comphenix.protocol.events.PacketAdapter;
|
||||
import com.comphenix.protocol.events.PacketEvent;
|
||||
import fr.xephi.authme.AuthMe;
|
||||
import fr.xephi.authme.util.message.I18NUtils;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
class I18NGetLocalePacketAdapter extends PacketAdapter {
|
||||
|
||||
I18NGetLocalePacketAdapter(AuthMe plugin) {
|
||||
super(plugin, ListenerPriority.NORMAL, PacketType.Play.Client.SETTINGS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketReceiving(PacketEvent event) {
|
||||
if (event.getPacketType() == PacketType.Play.Client.SETTINGS) {
|
||||
String locale = event.getPacket().getStrings().read(0).toLowerCase();
|
||||
UUID uuid = event.getPlayer().getUniqueId();
|
||||
|
||||
I18NUtils.addLocale(uuid, locale);
|
||||
}
|
||||
}
|
||||
|
||||
public void register() {
|
||||
ProtocolLibrary.getProtocolManager().addPacketListener(this);
|
||||
}
|
||||
|
||||
public void unregister() {
|
||||
ProtocolLibrary.getProtocolManager().removePacketListener(this);
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,9 @@ import fr.xephi.authme.initialization.SettingsDependent;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.properties.PluginSettings;
|
||||
import fr.xephi.authme.settings.properties.RestrictionSettings;
|
||||
import fr.xephi.authme.util.Utils;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
@@ -22,10 +24,12 @@ public class ProtocolLibService implements SettingsDependent {
|
||||
/* Packet Adapters */
|
||||
private InventoryPacketAdapter inventoryPacketAdapter;
|
||||
private TabCompletePacketAdapter tabCompletePacketAdapter;
|
||||
private I18NGetLocalePacketAdapter i18nGetLocalePacketAdapter;
|
||||
|
||||
/* Settings */
|
||||
private boolean protectInvBeforeLogin;
|
||||
private boolean denyTabCompleteBeforeLogin;
|
||||
private boolean i18nMessagesSending;
|
||||
|
||||
/* Service */
|
||||
private boolean isEnabled;
|
||||
@@ -58,6 +62,10 @@ public class ProtocolLibService implements SettingsDependent {
|
||||
logger.warning("WARNING! The denyTabComplete feature requires ProtocolLib! Disabling it...");
|
||||
}
|
||||
|
||||
if (i18nMessagesSending) {
|
||||
logger.warning("WARNING! The i18n Messages feature requires ProtocolLib on lower version (< 1.15.2)! Disabling it...");
|
||||
}
|
||||
|
||||
this.isEnabled = false;
|
||||
return;
|
||||
}
|
||||
@@ -84,6 +92,16 @@ public class ProtocolLibService implements SettingsDependent {
|
||||
tabCompletePacketAdapter = null;
|
||||
}
|
||||
|
||||
if (i18nMessagesSending) {
|
||||
if (i18nGetLocalePacketAdapter == null) {
|
||||
i18nGetLocalePacketAdapter = new I18NGetLocalePacketAdapter(plugin);
|
||||
i18nGetLocalePacketAdapter.register();
|
||||
}
|
||||
} else if (i18nGetLocalePacketAdapter != null) {
|
||||
i18nGetLocalePacketAdapter.unregister();
|
||||
i18nGetLocalePacketAdapter = null;
|
||||
}
|
||||
|
||||
this.isEnabled = true;
|
||||
}
|
||||
|
||||
@@ -101,6 +119,10 @@ public class ProtocolLibService implements SettingsDependent {
|
||||
tabCompletePacketAdapter.unregister();
|
||||
tabCompletePacketAdapter = null;
|
||||
}
|
||||
if (i18nGetLocalePacketAdapter != null) {
|
||||
i18nGetLocalePacketAdapter.unregister();
|
||||
i18nGetLocalePacketAdapter = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -120,6 +142,7 @@ public class ProtocolLibService implements SettingsDependent {
|
||||
|
||||
this.protectInvBeforeLogin = settings.getProperty(RestrictionSettings.PROTECT_INVENTORY_BEFORE_LOGIN);
|
||||
this.denyTabCompleteBeforeLogin = settings.getProperty(RestrictionSettings.DENY_TABCOMPLETE_BEFORE_LOGIN);
|
||||
this.i18nMessagesSending = settings.getProperty(PluginSettings.I18N_MESSAGES) && Utils.MAJOR_VERSION <= 15;
|
||||
|
||||
//it was true and will be deactivated now, so we need to restore the inventory for every player
|
||||
if (oldProtectInventory && !protectInvBeforeLogin && inventoryPacketAdapter != null) {
|
||||
|
||||
@@ -8,12 +8,15 @@ import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.properties.PluginSettings;
|
||||
import fr.xephi.authme.util.FileUtils;
|
||||
import fr.xephi.authme.util.message.I18NUtils;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.inject.Inject;
|
||||
import java.io.File;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import static fr.xephi.authme.message.MessagePathHelper.DEFAULT_LANGUAGE;
|
||||
|
||||
@@ -33,6 +36,7 @@ public abstract class AbstractMessageFileHandler implements Reloadable {
|
||||
|
||||
private String filename;
|
||||
private FileConfiguration configuration;
|
||||
private Map<String, FileConfiguration> i18nConfiguration;
|
||||
private final String defaultFile;
|
||||
|
||||
protected AbstractMessageFileHandler() {
|
||||
@@ -46,6 +50,7 @@ public abstract class AbstractMessageFileHandler implements Reloadable {
|
||||
filename = createFilePath(language);
|
||||
File messagesFile = initializeFile(filename);
|
||||
configuration = YamlConfiguration.loadConfiguration(messagesFile);
|
||||
i18nConfiguration = null;
|
||||
}
|
||||
|
||||
protected String getLanguage() {
|
||||
@@ -83,6 +88,24 @@ public abstract class AbstractMessageFileHandler implements Reloadable {
|
||||
: message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the i18n message for the given key and given locale.
|
||||
*
|
||||
* @param key the key to retrieve the message for
|
||||
* @param locale the locale that player client setting uses
|
||||
* @return the message
|
||||
*/
|
||||
public String getMessageByLocale(String key, String locale) {
|
||||
if (locale == null || !settings.getProperty(PluginSettings.I18N_MESSAGES)) {
|
||||
return getMessage(key);
|
||||
}
|
||||
|
||||
String message = getI18nConfiguration(locale).getString(key);
|
||||
return message == null
|
||||
? "Error retrieving message '" + key + "'"
|
||||
: message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the message for the given key only if it exists,
|
||||
* i.e. without falling back to the default file.
|
||||
@@ -94,6 +117,27 @@ public abstract class AbstractMessageFileHandler implements Reloadable {
|
||||
return configuration.getString(key);
|
||||
}
|
||||
|
||||
public FileConfiguration getI18nConfiguration(String locale) {
|
||||
if (i18nConfiguration == null) {
|
||||
i18nConfiguration = new ConcurrentHashMap<>();
|
||||
}
|
||||
|
||||
locale = I18NUtils.localeToCode(locale, settings);
|
||||
|
||||
if (i18nConfiguration.containsKey(locale)) {
|
||||
return i18nConfiguration.get(locale);
|
||||
} else {
|
||||
// Sync with reload();
|
||||
String i18nFilename = createFilePath(locale);
|
||||
File i18nMessagesFile = initializeFile(i18nFilename);
|
||||
FileConfiguration config = YamlConfiguration.loadConfiguration(i18nMessagesFile);
|
||||
|
||||
i18nConfiguration.put(locale, config);
|
||||
|
||||
return config;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the path to the messages file for the given language code.
|
||||
*
|
||||
|
||||
@@ -5,6 +5,7 @@ import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.mail.EmailService;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import fr.xephi.authme.util.expiring.Duration;
|
||||
import fr.xephi.authme.util.message.I18NUtils;
|
||||
import fr.xephi.authme.util.message.MiniMessageUtils;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
@@ -121,7 +122,10 @@ public class Messages {
|
||||
* @return The message from the file
|
||||
*/
|
||||
private String retrieveMessage(MessageKey key, CommandSender sender) {
|
||||
String message = messagesFileHandler.getMessage(key.getKey());
|
||||
String locale = sender instanceof Player
|
||||
? I18NUtils.getLocale((Player) sender)
|
||||
: null;
|
||||
String message = messagesFileHandler.getMessageByLocale(key.getKey(), locale);
|
||||
String displayName = sender.getName();
|
||||
if (sender instanceof Player) {
|
||||
displayName = ((Player) sender).getDisplayName();
|
||||
|
||||
@@ -5,6 +5,9 @@ import ch.jalu.configme.SettingsHolder;
|
||||
import ch.jalu.configme.properties.Property;
|
||||
import fr.xephi.authme.output.LogLevel;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import static ch.jalu.configme.properties.PropertyInitializer.newLowercaseStringSetProperty;
|
||||
import static ch.jalu.configme.properties.PropertyInitializer.newProperty;
|
||||
|
||||
public final class PluginSettings implements SettingsHolder {
|
||||
@@ -16,6 +19,26 @@ public final class PluginSettings implements SettingsHolder {
|
||||
public static final Property<Boolean> MENU_UNREGISTER_COMPATIBILITY =
|
||||
newProperty("3rdPartyFeature.compatibility.menuPlugins", false);
|
||||
|
||||
@Comment({
|
||||
"Send i18n messages to player based on their client settings, this option will override `settings.messagesLanguage`",
|
||||
"(Requires Protocollib or Packetevents)",
|
||||
"This will not affect language of AuthMe help command."
|
||||
})
|
||||
public static final Property<Boolean> I18N_MESSAGES =
|
||||
newProperty("3rdPartyFeature.features.i18nMessages.enabled", false);
|
||||
|
||||
@Comment({"Redirect locale code to certain AuthMe language code as you want",
|
||||
"Minecraft locale list: https://minecraft.wiki/w/Language",
|
||||
"AuthMe language code: https://github.com/HaHaWTH/AuthMeReReloaded/blob/master/docs/translations.md",
|
||||
"For example, if you want to show Russian messages to player using language Tatar(tt_ru),",
|
||||
"and show Chinese Simplified messages to player using language Classical Chinese(lzh), then:",
|
||||
"locale-code-redirect:",
|
||||
"- 'tt_ru:ru'",
|
||||
"- 'lzh:zhcn'"})
|
||||
public static final Property<Set<String>> I18N_CODE_REDIRECT =
|
||||
newLowercaseStringSetProperty("3rdPartyFeature.features.i18nMessages.locale-code-redirect",
|
||||
"tt_ru:ru", "lzh:zhcn");
|
||||
|
||||
@Comment({
|
||||
"Do you want to enable the session feature?",
|
||||
"If enabled, when a player authenticates successfully,",
|
||||
|
||||
@@ -2,6 +2,7 @@ package fr.xephi.authme.util;
|
||||
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.ConsoleCommandSender;
|
||||
@@ -107,4 +108,12 @@ public final class Utils {
|
||||
public static boolean isEmailEmpty(String email) {
|
||||
return StringUtils.isBlank(email) || "your@email.com".equalsIgnoreCase(email);
|
||||
}
|
||||
|
||||
private final static String[] serverVersion = Bukkit.getServer().getBukkitVersion()
|
||||
.substring(0, Bukkit.getServer().getBukkitVersion().indexOf("-"))
|
||||
.split("\\.");
|
||||
|
||||
private final static int FIRST_VERSION = Integer.parseInt(serverVersion[0]);
|
||||
public final static int MAJOR_VERSION = Integer.parseInt(serverVersion[1]);
|
||||
public final static int MINOR_VERSION = serverVersion.length == 3 ? Integer.parseInt(serverVersion[2]) : 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
package fr.xephi.authme.util.message;
|
||||
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.properties.PluginSettings;
|
||||
import fr.xephi.authme.util.Utils;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class I18NUtils {
|
||||
|
||||
private static Map<UUID, String> PLAYER_LOCALE = new ConcurrentHashMap<>();
|
||||
private static final Map<String, String> LOCALE_MAP = new HashMap<>();
|
||||
private static final List<String> LOCALE_LIST = Arrays.asList(
|
||||
"en", "bg", "de", "eo", "es", "et", "eu", "fi", "fr", "gl", "hu", "id", "it", "ja", "ko", "lt", "nl", "pl",
|
||||
"pt", "ro", "ru", "sk", "sr", "tr", "uk"
|
||||
);
|
||||
|
||||
static {
|
||||
LOCALE_MAP.put("pt_br", "br");
|
||||
LOCALE_MAP.put("cs_cz", "cz");
|
||||
LOCALE_MAP.put("nds_de", "de");
|
||||
LOCALE_MAP.put("sxu", "de");
|
||||
LOCALE_MAP.put("swg", "de");
|
||||
LOCALE_MAP.put("rpr", "ru");
|
||||
LOCALE_MAP.put("sl_si", "si");
|
||||
LOCALE_MAP.put("vi_vn", "vn");
|
||||
LOCALE_MAP.put("lzh", "zhcn");
|
||||
LOCALE_MAP.put("zh_cn", "zhcn");
|
||||
LOCALE_MAP.put("zh_hk", "zhhk");
|
||||
LOCALE_MAP.put("zh_tw", "zhtw");
|
||||
//LOCALE_MAP.put("zhmc", "zhmc");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the locale that player uses.
|
||||
*
|
||||
* @param player The player
|
||||
*/
|
||||
public static String getLocale(Player player) {
|
||||
if (Utils.MAJOR_VERSION > 15) {
|
||||
return player.getLocale().toLowerCase();
|
||||
} else if (PLAYER_LOCALE.containsKey(player.getUniqueId())) {
|
||||
return PLAYER_LOCALE.get(player.getUniqueId());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void addLocale(UUID uuid, String locale) {
|
||||
if (PLAYER_LOCALE == null) {
|
||||
PLAYER_LOCALE = new ConcurrentHashMap<>();
|
||||
}
|
||||
|
||||
PLAYER_LOCALE.put(uuid, locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the AuthMe messages file language code, by given locale and settings.
|
||||
* Dreeam - Hard mapping, based on mc1.20.6, 5/29/2024
|
||||
*
|
||||
* @param locale The locale that player client setting uses.
|
||||
* @param settings The AuthMe settings, for default/fallback language usage.
|
||||
*/
|
||||
public static String localeToCode(String locale, Settings settings) {
|
||||
// Certain locale code to AuthMe language code redirect
|
||||
if (!settings.getProperty(PluginSettings.I18N_CODE_REDIRECT).isEmpty()) {
|
||||
for (String raw : settings.getProperty(PluginSettings.I18N_CODE_REDIRECT)) {
|
||||
String[] split = raw.split(":");
|
||||
|
||||
if (split.length == 2 && locale.equalsIgnoreCase(split[0])) {
|
||||
return split[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Match certain locale code
|
||||
if (LOCALE_MAP.containsKey(locale)) {
|
||||
return LOCALE_MAP.get(locale);
|
||||
}
|
||||
|
||||
if (locale.contains("_")) {
|
||||
locale = locale.substring(0, locale.indexOf("_"));
|
||||
}
|
||||
|
||||
// Match locale code with "_"
|
||||
if (LOCALE_LIST.contains(locale)) {
|
||||
return locale;
|
||||
}
|
||||
|
||||
return settings.getProperty(PluginSettings.MESSAGES_LANGUAGE);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user