Google

Jun 22, 2014

How to write internalized Java applications? What do you understand by the terms internationalization (i18n) and localization (l10n) relating to Java programming? What is a ResourceBundle?

Localization (aka i10n, where 10 is the number of letters between the letter ‘i’ and the letter ‘n’ in the word localization ) refers to the adaptation of an application or a component to meet the language, cultural and other requirements to a specific locale (i.e. a target market).

Internationalization (aka i18n, where 18 is the number of letters between the letter ‘i’ and the letter ‘n’ in the word internationalization) refers to the process of designing a software so that it can be localized to various languages and regions cost-effectively and easily without any engineering changes to the software. A useful website on i18n is http://www.i18nfaq.com.

Q. What are the characteristics of an internalized program?
A.
  • The same executable can run worldwide without having to recompile for other or new languages. 
  • Text messages and GUI component labels are not hard-coded in the program. Instead they are stored outside the source code in “.properties” files and retrieved dynamically based on the locale. 
  • Culturally dependent data such as dates and currencies appear in formats that conform to end user's region and language. (e.g. USA date format mm/dd/yyyy, Australian date format dd/mm/yyyy). 

Q. What are the different types of data that vary with region or language?
A. Messages (error messages, warning messages, info messages, etc), dates, currencies, numbers, measurements, phone numbers, postal addresses, tax calculations, graphics, icons, GUI labels, sounds, colors, online help, etc.

Q. What is a Locale?
A.  A Locale has the form of xx_YY (xx – is a two character language code && YY is a two character country code. E.g. en_US (English – United States), en_GB (English - Great Britain), fr_FR (french - France). The java.util.Locale class can be used as follows:

Locale locale1 = new Locale(“en”, “US”);
Locale locale2 = Locale.US;
Locale locale3 = new Locale(“en”);
Locale locale4 = new Locale(“en”, “US”, “optional”); // to allow the possibility of more than one 
                                                     // locale per language/country combination.

locale2.getDefault().toString();         //  en_US
locale2.getLanguage();                   //  “en” 
locale2.getCountry();                    //  ”US”


Resource bundles can be created using the locale to externalize the locale-specific messages:

Message_en_US.properties

   Greetings = Hello

Message_fr_FR.properties

   Greetings = Bonjour

These resource bundles reside in classpath and gets read at runtime based on the locale.

Locale currentLoc = new Locale(“fr”, “FR”); 
ResourceBundle messages = ResourceBundle.getBundle(“Message”, currentLoc);
System.out.println(messages.getString(“Greetings”));  //prints Bonjour




Note: When paired with a locale, the closest matching file will be selected. If no match is found then the default file will be the Message.properties. In JEE, locale is stored in HTTP session and resource bundles (stored as *.properties files under WEB-INF/classes directory) are loaded from the web.xml deployment descriptor file. Locale specific messages can be accessed via tags (e.g. Struts, JSTL etc).

The java.text package consists of classes and interfaces that are useful for writing internationalized programs. By default they use the default locale, but this can be overridden. E.g. NumbeFormat, DateFormat, DecimalFormat, SimpleDateFormat, MessageFormat, ChoiceFormat, Collator (compare strings according to the customary sorting order for a locale) etc.

DateFormat:

 
Date now = new Date();
Locale locale = Locale.US;

String s = DateFormat.getDateInstance(DateFormat.SHORT, locale).format(now);

NumberFormat:
 
NumberFormat usFormat = NumberFormat.getInstance(Locale.US);
String s1 = usFormat.format(1785.85);  // s1   1,785.85

NumberFormat germanyFormat = NumberFormat.getInstance(Locale.GERMANY);
String s2 = germanyFormat.format(1785.85);  // s2  1.785,85

To use default locale:
 
NumberFormat.getInstance();
NumberFormat.getPercentInstance();
NumberFormat.getCurrencyInstance();

To use specific locale:
 
NumberFormat.getInstance(Locale.US);
NumberFormat.getCurrencyInstance(myLocale);

Q. When a web application has users with different time zones, how will you manage dates and time in the system in a manner that looks consistent to all users
A.
  • UTC is the coordinate universal time in the UK (like Greenwhich mean time). All time zones are calculated as offsets to UTC time. For example, Sydney is UTC+10, India is UTC+5.30, etc.
  • During somer, some regions do have the daylight savings. UTC time is independent of daylight savings time and it needs to be taken into consideration.
  • If your application needs to store dates and time internally, for example in a database, convert it to UTC time before storing it.
  • When the user retrieves records with date/time, it gets converted to their locale time as users like to see that date and time converted to his own time zone.
  • Websites need to capture the user customization info like preferred language, country of residence, current location, preferred time zone

Q. What is the difference between String.compareTo( ) and Collator.compare()?
A. Every language has its own rules for how strings and letters are sorted. So, using the String.compareTo( ) method may not work for all languages. So, you need use a java.text.Collator instance created for a specific Locale.

 
Locale   locale = Locale.UK;
Collator collator = Collator.getInstance(locale);
int result = collator.compare("Apple", "Apple");

Q. How does Java keep stings internally?
A. In Java all strings are kept in unicode (UTF-16 is 16 bit unicode). Since not all text received from users or the outside world is in unicode, your application may have to convert from non-unicode to unicode when reads and do the reverse by converting from unicode to non-unicode when writes. The Java String class and io package have methods to perform this conversion.

 
bytes[] bytes = str.getBytes(Charset.forName("UTF-8"));
Reader      reader      = new InputStreamReader(inputStream,
                                                Charset.forName("UTF-8"));

Labels:

0 Comments:

Post a Comment

Subscribe to Post Comments [Atom]

<< Home