Detecting browser locales/languages and generating output
We have a Java app that renders Localized text on user’s browser session based upon browser language settings. The app reads the browser language settings [set within the header that comes as in request to app] and prepares the localized text. But recently we faced issues for Mozilla 5.0 version browser. Note our code works fine in IE. Taking an example for 'ja' language we are expecting browser to send accepted language as 'ja-JP' [which IE does] - but unfortunately Mozilla (FF) d开发者_运维问答oes not - it only sends browser accepted language as 'ja'. So we land up in generating content using default language.
Since we are providing a fix for same - basically something like map [language code to language-Country code] like - 'ja' to 'ja-JP' and then create a new locale [only if 2 digits language code is present after in request] - my question is for other browsers like Chrome Safari etc What are the language formats send within headers? So having a array say like this ja-JP = ja-JP ja = ja-JP and mapping the browser language to language-country code would help to resolve the issue. But is there any specific constraint that we need to address – say are there languages that are spoken in multiple locations - if so then how would we deal with it? Any other thing that we need to pay attention to? Thanks in advance.Look at the java.util.ResourceBundle
class, mainly the getBundle()
method. (You can use this, or implement a similar mechanism by yourself.)
In principle, you have a hierarchy of locales, and whenever a locale is not specially supported, you fall back to the parent locale. In your case, "ja_JP"
(in Java notation) has the parent locale "ja"
, which in turn has the parent locale ""
.
As most Japanese pages are not specific to Japan, you would normally have all the Japanese translation done for ja
, and only when something special only would be valid for japanese users in Japan, then additionally have ja_JP
. Then you also have no problem if some user sends jp_US
since he is using Japanese in the USA.
If you wanted to use the Java ResourceBundle mechanism only for indicating for which locales we have data, you could create (for example) these (empty) files:
- MyLocale.properties - corresponds to "" Locale
- MyLocale_de.properties - corresponds to "de" Locale (german)
- MyLocale_en.properties - corresponds to "en" Locale (english)
- MyLocale_ja.properties - corresponds to "ja" Locale (japanese)
Then in your program you would write
Locale rLocale = request.getLocale();
ResourceBundle bundle = ResourceBundle.getBundle("MyLocale", rLocale);
Locale selectedLocale = bundle.getLocale();
Now selectedLocale is certainly one of "", "de", "en", "jp", no matter what locale rLocale was. For example, for "en", "en_GB", "en_US" in all cases "en" would be selected, "ja" and "ja_JP" would both result in "ja", while "de_DE" and "de_AT" would both result in "de", and "it_IT", "eo" and most other Locales would result in "".
The "right Java way" to do this: You would not ask your bundle about its Locale, but simply use the bundle as a ResourceBundle, taking the localized resources from it. So, when you need some text, you do
String text = bundle.getText("greeting.hello");
and then output the text. Sometimes you would use a MessageFormat to format text with values inserted (or a Formatter). (Then your property files would not be empty, of course, but contain lines like these:
greeting.hello = Hello World!
(in the english file)
greeting.hello = Hallo Welt!
(in the german file)
Note that often the Browser sends not only one Locale code, but a list of preferred ones. So you in fact should do this "bundle-search" for each of these codes and take the first one which does return something else than "", and fall back to "" only when no requested language matches. (For example, my browser sends "eo", "de_DE", "de", "en". Since most Websites don't support Esperanto, they fall back to german (if available and the selection is implemented correctly), or to the default language (if they look only at the first entry)).
http://www.tutorialspoint.com/jsp/jsp_internationalization.htm
and more info about a request: http://www.apl.jhu.edu/~hall/java/Servlet-Tutorial/Servlet-Tutorial-Request-Headers.html
package hall;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
/** Shows all the request headers sent on this
* particular request.
* <P>
* Part of tutorial on servlets and JSP that appears at
* http://www.apl.jhu.edu/~hall/java/Servlet-Tutorial/
* 1999 Marty Hall; may be freely used or adapted.
*/
public class ShowRequestHeaders extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
String title = "Servlet Example: Showing Request Headers";
out.println(ServletUtilities.headWithTitle(title) +
"<BODY BGCOLOR=\"#FDF5E6\">\n" +
"<H1 ALIGN=CENTER>" + title + "</H1>\n" +
"<B>Request Method: </B>" +
request.getMethod() + "<BR>\n" +
"<B>Request URI: </B>" +
request.getRequestURI() + "<BR>\n" +
"<B>Request Protocol: </B>" +
request.getProtocol() + "<BR><BR>\n" +
"<TABLE BORDER=1 ALIGN=CENTER>\n" +
"<TR BGCOLOR=\"#FFAD00\">\n" +
"<TH>Header Name<TH>Header Value");
Enumeration headerNames = request.getHeaderNames();
while(headerNames.hasMoreElements()) {
String headerName = (String)headerNames.nextElement();
out.println("<TR><TD>" + headerName);
out.println(" <TD>" + request.getHeader(headerName));
}
out.println("</TABLE>\n</BODY></HTML>");
}
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
You can get the list of locales from java class - Locale. By calling the method, getAvailableLocale().
http://docs.oracle.com/javase/8/docs/api/java/util/Locale.html#getAvailableLocales--
精彩评论