Java - 用于存储和获取翻译的数据结构(作为对象属性)

Java - data structure for storing and getting translations (as object properties)

我想在 class 中保存翻译值。因为它太方便了,Java 的 Locale 实现似乎是映射的正确键。问题是:如果我只使用 HashMap<Locale, String> translations = ...; 进行翻译,当特定语言环境不可用时,我的代码将无法回退。

如何实现用于存储对象翻译的良好数据结构?

请注意,这些翻译不是程序元素的翻译,就像用户界面一样,假设 class 是字典条目,因此每个 class 都有自己不同的翻译数量每一次。

这是 HashMap 问题的示例:

import java.util.HashMap;
import java.util.Locale;

public class Example
{
    private final HashMap<Locale, String> translationsMap = new HashMap<>();

    /*
     * +------------------------+-------------------+-------------------+
     * |         Input          |  Expected output  |   Actual output   |
     * +------------------------+-------------------+-------------------+
     * | new Locale("en")       | "enTranslation"   | "enTranslation"   |
     * | new Locale("en", "CA") | "enTranslation"   | null              | <-- Did not fall back
     * | new Locale("de")       | "deTranslation"   | "deTranslation"   |
     * | new Locale("de", "DE") | "deTranslation"   | null              | <-- Did not fall back
     * | new Locale("de", "AT") | "deATTranslation" | "deATTranslation" |
     * | new Locale("fr")       | "frTranslation"   | "frTranslation"   |
     * | new Locale("fr", "CA") | "frTranslation"   | null              | <-- Did not fall back
     * +------------------------+-------------------+-------------------+
     */
    public String getTranslation(Locale locale)
    {
        return translationsMap.get(locale);
    }

    public void addTranslation(Locale locale, String translation)
    {
        translationsMap.put(locale, translation);
    }

    // dynamic class initializer
    {
        addTranslation(new Locale("en"), "enTranslation");
        addTranslation(new Locale("de"), "deTranslation");
        addTranslation(new Locale("fr"), "frTranslation");
        addTranslation(new Locale("de", "AT"), "deATTranslation");
    }
}

让您的 类 扩展 ListResourceBundle。

看这里:https://docs.oracle.com/javase/tutorial/i18n/resbundle/list.html

这有点老套,但确实有效。使用 ResourceBundle.Control,可以使用标准实现进行回退。

private Map<Locale, String> translations = new HashMap<>();

/** static: this instance is not modified or bound, it can be reused for multiple instances */
private static final ResourceBundle.Control CONTROL = ResourceBundle.Control.getControl(ResourceBundle.Control.FORMAT_PROPERTIES);

@Nullable
public String getTranslation(@NotNull Locale locale)
{
    List<Locale> localeCandidates = CONTROL.getCandidateLocales("_dummy_", locale); // Sun's implementation discards the string argument
    for (Locale currentCandidate : localeCandidates)
    {
        String translation = translations.get(currentCandidate);
        if (translation != null)
            return translation;
    }
    return null;
}