diff --git a/.github/workflows/crowdin-download.yaml b/.github/workflows/crowdin-download.yaml index 0531d3cc..8270df11 100644 --- a/.github/workflows/crowdin-download.yaml +++ b/.github/workflows/crowdin-download.yaml @@ -40,6 +40,6 @@ jobs: project_id: ${{ secrets.CROWDIN_PROJECT_ID }} token: ${{ secrets.CROWDIN_PERSONAL_TOKEN }} source: "i18n/build/source.yaml" - translation: "/i18n/src/main/resources/translations/%three_letters_code%.%file_extension%" + translation: "/i18n/src/main/resources/translations/%two_letters_code%.%file_extension%" env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/crowdin-upload.yaml b/.github/workflows/crowdin-upload.yaml index 42fd2b79..f35cabb0 100644 --- a/.github/workflows/crowdin-upload.yaml +++ b/.github/workflows/crowdin-upload.yaml @@ -32,6 +32,6 @@ jobs: project_id: ${{ secrets.CROWDIN_PROJECT_ID }} token: ${{ secrets.CROWDIN_PERSONAL_TOKEN }} source: "i18n/build/source.yaml" - translation: "/i18n/src/main/resources/translations/%three_letters_code%.%file_extension%" + translation: "/i18n/src/main/resources/translations/%two_letters_code%.%file_extension%" env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/bukkit/src/main/java/com/discordsrv/bukkit/BukkitDiscordSRV.java b/bukkit/src/main/java/com/discordsrv/bukkit/BukkitDiscordSRV.java index 271d8dbf..192fc968 100644 --- a/bukkit/src/main/java/com/discordsrv/bukkit/BukkitDiscordSRV.java +++ b/bukkit/src/main/java/com/discordsrv/bukkit/BukkitDiscordSRV.java @@ -26,6 +26,7 @@ import com.discordsrv.bukkit.config.connection.BukkitConnectionConfig; import com.discordsrv.bukkit.config.main.BukkitConfig; import com.discordsrv.bukkit.config.manager.BukkitConfigManager; import com.discordsrv.bukkit.config.manager.BukkitConnectionConfigManager; +import com.discordsrv.bukkit.config.manager.BukkitMessagesConfigManager; import com.discordsrv.bukkit.console.BukkitConsole; import com.discordsrv.bukkit.listener.BukkitConnectionListener; import com.discordsrv.bukkit.listener.BukkitDeathListener; @@ -43,6 +44,8 @@ import com.discordsrv.common.ServerDiscordSRV; import com.discordsrv.common.command.game.handler.ICommandHandler; import com.discordsrv.common.config.configurate.manager.ConnectionConfigManager; import com.discordsrv.common.config.configurate.manager.MainConfigManager; +import com.discordsrv.common.config.configurate.manager.MessagesConfigManager; +import com.discordsrv.common.config.messages.MessagesConfig; import com.discordsrv.common.debug.data.OnlineMode; import com.discordsrv.common.messageforwarding.game.minecrafttodiscord.MinecraftToDiscordChatModule; import com.discordsrv.common.plugin.PluginManager; @@ -56,7 +59,7 @@ import java.lang.reflect.Field; import java.util.List; import java.util.Set; -public class BukkitDiscordSRV extends ServerDiscordSRV { +public class BukkitDiscordSRV extends ServerDiscordSRV { private BukkitAudiences audiences; private BukkitTranslationLoader translationLoader; @@ -71,6 +74,7 @@ public class BukkitDiscordSRV extends ServerDiscordSRV messagesConfigManager() { + return messagesConfigManager; + } + @Override protected void enable() throws Throwable { // Service provider diff --git a/bukkit/src/main/java/com/discordsrv/bukkit/config/manager/BukkitMessagesConfigManager.java b/bukkit/src/main/java/com/discordsrv/bukkit/config/manager/BukkitMessagesConfigManager.java new file mode 100644 index 00000000..e00b3bad --- /dev/null +++ b/bukkit/src/main/java/com/discordsrv/bukkit/config/manager/BukkitMessagesConfigManager.java @@ -0,0 +1,17 @@ +package com.discordsrv.bukkit.config.manager; + +import com.discordsrv.common.DiscordSRV; +import com.discordsrv.common.config.configurate.manager.MessagesConfigManager; +import com.discordsrv.common.config.messages.MessagesConfig; + +public class BukkitMessagesConfigManager extends MessagesConfigManager { + + public BukkitMessagesConfigManager(DiscordSRV discordSRV) { + super(discordSRV); + } + + @Override + public MessagesConfig createConfiguration() { + return new MessagesConfig(); + } +} diff --git a/bungee/src/main/java/com/discordsrv/bungee/BungeeDiscordSRV.java b/bungee/src/main/java/com/discordsrv/bungee/BungeeDiscordSRV.java index 6a75c547..3c0d43f1 100644 --- a/bungee/src/main/java/com/discordsrv/bungee/BungeeDiscordSRV.java +++ b/bungee/src/main/java/com/discordsrv/bungee/BungeeDiscordSRV.java @@ -24,10 +24,12 @@ import com.discordsrv.bungee.player.BungeePlayerProvider; import com.discordsrv.bungee.plugin.BungeePluginManager; import com.discordsrv.common.ProxyDiscordSRV; import com.discordsrv.common.command.game.handler.ICommandHandler; +import com.discordsrv.common.config.configurate.manager.MessagesConfigManager; import com.discordsrv.common.config.connection.ConnectionConfig; import com.discordsrv.common.config.main.MainConfig; import com.discordsrv.common.config.configurate.manager.ConnectionConfigManager; import com.discordsrv.common.config.configurate.manager.MainConfigManager; +import com.discordsrv.common.config.messages.MessagesConfig; import com.discordsrv.common.debug.data.OnlineMode; import com.discordsrv.common.plugin.PluginManager; import com.discordsrv.common.scheduler.StandardScheduler; @@ -36,7 +38,7 @@ import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.plugin.Plugin; import org.jetbrains.annotations.NotNull; -public class BungeeDiscordSRV extends ProxyDiscordSRV { +public class BungeeDiscordSRV extends ProxyDiscordSRV { private BungeeAudiences audiences; @@ -109,6 +111,11 @@ public class BungeeDiscordSRV extends ProxyDiscordSRV messagesConfigManager() { + return null; + } + @Override protected void enable() throws Throwable { // Player related diff --git a/common/src/main/java/com/discordsrv/common/AbstractDiscordSRV.java b/common/src/main/java/com/discordsrv/common/AbstractDiscordSRV.java index 21924a8b..04156fe0 100644 --- a/common/src/main/java/com/discordsrv/common/AbstractDiscordSRV.java +++ b/common/src/main/java/com/discordsrv/common/AbstractDiscordSRV.java @@ -33,12 +33,15 @@ import com.discordsrv.common.command.discord.DiscordCommandModule; import com.discordsrv.common.command.game.GameCommandModule; import com.discordsrv.common.command.game.commands.subcommand.reload.ReloadResults; import com.discordsrv.common.component.ComponentFactory; +import com.discordsrv.common.config.configurate.manager.ConnectionConfigManager; +import com.discordsrv.common.config.configurate.manager.MainConfigManager; +import com.discordsrv.common.config.configurate.manager.MessagesConfigManager; +import com.discordsrv.common.config.configurate.manager.MessagesConfigSingleManager; import com.discordsrv.common.config.connection.ConnectionConfig; import com.discordsrv.common.config.connection.UpdateConfig; import com.discordsrv.common.config.main.MainConfig; import com.discordsrv.common.config.main.linking.LinkedAccountConfig; -import com.discordsrv.common.config.configurate.manager.ConnectionConfigManager; -import com.discordsrv.common.config.configurate.manager.MainConfigManager; +import com.discordsrv.common.config.messages.MessagesConfig; import com.discordsrv.common.debug.data.VersionInfo; import com.discordsrv.common.dependency.DiscordSRVDependencyManager; import com.discordsrv.common.discord.api.DiscordAPIEventModule; @@ -84,6 +87,7 @@ import okhttp3.ConnectionPool; import okhttp3.Dispatcher; import okhttp3.OkHttpClient; import okhttp3.Request; +import org.apache.commons.lang3.StringUtils; import org.intellij.lang.annotations.Language; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -110,7 +114,12 @@ import java.util.jar.Manifest; * @param the config type * @param the connections config type */ -public abstract class AbstractDiscordSRV implements DiscordSRV { +public abstract class AbstractDiscordSRV< + B extends IBootstrap, + C extends MainConfig, + CC extends ConnectionConfig, + MC extends MessagesConfig +> implements DiscordSRV { private final AtomicReference status = new AtomicReference<>(Status.INITIALIZED); private final AtomicReference beenReady = new AtomicReference<>(false); @@ -380,6 +389,21 @@ public abstract class AbstractDiscordSRV messagesConfigManager(); + + @Override + public MC messagesConfig(Locale locale) { + MessagesConfigSingleManager manager = messagesConfigManager().getManager(locale); + if (manager == null) { + manager = messagesConfigManager().getManager(defaultLocale()); + } + if (manager == null) { + manager = messagesConfigManager().getManager(Locale.US); + } + return manager.config(); + } + // Module @Override @@ -430,8 +454,15 @@ public abstract class AbstractDiscordSRV configManager(); MainConfig config(); + MessagesConfigManager messagesConfigManager(); + MessagesConfig messagesConfig(Locale locale); + // Config helper ChannelConfigHelper channelConfig(); @@ -130,7 +135,7 @@ public interface DiscordSRV extends DiscordSRVApi { void unregisterModule(AbstractModule module); ModuleManager moduleManager(); - Locale locale(); + Locale defaultLocale(); // Status void setStatus(Status status); diff --git a/common/src/main/java/com/discordsrv/common/ProxyDiscordSRV.java b/common/src/main/java/com/discordsrv/common/ProxyDiscordSRV.java index 325ea7a5..5951edd4 100644 --- a/common/src/main/java/com/discordsrv/common/ProxyDiscordSRV.java +++ b/common/src/main/java/com/discordsrv/common/ProxyDiscordSRV.java @@ -21,9 +21,15 @@ package com.discordsrv.common; import com.discordsrv.common.bootstrap.IBootstrap; import com.discordsrv.common.config.connection.ConnectionConfig; import com.discordsrv.common.config.main.MainConfig; +import com.discordsrv.common.config.messages.MessagesConfig; import com.discordsrv.common.messageforwarding.game.ServerSwitchMessageModule; -public abstract class ProxyDiscordSRV extends AbstractDiscordSRV { +public abstract class ProxyDiscordSRV< + B extends IBootstrap, + C extends MainConfig, + CC extends ConnectionConfig, + MC extends MessagesConfig +> extends AbstractDiscordSRV { public ProxyDiscordSRV(B bootstrap) { super(bootstrap); diff --git a/common/src/main/java/com/discordsrv/common/ServerDiscordSRV.java b/common/src/main/java/com/discordsrv/common/ServerDiscordSRV.java index 62c31698..4b4f27ff 100644 --- a/common/src/main/java/com/discordsrv/common/ServerDiscordSRV.java +++ b/common/src/main/java/com/discordsrv/common/ServerDiscordSRV.java @@ -21,6 +21,7 @@ package com.discordsrv.common; import com.discordsrv.common.bootstrap.IBootstrap; import com.discordsrv.common.config.connection.ConnectionConfig; import com.discordsrv.common.config.main.MainConfig; +import com.discordsrv.common.config.messages.MessagesConfig; import com.discordsrv.common.messageforwarding.game.AwardMessageModule; import com.discordsrv.common.messageforwarding.game.DeathMessageModule; import com.discordsrv.common.player.ServerPlayerProvider; @@ -30,7 +31,12 @@ import org.jetbrains.annotations.NotNull; import javax.annotation.OverridingMethodsMustInvokeSuper; import java.util.concurrent.CompletableFuture; -public abstract class ServerDiscordSRV extends AbstractDiscordSRV { +public abstract class ServerDiscordSRV< + B extends IBootstrap, + C extends MainConfig, + CC extends ConnectionConfig, + MC extends MessagesConfig +> extends AbstractDiscordSRV { public ServerDiscordSRV(B bootstrap) { super(bootstrap); diff --git a/common/src/main/java/com/discordsrv/common/config/configurate/manager/MessagesConfigManager.java b/common/src/main/java/com/discordsrv/common/config/configurate/manager/MessagesConfigManager.java new file mode 100644 index 00000000..d890b676 --- /dev/null +++ b/common/src/main/java/com/discordsrv/common/config/configurate/manager/MessagesConfigManager.java @@ -0,0 +1,91 @@ +package com.discordsrv.common.config.configurate.manager; + +import com.discordsrv.common.DiscordSRV; +import com.discordsrv.common.config.main.MainConfig; +import com.discordsrv.common.config.messages.MessagesConfig; +import com.discordsrv.common.exception.ConfigException; +import com.discordsrv.common.logging.Logger; +import com.discordsrv.common.logging.NamedLogger; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.*; +import java.util.stream.Stream; + +public abstract class MessagesConfigManager { + + private final Map> configs = new LinkedHashMap<>(); + private final DiscordSRV discordSRV; + private final Logger logger; + + public MessagesConfigManager(DiscordSRV discordSRV) { + this.discordSRV = discordSRV; + this.logger = new NamedLogger(discordSRV, "MESSAGES_CONFIG"); + } + + public abstract C createConfiguration(); + + public MessagesConfigSingleManager getManager(Locale locale) { + synchronized (configs) { + return configs.get(locale); + } + } + + public Path directory() { + return discordSRV.dataDirectory().resolve("messages"); + } + + public void load() throws ConfigException { + synchronized (configs) { + configs.clear(); + + MainConfig config = discordSRV.config(); + if (config == null) { + throw new ConfigException("MainConfig not available"); + } + + if (config.messages.multiple) { + try { + Path messagesDirectory = directory(); + if (!Files.exists(messagesDirectory)) { + Files.createDirectory(messagesDirectory); + } + + List existing = new ArrayList<>(); + try (Stream paths = Files.list(messagesDirectory)) { + paths.forEach(path -> { + String fileName = path.getFileName().toString(); + String[] parts = fileName.split("\\.", 2); + if (parts.length != 2 || !parts[1].equals("yaml")) { + logger.warning("Unexpected messages file: " + fileName + " (invalid language code or not .yaml)"); + return; + } + + Locale locale = Locale.forLanguageTag(parts[0]); + if (locale == null) { + logger.warning("Unexpected messages file: " + fileName + " (unknown locale)"); + return; + } + + configs.put(locale, new MessagesConfigSingleManager<>(discordSRV, this, locale, true)); + existing.add(locale); + }); + } + + if (config.messages.loadAllDefaults) { + // TODO: load all default default locales missing + } + } catch (Throwable t) { + throw new ConfigException("Failed to initialize messages configs", t); + } + } else { + Locale defaultLocale = discordSRV.defaultLocale(); + configs.put(defaultLocale, new MessagesConfigSingleManager<>(discordSRV, this, defaultLocale, false)); + } + + for (Map.Entry> entry : configs.entrySet()) { + entry.getValue().load(); + } + } + } +} diff --git a/common/src/main/java/com/discordsrv/common/config/configurate/manager/MessagesConfigSingleManager.java b/common/src/main/java/com/discordsrv/common/config/configurate/manager/MessagesConfigSingleManager.java new file mode 100644 index 00000000..bf1ad923 --- /dev/null +++ b/common/src/main/java/com/discordsrv/common/config/configurate/manager/MessagesConfigSingleManager.java @@ -0,0 +1,44 @@ +package com.discordsrv.common.config.configurate.manager; + +import com.discordsrv.common.DiscordSRV; +import com.discordsrv.common.config.configurate.manager.abstraction.TranslatedConfigManager; +import com.discordsrv.common.config.configurate.manager.loader.YamlConfigLoaderProvider; +import com.discordsrv.common.config.messages.MessagesConfig; +import org.spongepowered.configurate.yaml.YamlConfigurationLoader; + +import java.util.Locale; + +public class MessagesConfigSingleManager + extends TranslatedConfigManager + implements YamlConfigLoaderProvider { + + private final MessagesConfigManager aggregateManager; + private final Locale locale; + private final boolean multi; + + protected MessagesConfigSingleManager(DiscordSRV discordSRV, MessagesConfigManager aggregateManager, Locale locale, boolean multi) { + super(discordSRV); + this.aggregateManager = aggregateManager; + this.locale = locale; + this.multi = multi; + } + + @Override + protected String fileName() { + if (multi) { + return aggregateManager.directory().resolve(locale.getISO3Language() + ".yaml").toString(); + } + + return MessagesConfig.FILE_NAME; + } + + @Override + public Locale locale() { + return locale; + } + + @Override + public C createConfiguration() { + return aggregateManager.createConfiguration(); + } +} diff --git a/common/src/main/java/com/discordsrv/common/config/configurate/manager/abstraction/ConfigurateConfigManager.java b/common/src/main/java/com/discordsrv/common/config/configurate/manager/abstraction/ConfigurateConfigManager.java index 2da5526d..8f47b3ae 100644 --- a/common/src/main/java/com/discordsrv/common/config/configurate/manager/abstraction/ConfigurateConfigManager.java +++ b/common/src/main/java/com/discordsrv/common/config/configurate/manager/abstraction/ConfigurateConfigManager.java @@ -71,7 +71,7 @@ public abstract class ConfigurateConfigManager) configuration.getClass(), node); loader.save(node); diff --git a/common/src/main/java/com/discordsrv/common/config/configurate/manager/abstraction/TranslatedConfigManager.java b/common/src/main/java/com/discordsrv/common/config/configurate/manager/abstraction/TranslatedConfigManager.java index 877af294..37356201 100644 --- a/common/src/main/java/com/discordsrv/common/config/configurate/manager/abstraction/TranslatedConfigManager.java +++ b/common/src/main/java/com/discordsrv/common/config/configurate/manager/abstraction/TranslatedConfigManager.java @@ -36,6 +36,7 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Locale; public abstract class TranslatedConfigManager> extends ConfigurateConfigManager { @@ -53,6 +54,10 @@ public abstract class TranslatedConfigManager { } gameChannel.sendMessage(component); + discordSRV.eventBus().publish(new DiscordChatMessageForwardedEvent(component, gameChannel)); } public static class MessageSend { diff --git a/common/src/test/java/com/discordsrv/common/MockDiscordSRV.java b/common/src/test/java/com/discordsrv/common/MockDiscordSRV.java index cd7bf0f1..1c411759 100644 --- a/common/src/test/java/com/discordsrv/common/MockDiscordSRV.java +++ b/common/src/test/java/com/discordsrv/common/MockDiscordSRV.java @@ -24,6 +24,7 @@ import com.discordsrv.common.bootstrap.LifecycleManager; import com.discordsrv.common.command.game.handler.ICommandHandler; import com.discordsrv.common.config.configurate.manager.ConnectionConfigManager; import com.discordsrv.common.config.configurate.manager.MainConfigManager; +import com.discordsrv.common.config.configurate.manager.MessagesConfigManager; import com.discordsrv.common.config.configurate.manager.abstraction.ServerConfigManager; import com.discordsrv.common.config.connection.ConnectionConfig; import com.discordsrv.common.config.main.MainConfig; @@ -31,6 +32,7 @@ import com.discordsrv.common.config.main.PluginIntegrationConfig; import com.discordsrv.common.config.main.channels.base.ChannelConfig; import com.discordsrv.common.config.main.generic.DestinationConfig; import com.discordsrv.common.config.main.generic.ThreadConfig; +import com.discordsrv.common.config.messages.MessagesConfig; import com.discordsrv.common.console.Console; import com.discordsrv.common.debug.data.OnlineMode; import com.discordsrv.common.debug.data.VersionInfo; @@ -54,7 +56,7 @@ import java.nio.file.Paths; import java.util.List; @SuppressWarnings("ConstantConditions") -public class MockDiscordSRV extends AbstractDiscordSRV { +public class MockDiscordSRV extends AbstractDiscordSRV { public static final MockDiscordSRV INSTANCE = new MockDiscordSRV(); @@ -225,4 +227,9 @@ public class MockDiscordSRV extends AbstractDiscordSRV messagesConfigManager() { + return null; + } } diff --git a/i18n/src/main/java/com/discordsrv/config/MockDiscordSRV.java b/i18n/src/main/java/com/discordsrv/config/MockDiscordSRV.java new file mode 100644 index 00000000..e69de29b diff --git a/sponge/src/main/java/com/discordsrv/sponge/SpongeDiscordSRV.java b/sponge/src/main/java/com/discordsrv/sponge/SpongeDiscordSRV.java index a143a58d..2e579737 100644 --- a/sponge/src/main/java/com/discordsrv/sponge/SpongeDiscordSRV.java +++ b/sponge/src/main/java/com/discordsrv/sponge/SpongeDiscordSRV.java @@ -21,10 +21,12 @@ package com.discordsrv.sponge; import com.discordsrv.api.DiscordSRVApi; import com.discordsrv.common.ServerDiscordSRV; import com.discordsrv.common.command.game.handler.ICommandHandler; +import com.discordsrv.common.config.configurate.manager.MessagesConfigManager; import com.discordsrv.common.config.connection.ConnectionConfig; import com.discordsrv.common.config.main.MainConfig; import com.discordsrv.common.config.configurate.manager.ConnectionConfigManager; import com.discordsrv.common.config.configurate.manager.MainConfigManager; +import com.discordsrv.common.config.messages.MessagesConfig; import com.discordsrv.common.debug.data.OnlineMode; import com.discordsrv.common.plugin.PluginManager; import com.discordsrv.sponge.console.SpongeConsole; @@ -37,7 +39,7 @@ import org.spongepowered.api.event.Listener; import org.spongepowered.api.event.lifecycle.ProvideServiceEvent; import org.spongepowered.plugin.PluginContainer; -public class SpongeDiscordSRV extends ServerDiscordSRV { +public class SpongeDiscordSRV extends ServerDiscordSRV { private final SpongeScheduler scheduler; private final SpongeConsole console; @@ -105,6 +107,11 @@ public class SpongeDiscordSRV extends ServerDiscordSRV messagesConfigManager() { + return null; + } + @Override protected void enable() throws Throwable { // Service provider diff --git a/velocity/src/main/java/com/discordsrv/velocity/VelocityDiscordSRV.java b/velocity/src/main/java/com/discordsrv/velocity/VelocityDiscordSRV.java index c1f8c46f..957b2bfa 100644 --- a/velocity/src/main/java/com/discordsrv/velocity/VelocityDiscordSRV.java +++ b/velocity/src/main/java/com/discordsrv/velocity/VelocityDiscordSRV.java @@ -20,10 +20,12 @@ package com.discordsrv.velocity; import com.discordsrv.common.ProxyDiscordSRV; import com.discordsrv.common.command.game.handler.ICommandHandler; +import com.discordsrv.common.config.configurate.manager.MessagesConfigManager; import com.discordsrv.common.config.connection.ConnectionConfig; import com.discordsrv.common.config.main.MainConfig; import com.discordsrv.common.config.configurate.manager.ConnectionConfigManager; import com.discordsrv.common.config.configurate.manager.MainConfigManager; +import com.discordsrv.common.config.messages.MessagesConfig; import com.discordsrv.common.debug.data.OnlineMode; import com.discordsrv.common.plugin.PluginManager; import com.discordsrv.common.scheduler.StandardScheduler; @@ -39,7 +41,7 @@ import java.net.URL; import java.net.URLClassLoader; import java.util.jar.JarFile; -public class VelocityDiscordSRV extends ProxyDiscordSRV { +public class VelocityDiscordSRV extends ProxyDiscordSRV { private final StandardScheduler scheduler; private final VelocityConsole console; @@ -121,6 +123,11 @@ public class VelocityDiscordSRV extends ProxyDiscordSRV messagesConfigManager() { + return null; + } + @Override protected void enable() throws Throwable { super.enable();