diff --git a/pom.xml b/pom.xml
index 5f7b096..6e0c8f3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -119,7 +119,13 @@
adventure-text-minimessage
4.16.0
-
+
+
+ net.kyori
+ adventure-text-serializer-ansi
+ 4.16.0
+
+
net.kyori
adventure-text-logger-slf4j
diff --git a/src/main/java/me/xginko/villageroptimizer/logging/ComponentLoggerProviderImpl.java b/src/main/java/me/xginko/villageroptimizer/logging/ComponentLoggerProviderImpl.java
new file mode 100644
index 0000000..5652c78
--- /dev/null
+++ b/src/main/java/me/xginko/villageroptimizer/logging/ComponentLoggerProviderImpl.java
@@ -0,0 +1,23 @@
+package me.xginko.villageroptimizer.logging;
+
+import net.kyori.adventure.text.logger.slf4j.ComponentLogger;
+import net.kyori.adventure.text.logger.slf4j.ComponentLoggerProvider;
+import net.kyori.adventure.text.serializer.ansi.ANSIComponentSerializer;
+import org.jetbrains.annotations.NotNull;
+import org.slf4j.LoggerFactory;
+
+@SuppressWarnings("UnstableApiUsage")
+public final class ComponentLoggerProviderImpl implements ComponentLoggerProvider {
+ private static final ANSIComponentSerializer SERIALIZER = ANSIComponentSerializer.builder()
+ .flattener(TranslatableMapper.FLATTENER)
+ .build();
+
+ @Override
+ public @NotNull ComponentLogger logger(
+ final @NotNull LoggerHelper helper,
+ final @NotNull String name
+ ) {
+ return helper.delegating(LoggerFactory.getLogger(name), SERIALIZER::serialize);
+ }
+}
+
diff --git a/src/main/java/me/xginko/villageroptimizer/logging/TranslatableMapper.java b/src/main/java/me/xginko/villageroptimizer/logging/TranslatableMapper.java
new file mode 100644
index 0000000..2517e7b
--- /dev/null
+++ b/src/main/java/me/xginko/villageroptimizer/logging/TranslatableMapper.java
@@ -0,0 +1,44 @@
+package me.xginko.villageroptimizer.logging;
+
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.TranslatableComponent;
+import net.kyori.adventure.text.flattener.ComponentFlattener;
+import net.kyori.adventure.translation.GlobalTranslator;
+import net.kyori.adventure.translation.TranslationRegistry;
+import net.kyori.adventure.translation.Translator;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Locale;
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+
+public enum TranslatableMapper implements BiConsumer> {
+ INSTANCE;
+
+ public static final ComponentFlattener FLATTENER = ComponentFlattener.basic().toBuilder()
+ .complexMapper(TranslatableComponent.class, TranslatableMapper.INSTANCE)
+ .build();
+
+ @Override
+ public void accept(
+ final TranslatableComponent translatableComponent,
+ final Consumer componentConsumer
+ ) {
+ for (final Translator source : GlobalTranslator.translator().sources()) {
+ if (source instanceof TranslationRegistry && ((TranslationRegistry) source).contains(translatableComponent.key())) {
+ componentConsumer.accept(GlobalTranslator.render(translatableComponent, Locale.getDefault()));
+ return;
+ }
+ }
+ final @Nullable String fallback = translatableComponent.fallback();
+ if (fallback == null) {
+ return;
+ }
+ for (final Translator source : GlobalTranslator.translator().sources()) {
+ if (source instanceof TranslationRegistry && ((TranslationRegistry) source).contains(fallback)) {
+ componentConsumer.accept(GlobalTranslator.render(Component.translatable(fallback), Locale.getDefault()));
+ return;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/META-INF/services/me.xginko.villageroptimizer.logging.ComponentLoggerProviderImpl b/src/main/resources/META-INF/services/me.xginko.villageroptimizer.logging.ComponentLoggerProviderImpl
new file mode 100644
index 0000000..7673648
--- /dev/null
+++ b/src/main/resources/META-INF/services/me.xginko.villageroptimizer.logging.ComponentLoggerProviderImpl
@@ -0,0 +1 @@
+me.xginko.villageroptimizer.logging.ComponentLoggerProviderImpl
\ No newline at end of file