繁体   English   中英

无法获得特定国家/地区的本地化响应

[英]Failed to get country specific Localized response

我有一个spring boot应用程序,我们正在尝试支持多种语言和国家/地区。

这些是我们现在计划支持的代码。 en,es,fr,en-gb,es-mx,zh,ja。

我正在努力获取一些字段以响应本地化。 当我在本地(eclipse)中运行应用程序并检查邮递员的响应时,我可以看到它正在拾取特定于国家/地区的文件并正确地给出响应,但是当我将更改推送到AWS服务器时它不是,它只是获取特定于语言的文件并忽略国家/地区代码。

例如,如果我将Accept-Language设置为da,es-MX; q = 0.8我期望es-MX中的响应(我们不支持da)但它只是在es中给出响应(我有es和es-MX文件)并忽略国家代码MX。

但是,如果我将Accept-Language作为fr,es-MX; q = 0.8,它将获取messages_fr.properties文件,并以法语给出响应,这是我所期望的。

以下是我的课程。

@Configuration
@ComponentScan("com.hsf")
@EnableWebMvc
public class ApplicationConfig extends WebMvcConfigurerAdapter {

    @Value("${spring.application.name}")
    String appName;

    @Bean
    public LocaleResolver localeResolver() {
        return new SmartLocaleResolver();
    }

    @Bean
    public DispatcherServlet dispatcherServlet() {
        final DispatcherServlet servlet = new DispatcherServlet();
        servlet.setDispatchOptionsRequest(true);
        return servlet;
    }

    @Bean
    public ReloadableResourceBundleMessageSource messageSource() {
        final ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
        messageSource.setBasename("classpath:i18n/messages");
        // If true, the key of the message will be displayed if the key is not
        // found, instead of throwing an exception
        messageSource.setUseCodeAsDefaultMessage(true);
        messageSource.setDefaultEncoding("UTF-8");
        // The value 0 means always reload the messages to be developer friendly
        messageSource.setCacheSeconds(10);
        return messageSource;
    }

}

此类解析Accept-Language标头并设置Locale。

public class SmartLocaleResolver extends AcceptHeaderLocaleResolver {

        @Override
        public Locale resolveLocale(HttpServletRequest request) {
            try {
                List<LanguageRange> list = Locale.LanguageRange.parse(request.getHeader("Accept-Language"));
                if (!list.isEmpty()) {
                    for (LanguageRange s : list) {
                        if (ApplicationConstants.LOCALE.contains(s.getRange())) {
                            return Locale.forLanguageTag(s.getRange());
                        }
                    }
                }
            } catch (IllegalArgumentException e) {
                throw e;
            }
            return request.getLocale();
        }
    }

我的ApplicationConstants类中有以下常量

public static final List<String> LOCALE              = Collections
            .unmodifiableList(Arrays.asList("en", "es", "fr", "es-mx", "zh", "ja"));

这是MessageHandler类

@Component
public class MessageHandler {
    @Autowired
    private MessageSource messageSource;

    public String localizeMessage(String errorCode, Object args[]) {
        Locale locale = LocaleContextHolder.getLocale();
        String message = messageSource.getMessage(errorCode, args, locale);
        return message;

    }

    public String localizeMessage(String errorCode) {
        return localizeMessage(errorCode, null);
    }

}

有什么想法吗?

看来你只是重新实现了Locale的lookup()方法:

    List<Locale> locales = Arrays.asList(new Locale("en"),
                                         new Locale("es"),
                                         new Locale("fr"),
                                         new Locale("es", "MX"),
                                         new Locale("zh"),
                                         new Locale("ja"));
    List<Locale.LanguageRange> ranges = Locale.LanguageRange.parse("da,es-MX;q=0.8");
    Locale best = Locale.lookup(ranges, locales);
    System.out.println("best = " + best); // prints best = es_MX

    ranges = Locale.LanguageRange.parse("fr,es-MX;q=0.8");
    best = Locale.lookup(ranges, locales);
    System.out.println("best = " + best); // prints best = fr

有几种方法可以实现正确的区域设置查找方法(顺便提一下,遵循i18n最佳实践)。
一种方法是在您尝试时“手动”解析标题。
但请注意, HttpServletRequest从其超类派生出一个奇特的方法,即ServletRequest#getLocales()
我的观点是,您将收到已经解析的优先级枚举区域设置。 顺便说一句,我肯定会使用HashSet来比较区域设置(出于性能原因)。

足够说话:

public class SmartLocaleResolver extends AcceptHeaderLocaleResolver {

    @Override
    public Locale resolveLocale(HttpServletRequest request) {
        List<Locale> locales = Collections.list(request.getLocales());
        return getBestMatchingOrDefault(locales);
    }

    private Locale getBestMatchingOrDefault(List<Locale> locales) {
        Optional<Locale> maybeLocale = locales.stream()
            .filter(locale -> ApplicationConstants.LOCALE.contains(locale))
            .findFirst();
        return maybeLocale.orElse(ApplicationConstants.DEFAULT_LOCALE);
    }
}

在这种情况下,需要修改ApplicationConstants类:

public static final Set<Locale> LOCALE = Collections.unmodifiableSet(
    new HashSet<Locale>(
        Arrays.asList(Locale.ENGLISH, 
                      Locale.forLanguageTag("es"), 
                      Locale.FRENCH, 
                      Locale.forLanguageTag("es-MX"), 
                      Locale.JAPANESE, 
                      Locale.forLanguageTag("zh-Hans"), 
                      Locale.PRC, 
                      Locale.CHINESE)));
public static final Locale DEFAULT_LOCALE = Locale.ENGLISH; // or something else?

关于中文的一个词。 有两种中文口味 - 简体中文(zh-Hans)和繁体中文(zh-Hant)。 最好不要混合它们。 我不确定将简体中文版本作为默认中文版本服务是否是个好主意。 好吧,也许是,但我怀疑。 我会特别使用zh-Hans和zh-CN(即使这意味着我会在CI构建期间复制同一个文件)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM