diff --git a/api/src/main/java/eu/darkbot/api/extensions/DescriptionBuilder.java b/api/src/main/java/eu/darkbot/api/extensions/DescriptionBuilder.java new file mode 100644 index 00000000..d37143a0 --- /dev/null +++ b/api/src/main/java/eu/darkbot/api/extensions/DescriptionBuilder.java @@ -0,0 +1,49 @@ +package eu.darkbot.api.extensions; + +import eu.darkbot.api.managers.I18nAPI; +import org.jetbrains.annotations.Nullable; + +public interface DescriptionBuilder { + + /** + * You can freely create descriptions for your tooltips or not by returning {@code null} + * Default implementation will return {@code "Missing " + key} string if no translation is found + * + * @param namespace your plugin namespace or null if it bot namespace + * @param key base translation key + * @param arguments passed arguments to the description + * @return description text which will be used in tooltips or null to do not create description tooltip + */ + @Nullable String getDescription(PluginInfo namespace, String key, Object... arguments); + + /** + * Retrieves the description for a given translation key, falling back to a default string if not found. + *

+ * This method allows for creating descriptions for tooltips with a fallback option. + * + * @param namespace your plugin namespace or {@code null} if using the bot namespace + * @param key the base translation key to look up the description + * @param fallback the fallback description to return if the key is not found + * @param arguments the arguments to be used in the description or fallback (if applicable) + * @return the description text to be used in tooltips if available, if not found, the fallback string will be returned + */ + @Nullable String getOrDefaultDescription(PluginInfo namespace, String key, String fallback, Object... arguments); + + class Default implements DescriptionBuilder { + private final I18nAPI i18n; + + public Default(I18nAPI i18n) { + this.i18n = i18n; + } + + @Override + public @Nullable String getDescription(PluginInfo namespace, String key, Object... arguments) { + return i18n.get(namespace, key + ".desc", arguments); + } + + @Override + public @Nullable String getOrDefaultDescription(PluginInfo namespace, String key, String fallback, Object... arguments) { + return i18n.getOrDefault(namespace, key + ".desc", fallback, arguments); + } + } +} diff --git a/api/src/main/java/eu/darkbot/api/extensions/PluginInfo.java b/api/src/main/java/eu/darkbot/api/extensions/PluginInfo.java index fb626f1e..4f65719d 100644 --- a/api/src/main/java/eu/darkbot/api/extensions/PluginInfo.java +++ b/api/src/main/java/eu/darkbot/api/extensions/PluginInfo.java @@ -1,6 +1,7 @@ package eu.darkbot.api.extensions; import eu.darkbot.api.utils.Version; +import org.jetbrains.annotations.Nullable; import java.net.URL; @@ -60,4 +61,8 @@ public interface PluginInfo extends IssueHandler { */ URL getDownloadURL(); + /** + * @return The {@link DescriptionBuilder} for this plugin + */ + @Nullable DescriptionBuilder getDescriptionBuilder(); } diff --git a/api/src/main/java/eu/darkbot/api/managers/I18nAPI.java b/api/src/main/java/eu/darkbot/api/managers/I18nAPI.java index 4bf2e088..c6a95a94 100644 --- a/api/src/main/java/eu/darkbot/api/managers/I18nAPI.java +++ b/api/src/main/java/eu/darkbot/api/managers/I18nAPI.java @@ -8,7 +8,7 @@ /** * Provides access to bot built-in translations, as well as plugin translations. - * + *

* Access to bot base translations is available in methods without a namespace parameter: *
* {@link #get(String)}, {@link #get(String, Object...)}, @@ -22,6 +22,7 @@ public interface I18nAPI extends API.Singleton { /** * Get the translation for a specific bot translation key + * * @param key translation key to search for * @return The translated text if available, a placeholder text otherwise */ @@ -31,8 +32,9 @@ default String get(@NotNull String key) { /** * Get the translation for a specific plugin translation key + * * @param namespace the plugin namespace to search - * @param key translation key to search for + * @param key translation key to search for * @return The translated text if available, a placeholder text otherwise */ default String get(@Nullable PluginInfo namespace, @NotNull String key) { @@ -41,7 +43,8 @@ default String get(@Nullable PluginInfo namespace, @NotNull String key) { /** * Get the translation for a specific bot translation key with arguments - * @param key translation key to search for + * + * @param key translation key to search for * @param arguments the arguments to put in the translated text * @return The translated text if available, a placeholder text otherwise */ @@ -51,8 +54,9 @@ default String get(@NotNull String key, @NotNull Object... arguments) { /** * Get the translation for a specific plugin translation key with arguments + * * @param namespace the plugin namespace to search - * @param key translation key to search for + * @param key translation key to search for * @param arguments the arguments to put in the translated text * @return The translated text if available, a placeholder text otherwise */ @@ -60,7 +64,8 @@ default String get(@NotNull String key, @NotNull Object... arguments) { /** * Get the translation for a specific bot translation key, or fallback to a default string - * @param key translation key to search for, if null, fallback string will be used + * + * @param key translation key to search for, if null, fallback string will be used * @param fallback fallback string, returned in case no translation was found * @return the translated message if available, fallback otherwise */ @@ -70,9 +75,10 @@ default String getOrDefault(@Nullable String key, @Nullable String fallback) { /** * Get the translation for a specific plugin translation key, or fallback to a default string + * * @param namespace the plugin namespace to search - * @param key translation key to search for, if null, fallback string will be used - * @param fallback fallback string, used as translation text and filled with arguments if no text is found + * @param key translation key to search for, if null, fallback string will be used + * @param fallback fallback string, used as translation text and filled with arguments if no text is found * @return the translated message if available, fallback otherwise */ default String getOrDefault(@Nullable PluginInfo namespace, @Nullable String key, @Nullable String fallback) { @@ -81,8 +87,9 @@ default String getOrDefault(@Nullable PluginInfo namespace, @Nullable String key /** * Get the translation for a specific bot translation key, or fallback to a default string - * @param key translation key to search for, if null, fallback string will be used - * @param fallback fallback string, used as translation text and filled with arguments if no text is found + * + * @param key translation key to search for, if null, fallback string will be used + * @param fallback fallback string, used as translation text and filled with arguments if no text is found * @param arguments the arguments to put in the translated text (or in fallback if no translation is found) * @return the translated message if available, fallback otherwise */ @@ -92,12 +99,101 @@ default String getOrDefault(@Nullable String key, @Nullable String fallback, @No /** * Get the translation for a specific bot translation key, or fallback to a default string + * * @param namespace the plugin namespace to search - * @param key translation key to search for, if null, fallback string will be used - * @param fallback fallback string, used as translation text and filled with arguments if no text is found + * @param key translation key to search for, if null, fallback string will be used + * @param fallback fallback string, used as translation text and filled with arguments if no text is found * @param arguments the arguments to put in the translated text (or in fallback if no translation is found) * @return the translated message if available, fallback otherwise */ String getOrDefault(@Nullable PluginInfo namespace, @Nullable String key, @Nullable String fallback, @NotNull Object... arguments); + /** + * Get the description for a specific bot description key + * + * @param key description key to search for + * @return The description text if available, a placeholder text otherwise + */ + default String getDescription(@NotNull String key) { + return getDescription(key, ArrayUtils.EMPTY_OBJECT_ARRAY); + } + + /** + * Get the description for a specific plugin description key + * + * @param namespace the plugin namespace to search + * @param key description key to search for + * @return The description text if available, a placeholder text otherwise + */ + default String getDescription(@Nullable PluginInfo namespace, @NotNull String key) { + return getDescription(namespace, key, ArrayUtils.EMPTY_OBJECT_ARRAY); + } + + /** + * Get the description for a specific bot description key with arguments + * + * @param key description key to search for + * @param arguments the arguments to put in the description text + * @return The description text if available, a placeholder text otherwise + */ + default String getDescription(@NotNull String key, @NotNull Object... arguments) { + return getDescription(null, key, arguments); + } + + /** + * Get the description for a specific plugin description key with arguments + * + * @param namespace the plugin namespace to search + * @param key description key to search for + * @param arguments the arguments to put in the description text + * @return The description text if available, a placeholder text otherwise + */ + String getDescription(@Nullable PluginInfo namespace, @NotNull String key, @NotNull Object... arguments); + + + /** + * Get the description for a specific bot description key, or fallback to a default string + * + * @param key description key to search for, if null, fallback string will be used + * @param fallback fallback string, returned in case no description was found + * @return the description if available, fallback otherwise + */ + default String getOrDefaultDescription(@Nullable String key, @Nullable String fallback) { + return getOrDefaultDescription(key, fallback, ArrayUtils.EMPTY_OBJECT_ARRAY); + } + + /** + * Get the description for a specific plugin description key, or fallback to a default string + * + * @param namespace the plugin namespace to search + * @param key description key to search for, if null, fallback string will be used + * @param fallback fallback string, used as description text and filled with arguments if no text is found + * @return the description if available, fallback otherwise + */ + default String getOrDefaultDescription(@Nullable PluginInfo namespace, @Nullable String key, @Nullable String fallback) { + return getOrDefaultDescription(namespace, key, fallback, ArrayUtils.EMPTY_OBJECT_ARRAY); + } + + /** + * Get the description for a specific bot description key, or fallback to a default string + * + * @param key description key to search for, if null, fallback string will be used + * @param fallback fallback string, used as description text and filled with arguments if no text is found + * @param arguments the arguments to put in the description (or in fallback if no description is found) + * @return the description if available, fallback otherwise + */ + default String getOrDefaultDescription(@Nullable String key, @Nullable String fallback, @NotNull Object... arguments) { + return getOrDefaultDescription(null, key, fallback, arguments); + } + + /** + * Get the description for a specific plugin description key, or fallback to a default string + * + * @param namespace the plugin namespace to search + * @param key description key to search for, if null, fallback string will be used + * @param fallback fallback string, used as description text and filled with arguments if no text is found + * @param arguments the arguments to put in the description (or in fallback if no description is found) + * @return the description if available, fallback otherwise + */ + String getOrDefaultDescription(@Nullable PluginInfo namespace, @Nullable String key, @Nullable String fallback, @NotNull Object... arguments); } diff --git a/impl/src/main/java/eu/darkbot/impl/managers/I18n.java b/impl/src/main/java/eu/darkbot/impl/managers/I18n.java index 58abe770..e57ba1f5 100644 --- a/impl/src/main/java/eu/darkbot/impl/managers/I18n.java +++ b/impl/src/main/java/eu/darkbot/impl/managers/I18n.java @@ -3,11 +3,14 @@ import eu.darkbot.api.PluginAPI; import eu.darkbot.api.events.EventHandler; import eu.darkbot.api.events.Listener; +import eu.darkbot.api.extensions.DescriptionBuilder; import eu.darkbot.api.extensions.PluginInfo; import eu.darkbot.api.managers.ExtensionsAPI; import eu.darkbot.api.managers.I18nAPI; +import lombok.Getter; import lombok.NonNull; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.io.IOException; import java.io.InputStream; @@ -31,7 +34,9 @@ public class I18n implements I18nAPI, Listener { private final Map pluginProps = new HashMap<>(); private final Map formatCache = new HashMap<>(); - private Locale locale; + private final DescriptionBuilder defaultBuilder = new DescriptionBuilder.Default(this); + + @Getter private Locale locale; public I18n(PluginAPI pluginAPI) { // Due to I18n being such an integral part, we cannot afford a direct dependency here. @@ -47,10 +52,6 @@ public void setLocale(Locale locale) { formatCache.clear(); } - public Locale getLocale() { - return locale; - } - public void reloadResources() { props.loadResources(locale, "", getClass().getClassLoader()); pluginProps.forEach((pi, pc) -> @@ -98,6 +99,12 @@ private String getOrDefaultInternal(PluginInfo namespace, String key, String fal return res == null ? fallback : res; } + private DescriptionBuilder getDescriptionBuilder(@Nullable PluginInfo namespace) { + if (namespace == null) return defaultBuilder; + DescriptionBuilder descriptionBuilder = namespace.getDescriptionBuilder(); + return descriptionBuilder == null ? defaultBuilder : descriptionBuilder; + } + @Override public String get(PluginInfo namespace, @NotNull String key, Object... arguments) { return format(getInternal(namespace, key), arguments); @@ -109,6 +116,16 @@ public String getOrDefault(PluginInfo namespace, String key, String fallback, Ob return format(text, arguments); } + @Override + public String getDescription(@Nullable PluginInfo namespace, @NotNull String key, @NotNull Object... arguments) { + return getDescriptionBuilder(namespace).getDescription(namespace, key, arguments); + } + + @Override + public String getOrDefaultDescription(@Nullable PluginInfo namespace, @Nullable String key, @Nullable String fallback, @NotNull Object... arguments) { + return getDescriptionBuilder(namespace).getOrDefaultDescription(namespace, key, fallback, arguments); + } + private static class PropertyContainer { private final Properties fallback; private final Properties props;