I got one application that can switch language between English and Germany. When in Germany language i want the currency display will auto convert into German format. Therefore in my program i have to do checking for the locale then convert the currency based on the language selected. I choose to use locale.setDefault() but i not sure whether this will has any risk or not based on below statement which i found. Can somebody advise for this?
Statement:
"Since changing the default locale may affect many different areas of functionality, this method should only be used if the caller is prepared to reinitialize locale-sensitive code running within the same Java Virtual Machine."
Thanks.
That warning means that if you've already had code that initialized based on a different locale, then it won't magically hear about the locale change and update. For example, if you already set up your title bar and menus and button labels in English and then call setDefault(Locale.GERMANY), all of the text will still be in English. Your example sounds like you won't be changing the locale after startup, so just make sure that you call setDefault early, before you do anything that depends on the locale.
Related
I am looking for a way to print time-related strings like "Today" and "Yesterday" translated to the user's Locale (i.e language) in an Android app.
I have tried to use DateUtils.getRelativeDateTimeString but it
does not consider the locale, or at least it is not possible to change it during runtime. I would need something similar to this existing constructor of SimpleDateFormat:
public SimpleDateFormat(String pattern, Locale locale)
Of course, it would be possible to add translations of each word in every language but isn't there a better way assuming the words actually exists in the OS.
Is there a way to achieve this?
Edit:
I am trying to do something similar to the date picker on iOS:
With #Meno Hochschild' comment I was able to solve it by:
Adding the Time4A library.
Made a local copy of UnitPatterns.java and made it public.
Used it like this:
UnitPatterns.of(locale).getTodayWord(); // returns "today"
UnitPatterns.of(locale).getYesterdayWord(); // returns "yesterday"
This appears to be a translation problem,
not a date-format problem.
Your app will have messages that it wants to display to the user.
These messages will need to be translated into your target languages.
Once you know the message you want to display,
retrieve then display the localized (i.e. translated) message using the locale (Android supports that).
It is likely that you do you actually want to display the word "tomorrow" or "yesterday".
Instead,
you probably want to display something like "blah blah tomorrow" or
"sorry blah blah yesterday".
Translate the entire message,
not just the words individually.
Additional Info
I think you do need to translate "Today" into every target language.
And, you need to translate each of the date related strings into every target language (by which I mean "Tue May 1" needs to be translated into every language).
There are "tricks" you can use.
Choose the "base" part of the string and use placeholders for the other parts.
Placeholders,
because different languages may have different orders for
"Day-of-week Month Day"
I'm developing a project where I need to automatically determinate which is the user language used to created the content.
We're actually using Locale.getDefault().getLanguage() but this can not be the right choice because, for istance, I live in Italy, I write content in Italian but my default Locale on my phone is en_US.
So I tought that maybe I could determinate it from the SIM Country (and fallback to user Locale when the device does not have one) but there's no one-to-one relation from a Country to a Language. For istance, US has en_US and es_US.
Do you have any suggestion? Should I ask the user for their current content's Locale?
What's the reason you need the user language?
I too have my locale set to en_US, and I have that because I prefer to have menus etc in English. (The translation of menus and settings etc feels strained in my native language.)
Chances are that your users will be annoyed (I know I would) if you use anything other than Locale.getDefault().getLanguage() for whatever you're using the language for.
That being said, if you really want to use a local language, I suggest you figure out the country code by some heuristics based on
Default locale
SIM country
Current network country
and use a hard coded lookup table from country code to (one of) the official language code(s). There are open databases with this information, see for example these resources:
List of language codes by country
Country codes / language codes on the OpenStreetMap wiki
I have a Java Desktop App, the users of the application have the availability to set the aplications language.
By now i manage it in the database, i call the value of a field called - userLanguage - which is an Integer, and when the user has logged in depending on this value i set the corresponding text to each element on the app by using a switch ( case 1: set labels text ENGLISH, case 2: set labels text SPANISH ... etc)
But i've heard that control the language from the database is an insult, and i would like to know which's a nice way to do it, or what's the best way to do so, it doesn't matter how difficult it would be but the efficence of the method to internationallize an app is what metters for me.
I would actually handle this problem using the Java Preferences. It keeps the preferences for each user separately in a system independent way (for you at least). If you use XML you need to create a SAX/DOM parser or if you use a DB you need to use jdbc. Neither XML or the DB is a bad or a tough solution, I just think the preferences are the easiest.
For internationalization, I would use a ResourceBundle that localized for different Locales. It is a pretty big topic see The Java internationalization (I18n) tutorial
Java Preferences is what you are looking for then.
Or, instead of using XML file you can use Properties.
...i've heard that control the language from the database is an insult...
I do not agree with that. I think it is scenario dependent, and in your case I think you should keep it the way it is to avoid unnecessary work, unless there is an absolute need for keeping the preferred idiom outside your DB.
You've received two answers, both of which are plainly wrong. If you have Java Desktop Application, you should this code:
Locale locale = Locale.getDefault(Locale.Category.DISPLAY);
This will give you valid User Interface language for your application - the one user set in his OS preferences. If you want to keep the language in a database or in some kind of preferences, you'll be forcing users to chose language. What for? I've already set what language I want. If you don't have it, let Java fall back to your application's default.
In case you wonder, if you use ResourceBundle, the default would be the one without a Locale in its name. That is unless you override this process by using custom ResourceBundle.Control.
I currently have a JSF application which sets the locale based on a user's choice of language. He gets a dropdown, and when choosing English, I set the locale to en, etc.
This works very nice with number formats as well as with the language strings loaded from my ResourceBundle.
So for en, I get English words and a . as decimal seperator.
For fr, I get French and a , as decimal seperator.
However, there is now a requirement that for this website, the number format must always have a , as decimal seperator. So, I was thinking to keep the locale fixed to fr.
Still the user must be able to change his language.
So, is it possible in JSF to load a different language without changing the locale?
Seams you need a special solution for formatting, so overwriting the formatters might be the better solution. I think JSF supports replacing the default number format.
Just explicitly specify the locale attribute of the <f:convertNumber> tags which you're using there.
E.g.
<f:convertNumber ... locale="fr" />
or something like
<f:convertNumber ... locale="#{app.defaultNumberLocale}" />
It would otherwise indeed default to UIViewRoot#getLocale(), as you're experiencing.
See also:
<f:convertNumber> tag documentation - read the locale attribute
I've been given the (rather daunting) task of introducing i18n to a J2EE web application using the 2.3 servlet specification. The application is very large and has been in active development for over 8 years.
As such, I want to get things right the first time so I can limit the amount of time I need to scrawl through JSPs, JavaScript files, servlets and wherever else, replacing hard-coded strings with values from message bundles.
There is no framework being used here. How can I approach supporting i18n. Note that I want to have a single JSP per view that loads text from (a) properties file(s) and not a different JSP for each supported locale.
I guess my main question is whether I can set the locale somewhere in the 'backend' (i.e. read locale from user profile on login and store value in session) and then expect that the JSP pages will be able to correctly load the specified string from the correct properties file (i.e. from messages_fr.properties when the locale is to French) as opposed to adding logic to find the correct locale in each JSP.
Any ideas how I can approach this?
There are a lot of things that need to be taken care of while internationalizing application:
Locale detection
The very first thing you need to think about is to detect end-user's Locale. Depending on what you want to support it might be easy or a bit complicated.
As you surely know, web browsers tend to send end-user's preferred language via HTTP Accept-Language header. Accessing this information in the Servlet might be as simple as calling request.getLocale(). If you are not planning to support any fancy Locale Detection workflow, you might just stick to this method.
If you have User Profiles in your application, you might want to add Preferred Language and Preferred Formatting Locale to it. In such case you would need to switch Locale after user logs in.
You might want to support URL-based language switching (for example: http://deutsch.example.com/ or http://example.com?lang=de). You would need to set valid Locale based on URL information - this could be done in various ways (i.e. URL Filter).
You might want to support language switching (selecting it from drop-down menu, or something), however I would not recommend it (unless it is combined with point 3).
JSTL approach could be sufficient if you just want to support first method or if you are not planning to add any additional dependencies (like Spring Framework).
While we are at Spring Framework it has quite a few nice features that you can use both to detect Locale (like CookieLocaleResolver, AcceptHeaderLocaleResolver, SessionLocaleResolver and LocaleChangeInterceptor) and externalizing strings and formatting messages (see spring:message tab).
Spring Framework would allow you to quite easily implement all the scenarios above and that is why I prefer it.
String externalization
This is something that should be easy, right? Well, mostly it is - just use appropriate tag. The only problem you might face is when it comes to externalizing client-side (JavaScript) texts. There are several possible approaches, but let me mention these two:
Have each JSP written array of translated strings (with message tag) and simply access that array in client code. This is easier approach but less maintainable - you would need to actually write valid strings from valid pages (the ones that actually reference your client-side scripts). I have done that before and believe me, this is not something you want to do in large application (but it is probably the best solution for small one).
Another approach may sound hard in principle but it is actually way easier to handle in the future. The idea is to centralize strings on client side (move them to some common JavaScript file). After that you would need to implement your own Servlet that will return this script upon request - the contents should be translated. You won't be able to use JSTL here, you would need to get strings from Resource Bundles directly.
It is much easier to maintain, because you would have one, central point to add translatable strings.
Concatenations
I hate to say that, but concatenations are really painful from Localizability perspective. They are very common and most people don't realize it.
So what is concatenation then?
On the principle, each English sentence need to be translated to target language. The problem is, it happens many times that correctly translated message uses different word order than its English counterpart (so English "Security policy" is translated to Polish "Polityka bezpieczeństwa" - "policy" is "polityka" - the order is different).
OK, but how it is related to software?
In web application you could concatenate Strings like this:
String securityPolicy = "Security " + "policy";
or like this:
<p><span style="font-weight:bold">Security</span> policy</p>
Both would be problematic. In the first case you would need to use MessageFormat.format() method and externalize strings as (for example) "Security {0}" and "policy", in the latter you would externalize the contents of the whole paragraph (p tag), including span tag. I know that this is painful for translators but there is really no better way.
Sometimes you have to use dynamic content in your paragraph - JSTL fmt:format tag will help you here as well (it works lime MessageFormat on the backend side).
Layouts
In localized application, it often happens that translated strings are way longer than English ones. The result could look very ugly. Somehow, you would need to fix styles. There are again two approaches:
Fix issues as they happen by adjusting common styles (and pray that it won't break other languages). This is very painful to maintain.
Implement CSS Localization Mechanism. The mechanism I am talking about should serve default, language-independent CSS file and per-language overrides. The idea is to have override CSS file for each language, so that you can adjust layouts on-demand (just for one language). In order to do that, default CSS file, as well as JSP pages must not contain !important keyword next to any style definitions. If you really have to use it, move them to language-based en.css - this would allow other languages to modify them.
Culture specific issues
Avoid using graphics, colors and sounds that might be specific for western culture. If you really need it, please provide means of Localization. Avoid direction-sensitive graphics (as this would be a problem when you try to localize to say Arabic or Hebrew). Also, do not assume that whole world is using the same numbers (i.e. not true for Arabic).
Dates and time zones
Handling dates in times in Java is to say the least not easy. If you are not going to support anything else than Gregorian Calendar, you could stick to built-in Date and Calendar classes.
You can use JSTL fmt:timeZone, fmt:formatDate and fmt:parseDate to correctly set time zone, format and parse date in JSP.
I strongly suggest to use fmt:formatDate like this:
<fmt:formatDate value="${someController.somedate}"
timeZone="${someController.detectedTimeZone}"
dateStyle="default"
timeStyle="default" />
It is important to covert date and time to valid (end user's) time zone. Also it is quite important to convert it to easily understandable format - that is why I recommend default formatting style.
BTW. Time zone detection is not something easy, as web browsers are not so nice to send anything. Instead, you can either add preferred time zone field to User preferences (if you have one) or get current time zone offset from web browser via client side script (see Date object's methods)
Numbers and currencies
Numbers as well as currencies should be converted to local format. It is done in the similar way to formatting dates (parsing is also done similarly):
<fmt:formatNumber value="1.21" type="currency"/>
Compound messages
You already have been warned not to concatenate strings. Instead you would probably use MessgageFormat. However, I must state that you should minimize use of compound messages. That is just because target grammar rules are quite commonly different, so translators might need not only to re-order the sentence (this would be resolved by using placeholders and MessageFormat.format()), but translate the whole sentence in different way based on what will be substituted. Let me give you some examples:
// Multiple plural forms
English: 4 viruses found.
Polish: Znaleziono 4 wirusy. **OR** Znaleziono 5 wirusów.
// Conjugation
English: Program encountered incorrect character | Application encountered incorrect character.
Polish: Program napotkał nieznaną literę | Aplikacja napotkała nieznaną literę.
Character encoding
If you are planning to Localize into languages that does not support ISO 8859-1 code page, you would need to support Unicode - the best way is to set page encoding to UTF-8. I have seen people doing it like this:
<%# page contentType="text/html; charset=UTF-8" %>
I must warn you: this is not enough. You actually need this declaration:
<%#page pageEncoding="UTF-8" %>
Also, you would still need to declare encoding in the page header, just to be on the safe side:
<META http-equiv="Content-Type" content="text/html;charset=UTF-8">
The list I gave you is not exhaustive but this is good starting point. Good luck :)
You can do exactly this using JSTL standard tag library with the tag. Grab a copy of the JSTL specification, read the i8N chapters, which discuss general text + date, time, currency. Very clearly written and shows you how you can do it all with tags. You can also set things like Locale programmatically
You dont(and shouldnt) need to have a separate JSP file per locale. The hard task is to figure out the keys that arent i18n-ed and move them to a file per locale, say, messages_en.properties, messages_fr.properties and so on.
Locale calculation can happen in multiple places depending on your logic. We support user locales stored in a database as well as the browser locale. Every request that comes into your application will have a "Accept-Language" header that indicates what are the languages your browser has been configured with , with preferences, i.e. Japanese first and then English. If thats the case, the application should read the messages_ja.properties and for keys that are not in that file, fallback to messages_en.properties. The same can hold true for user locales that are stored inside the database. Please note that the standard is just to switch the language in the browser and expect the content to be i18n-ed. (We initially started with storing locale in the database and then moved to support locales from the browser). Also you will need a default anyway as translators miss copying keys and values from english (main language file) to other languages, so you will need to default to english for values that are not in other files.
Ive also found mygengo very useful when giving translation job to other people who know a particular language, its saved us a lot of time.