Skip to content

Creating a Custom Storage

Leo edited this page Dec 1, 2023 · 4 revisions

A Translations instance can hold two types of storages: a MessageStorage and a StyleStorage. The storages define where to load locales and styles from and where to store them. By default, YML and properties files are supported. It is possible though to implement SQL properties or CrowdIn support. Maybe this comes with future updates :)

Message Storage

To provide a custom MessageStorage, first, implement the following interface.

public interface MessageStorage {
    /**
     * Reads and returns a whole message storage.
     * The operation does not affect the dictionary of any message instance.
     *
     * @param locale The locale to load all translations for.
     * @return a map of all values that were present in this storage. The map key is a {@link Message} instance that
     * is not yet part of any translations instance and must be assigned to be translatable.
     */
    Map<Message, String> readMessages(Locale locale);

    /**
     * Writes a collection of {@link Message} instances into the storage. If the storage already contains
     * a translation for a namespaced key, the value will not be affected.
     * The value to write will be provided by the dictionary of the message and the given {@link Locale}.
     *
     * @param messages A collection of messages to write.
     * @param locale A locale to write the message translations for.
     * @return A collection of Messages that were successfully written into storage.
     */
    Collection<Message> writeMessages(Collection<Message> messages, Locale locale);
}

Then apply an instance to a Translations:

translations.setMessageStorage(new MyCustomMessageStorage());

Voilà, translations.loadLocales() and translations.saveLocale(...) now use your custom storage.

Style Storage

StyleStorages work similar to MessageStorages. The only difference is the use of the newly introduced Type MessageStyle

/**
 * Stores {@link Style}s in a Map format, where the key represents a MiniMessage tag and the value the according style
 * that the tag will render.
 */
public interface StyleStorage {

    /**
     * Writes a map of styles into the storage.
     * Values that are already part of the storage must not be removed or modified.
     * Only non-existing values of the input map will therefore be added to this storage.
     *
     * @param styles A map of styles with their tag as key.
     */
    void writeStyles(Map<String, MessageStyle> styles);

    /**
     * Loads a map of styles with their MiniMessage tag as key.
     * @return The loaded map.
     */
    Map<String, MessageStyle> loadStyles();
}

A MessageStyle is a wrapper for a styles key, TagResolver and String representation. The key serves as MiniMessage tag, the TagResolver specifies the way the style is being applied and the String representation is the styles serialized version. Only MessageStyles with a String representation can be stored into a StyleStorage. If plugin developers register styles without string representation, they will not be serialized.

To turn style strings into MessageStyle objects, you might want to use the StyleDeserializerImpl implementation of StyleDeserializer.