Skip to content

Flexible locale resolution based on supported languages [SPR-13330] #17915

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
spring-projects-issues opened this issue Aug 7, 2015 · 5 comments
Assignees
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) type: enhancement A general enhancement
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

spring-projects-issues commented Aug 7, 2015

Yi EungJun opened SPR-13330 and commented

When an HTTP client prefers a specific language, the server can return a message in the language as follows:

@Autowired
private MessageSource messageSource;

public String say (Locale locale) {
    return messageSource.getMessage("my.message", null, locale);
}

But Here is a difficult case. If a client requests with many acceptable languages by Accept-Language header:

Accept-Language: ko, ja;q=0.9, en;q=0.8; *;q=0.1

and the server supports many languages, the server should find the best match. In this case, if the server supports 'ja' and 'en', the best match is 'ja'.

But it seems that Spring Framework does not provide a way to do that. It would be nice if it supports that as the following examples:

  1. getMessage() accepts a list of locales and choose the best one
@Autowired
private MessageSource messageSource;

public String say1 (Collection<Locale> locales) {
    return messageSource.getMessage("my.message", null, locales);
}
  1. MessageSource has a method to lookup the best locale as java.util.Locale does.
public String say2(Collection<Locale> locales) {
    Locale locale = messageSource.lookupBestLocale(locales);
    return messageSource.getMessage("my.message", null, locale);
}

Issue Links:

Referenced from: commits b3d67b9

@spring-projects-issues
Copy link
Collaborator Author

Rossen Stoyanchev commented

In the top example above, the Locale is resolved based on the configured LocaleResolver. By default this is the AcceptHeaderLocaleResolver which gets the locale via ServletRequest#getLocale. According to the Javadoc and the Servlet API the locale is "the preferred Locale that the client will accept content in, based on the Accept-Language header".

In short this should already be working. Have you tried and is there an issue?

@spring-projects-issues
Copy link
Collaborator Author

Yi EungJun commented

I already used AcceptHeaderLocaleResolver but it does not work as I want.

If a client requests with "Accept-Language: ko, ja;q=0.9" and my server has messages.properties (English) and messages_ko.properties, it works as I want.

But if a client requests with the same header and my server has messages.properties (English) and messages_ja.properties, but not messages_ko.properties, it does not work as I want. It returns an English message instead of a "ja" message which I want. AcceptHeaderLocalResolver.resolveLocale() returns "ko", which the user mostly prefers, but the server returns an English message, not a "ko" message, because it does not have messages_ko.properties. In such a case, the better way is response with "ja", the secondary preferred language.

So we need a way to resolve a best-match language. Both of AcceptHeaderLocaleResolver.resolveLocale() and ServletRequest.getLocale() considers only the client's Accept-Language header. But it is not enough. The better language-negotiation should consider also the server's language capability.

I guess this issue can be resolved by adding new implementation of LocaleResolver, which considers both of client's requirement and server's capability.

@spring-projects-issues
Copy link
Collaborator Author

Rossen Stoyanchev commented

Okay I see. It looks like ServletRequest also has getLocales which returns an enumeration with all locales in order of preference. We could extend the existing AcceptHeaderLocaleResolver to be configured with a list of locales that are available and then apply that against the list of requested locales.

I don't see any reliable way to automatically determine what locales are supported. ReloadableResourceBundleMessageSource is configured with basenames of resource bundles. It could try to find on start up what's available but each basename could have different locales. Also what's available may change at any time by additional files being added. The most viable path I see is a configuration property on AcceptHeaderLocaleResolver.

@spring-projects-issues
Copy link
Collaborator Author

Yi EungJun commented

Thanks for your effort! Feel free to let me know if there is anything I help you.

@spring-projects-issues
Copy link
Collaborator Author

Rossen Stoyanchev commented

There is a proposed fix for this now in master (4.3 snapshot). Please give that a try if you can.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

2 participants