【问题标题】:Missing functionality between Accept-Language header and ResourceBundleAccept-Language 标头和 ResourceBundle 之间缺少功能
【发布时间】: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资源包是slen,这会尝试找到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


    【解决方案1】:

    我会写一个拦截器,在那里你可以设置你想要的语言并将你想要的逻辑应用到一个 ThreadLocal 或传递它。

    即您检查可用语言并定义顺序或设置默认值。

    如果您使用 Spring,则可以手动设置 LocaleContextHolder 或使用 LocaleContextResolver 而不是编写自己的拦截器。

    【讨论】:

    • 在 Spring 中使用 ResourceBundleMessageSource 代替
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-04-20
    • 1970-01-01
    • 2018-01-22
    • 1970-01-01
    • 1970-01-01
    • 2014-01-01
    • 2012-03-10
    相关资源
    最近更新 更多