【发布时间】:2023-03-08 12:38:01
【问题描述】:
Google foo 让我失望了。我想知道是否有一种标准的“书本”方式将输入语言环境从 Accept-Language 标头转换为正确的 ResourceBundle。
ResourceBundle::getBundle() 方法接受单一语言环境,但 Accept-Language 可以有多个按索引加权的语言环境,例如:de;q=1.0, sl;q=0.9。
当前代码:
@Context
private HttpServletRequest request;
public String getString(String key) {
ResourceBundle i18n = ResourceBundle.getBundle("locale/strings", this.request.getLocale());
return i18n.getString(key);
}
问题在于getLocale() 返回首选语言环境,在本例中为de。如果available资源包是sl和en,这会尝试找到de然后回退到en,但是客户端实际期望的结果是sl!
我的问题基本上是,我是否必须实现一个自定义的后备代码来迭代HttpServletRequest.getLocales()(我不想重新发明轮子..),还是有更标准和更直接的方法来做到这一点?我也会满足于一些填补这一空白的第 3 方库。
到目前为止的自定义解决方案:
@RequestScoped
public class Localization {
@Context
private HttpServletRequest request;
private ResourceBundle i18n;
@PostConstruct
void postConstruct() {
//List of locales from Accept-Language header
List<Locale> locales = Collections.list(request.getLocales());
if (locales.isEmpty()) {
//Fall back to default locale
locales.add(request.getLocale());
}
for (Locale locale : locales) {
try {
i18n = ResourceBundle.getBundle("bundles/translations", locale);
if (!languageEquals(i18n.getLocale(), locale)) {
//Default fallback detected
//The resource bundle that was returned has different language than the one requested, continue
//Only language tag is checked, no support for detecting different regions in this sample
continue;
}
break;
}
catch (MissingResourceException ignore) {
}
}
}
private boolean languageEquals(Locale first, Locale second) {
return getISO2Language(first).equalsIgnoreCase(getISO2Language(second));
}
private String languageGetISO2(Locale locale) {
String[] localeStrings = (locale.getLanguage().split("[-_]+"));
return localeStrings[0];
}
public ResourceBundle i18n() {
return this.i18n;
}
}
【问题讨论】:
标签: java jakarta-ee jax-rs