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;
}
我想在 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;
}