簡體   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