Java and Locales
Each country in the world has its own
cultural conventions. Sometimes, a
country has multiple cultural conventions if it consists of more than one ethnic
group.
When you internationalize your
software, you have to take these issues into consideration. Locale is used to refer to cultural
conventions used in each country. If the format of data is affected by the
locale, the data is said to be locale-sensitive. If the data is
locale-sensitive, you have to present or process the data following the
conventions used in the specific locale.
Typical locale-sensitive data
are:
l Date and time format
l Number format including monetary format
l Collation sequence
l Name format
l Address format
l Unit of measurement - Metric (SI) or pound/feet
For date, time, number formats and collation sequence, Java provides string support of locale via the Locale class and various locale-sensitive formatter class.
Locale class
Before we discuss locale-sensitive
data, let's go over the Locale class that is essential in handling the
locale-sensitive data in your code.
Here is how to instantiate the class for the major Western Europe and
North America countries:
import java.util.*;
public class intl31 {
public static void main(String args[])
{
String asLanguageCountry[][] = {
// Western Europe
{ "en", "GB"},
{ "fr", "FR"},
{ "de", "DE"},
{ "es", "ES"},
{ "it", "IT"},
{ "sv", "SE"},
{ "da", "DK"},
{ "nl", "NL"},
// North America
{ "en", "US"},
{ "en", "CA"},
{ "fr", "CA"},
{ "es", "MX"}
};
Locale l;
int i;
// Code
for(i = 0; i < asLanguageCountry.length; i++){
l = new Locale(asLanguageCountry[i][0], asLanguageCountry[i][1]);
System.out.print(l.getDisplayName(Locale.US) + "\n");
}
}
intl31.java
In
the first argument of the Locale constructor, you specify the two-digit ISO-639
language code in lower
case.
In
the second argument of the Locale constructor, you specify the two-digit
ISO-3166 country code in upper
case.
For
example, since Canada has an English-speaking region and a French-speaking
region, it has two locales to support each of them.
This
code outputs the following:
C:\programs\javatest\site>java intl31
English (United Kingdom)
French (France)
German (Germany)
Spanish (Spain)
Italian (Italy)
Swedish (Sweden)
Danish (Denmark)
Dutch (Netherlands)
English (United States)
English (Canada)
French (Canada)
Spanish (Mexico)
In
the sections that follow, we will use this code as the basis, and examine the
formats for various locale-sensitive data.
Date and time format
Java
provides the DateFormat class to present the date in a format appropriate for
each locale. The following code
displays the current date for the countries we used in previous example in the
four formats (full, long, medium and short formats):
import java.util.*;
import java.text.*;
public class intl33 {
public static void main(String args[])
{
String asLanguageCountry[][] = {
// Western Europe
{ "en", "GB"},
{ "fr", "FR"},
{ "de", "DE"},
{ "es", "ES"},
{ "it", "IT"},
{ "sv", "SE"},
{ "da", "DK"},
{ "nl", "NL"},
// North America
{ "en", "US"},
{ "en", "CA"},
{ "fr", "CA"},
{ "es", "MX"}
};
Locale l;
int i, j;
DateFormat df;
int aiDateFormat[] = {
DateFormat.FULL,
DateFormat.LONG,
DateFormat.MEDIUM,
DateFormat.SHORT
};
// Code
for(j = 0; j < aiDateFormat.length; j++){
for(i = 0; i < asLanguageCountry.length; i++){
l = new Locale(asLanguageCountry[i][0], asLanguageCountry[i][1]);
System.out.print(l.getDisplayName(Locale.US) + "\t");
df = DateFormat.getDateInstance(aiDateFormat[j], l);
System.out.print(df.format(new Date()) + "\n");
}
}
}
}
intl33.java
The
output result is following (The
chcp command issued at the beginning is to set the code page to 1252 on the
machine that executes this program):
C:\programs\javatest\site>chcp 1252
Active code page: 1252
C:\programs\javatest\site>java intl33
English (United Kingdom) 04 October 2002
French (France) vendredi 4 octobre 2002
German (Germany) Freitag, 4. Oktober 2002
Spanish (Spain) viernes 4 de octubre de 2002
Italian (Italy) venerdì 4 ottobre 2002
Swedish (Sweden) den 4 oktober 2002
Danish (Denmark) 4. oktober 2002
Dutch (Netherlands) vrijdag 4 oktober 2002
English (United States) Friday, October 4, 2002
English (Canada) Friday, October 4, 2002
French (Canada) vendredi 4 octobre 2002
Spanish (Mexico) viernes 4 de octubre de 2002
English (United Kingdom) 04 October 2002
French (France) 4 octobre 2002
German (Germany) 4. Oktober 2002
Spanish (Spain) 4 de octubre de 2002
Italian (Italy) 4 ottobre 2002
Swedish (Sweden) den 4 oktober 2002
Danish (Denmark) 4. oktober 2002
Dutch (Netherlands) 4 oktober 2002
English (United States) October 4, 2002
English (Canada) October 4, 2002
French (Canada) 4 octobre 2002
Spanish (Mexico) 4 de octubre de 2002
English (United Kingdom) 04-Oct-02
French (France) 4 oct. 02
German (Germany) 04.10.2002
Spanish (Spain) 04-oct-02
Italian (Italy) 4-ott-02
Swedish (Sweden) 2002-okt-04
Danish (Denmark) 04-10-2002
Dutch (Netherlands) 4-okt-02
English (United States) Oct 4, 2002
English (Canada) 4-Oct-02
French (Canada) 02-10-04
Spanish (Mexico) 4/10/2002
English (United Kingdom) 04/10/02
French (France) 04/10/02
German (Germany) 04.10.02
Spanish (Spain) 4/10/02
Italian (Italy) 04/10/02
Swedish (Sweden) 2002-10-04
Danish (Denmark) 04-10-02
Dutch (Netherlands) 4-10-02
English (United States) 10/4/02
English (Canada) 04/10/02
French (Canada) 02-10-04
Spanish (Mexico)
4/10/02
As
you can see, the Month/Day/Year format that is used in the U.S. is not
necessarily used in the rest of the world, and supporting different formats on
your own requires certain development cycles. Using the DateFormat class can take the
burden off your development, and makes it possible to easily provide the
international date format support in your software.
Time format
The
appropriate time format for each locale can be obtained by calling DateFormat.getTimeInstance(). The following code contains a
slight modification from the previous example to illustrate
this:
import java.util.*;
import java.text.*;
public class intl34 {
public static void main(String args[])
{
String asLanguageCountry[][] = {
// Western Europe
{ "en", "GB"},
{ "fr", "FR"},
{ "de", "DE"},
{ "es", "ES"},
{ "it", "IT"},
{ "sv", "SE"},
{ "da", "DK"},
{ "nl", "NL"},
// North America
{ "en", "US"},
{ "en", "CA"},
{ "fr", "CA"},
{ "es", "MX"}
};
Locale l;
int i, j;
DateFormat tf;
int aiDateFormat[] = {
DateFormat.FULL,
DateFormat.LONG,
DateFormat.MEDIUM,
DateFormat.SHORT
};
// Code
for(j = 0; j < aiDateFormat.length; j++){
for(i = 0; i < asLanguageCountry.length; i++){
l = new Locale(asLanguageCountry[i][0], asLanguageCountry[i][1]);
System.out.print(l.getDisplayName(Locale.US) + "\t");
tf = DateFormat.getTimeInstance(aiDateFormat[j], l);
System.out.print(tf.format(new Date()) + "\n");
}
System.out.println("\n");
}
}
}
The
output is shown below:
C:\programs\javatest\site>java intl34
English (United Kingdom) 17:54:06 o'clock PDT
French (France) 17 h 54 PDT
German (Germany) 17.54 Uhr PDT
Spanish (Spain) 17H54' PDT
Italian (Italy) 17.54.06 PDT
Swedish (Sweden) kl 17:54 PDT
Danish (Denmark) 17:54:06 PDT
Dutch (Netherlands) 17:54:06 uur PDT
English (United States) 5:54:06 PM PDT
English (Canada) 5:54:06 o'clock PM PDT
French (Canada) 17 h 54 PDT
Spanish (Mexico) 05:54:06 PM PDT
English (United Kingdom) 17:54:06 PDT
French (France) 17:54:06 PDT
German (Germany) 17:54:06 PDT
Spanish (Spain) 17:54:06 PDT
Italian (Italy) 17.54.06 PDT
Swedish (Sweden) 17:54:06 PDT
Danish (Denmark) 17:54:06 PDT
Dutch (Netherlands) 17:54:06 PDT
English (United States) 5:54:06 PM PDT
English (Canada) 5:54:06 PDT PM
French (Canada) 17:54:06 PDT
Spanish (Mexico) 05:54:06 PM PDT
English (United Kingdom) 17:54:06
French (France) 17:54:06
German (Germany) 17:54:06
Spanish (Spain) 17:54:06
Italian (Italy) 17.54.06
Swedish (Sweden) 17:54:06
Danish (Denmark) 17:54:06
Dutch (Netherlands) 17:54:06
English (United States) 5:54:06 PM
English (Canada) 5:54:06 PM
French (Canada) 17:54:06
Spanish (Mexico) 05:54:06 PM
English (United Kingdom) 17:54
French (France) 17:54
German (Germany) 17:54
Spanish (Spain) 17:54
Italian (Italy) 17.54
Swedish (Sweden) 17:54
Danish (Denmark) 17:54
Dutch (Netherlands) 17:54
English (United States) 5:54 PM
English (Canada) 5:54 PM
French (Canada) 17:54
Spanish (Mexico) 05:54 PM
In
addition to the time format, if your software supports simultaneous use of your
software by multiple users in different time zones (for example U.S., Japan and
Europe) at the same time, you may want to consider storing date/time information
in a single time-zone, and convert the value to the local time zone of the user
when it accepts or displays data.
If you take this approach, you will no longer have to tag each date/time
data with the time zone which may be a plus depending on your
application.
Conversion from string to date
In
Java, it is possible to parse a monolithic date string that contains month, day
and year and convert it to the Date class.
However, this is not recommended when your software receives data input
from various regions of the world at the same time. The following example illustrates the
case where the user in the U.S. enters the date "
October 12, 2004" in short format "10/12/4", and how
this string is interpreted in different locale settings:
import java.util.*;
import java.text.*;
public class intl35 {
public static void main(String args[])
{
String asLanguageCountry[][] = {
// Western Europe
{ "en", "GB"},
{ "fr", "FR"},
{ "de", "DE"},
{ "es", "ES"},
{ "it", "IT"},
{ "sv", "SE"},
{ "da", "DK"},
{ "nl", "NL"},
// North America
{ "en", "US"},
{ "en", "CA"},
{ "fr", "CA"},
{ "es", "MX"}
};
Locale l;
int i, j;
DateFormat df;
DateFormat dfLong;
String sDate = "10/12/4"; // October 12, 2004 in the U.S. format
Date d;
// Code
for(i = 0; i < asLanguageCountry.length; i++){
l = new Locale(asLanguageCountry[i][0], asLanguageCountry[i][1]);
System.out.print(l.getDisplayName(Locale.US) + "\t");
df = DateFormat.getDateInstance(DateFormat.SHORT, l);
dfLong = DateFormat.getDateInstance(DateFormat.LONG, l);
try {
d = df.parse(sDate);
if(d == null){
System.out.print("Date string cannot be parsed." + "\n");
}
else{
System.out.print(dfLong.format(new Date()) + "\n");
}
}
catch(Exception e){
System.out.print("Date string cannot be parsed: " + e.getMessage() + "\n");
}
}
}
}
intl35.java
The
output is shown below:
C:\programs\javatest\site>java intl35
English (United Kingdom) 04
October 2002
French (France) 4 octobre 2002
German (Germany) Date
string cannot be parsed: Unparseable date: "10/12/4
"
Spanish (Spain) 4 de octubre de 2002
Italian (Italy) 4 ottobre 2002
Swedish (Sweden) Date
string cannot be parsed: Unparseable date: "10/12/4
"
Danish (Denmark) Date
string cannot be parsed: Unparseable date: "10/12/4
"
Dutch (Netherlands) Date string cannot be
parsed: Unparseable date: "10/12/4
"
English (United States) October 4, 2002
English (Canada)
October 4, 2002
French (Canada) Date string cannot be parsed: Unparseable date:
"10/12/4"
Spanish (Mexico) 4 de
octubre de 2002
As you can see, parse failed for some of the
locales. Even you can make a fairly
intelligent guess, you can't conduct a 100%-foolproof parsing, and the risk is
not worth taking. For this reason, if you accept a date input from the user, it
is much safer to provide three separate fields for month, day and year, and
parse each value separately. If this is not possible, you can also put the
format that you expect by the input field as many paper forms
do.
Number format
You
can use a similar technique to display the number based on the
locale.
The
following code displays "12,345.6789" in various locales:
import java.util.*;
import java.text.*;
public class intl37 {
public static void
main(String args[])
{
String
asLanguageCountry[][] = {
// Western Europe
{ "en", "GB"},
{ "fr", "FR"},
{ "de", "DE"},
{ "es", "ES"},
{ "it", "IT"},
{ "sv", "SE"},
{ "da", "DK"},
{ "nl", "NL"},
// North America
{ "en", "US"},
{ "en", "CA"},
{ "fr", "CA"},
{ "es", "MX"}
};
Locale
l;
int i,
j;
NumberFormat nf;
//
Code
for(i = 0;
i < asLanguageCountry.length; i++){
l = new Locale(asLanguageCountry[i][0],
asLanguageCountry[i][1]);
System.out.print(l.getDisplayName(Locale.US) +
"\t");
nf = NumberFormat.getInstance(l);
System.out.print(nf.format(new Double(12345.6789)) +
"\n");
}
}
}
intl37.java
The
output is shown below:
C:\programs\javatest\site>java intl37
English (United Kingdom) 12,345.679
French (France) 12 345,679
German (Germany) 12.345,679
Spanish (Spain) 12.345,679
Italian (Italy) 12.345,679
Swedish (Sweden) 12 345,679
Danish (Denmark) 12.345,679
Dutch (Netherlands) 12.345,679
English (United States) 12,345.679
English (Canada) 12,345.679
French (Canada) 12 345,679
Spanish (Mexico) 12,345.679
Please note :
l For Germany, Italy, Spain, Netherlands and Denmark, a period is used for a thousand separator and a comma is used for a decimal separator, which is opposite from the U.S. custom.
l For France, French Canada and Sweden, a space is used for a thousand separator and a comma is used for a decimal separator.
As
you can imagine, the conversion from the numeric string to actual number poses
the same problem as the conversion from a date string to the Date object. If the text field in your software
accepts a floating point number, the safest way is provide two fields for the
integer part and the fractional part. If that is not possible in your software,
you may want to clearly mark the format you expect for the numeric field.
Currency format
You
can also use the same technique for formatting the monetary value using the
NumberFormat class, even though there are some issues you need to
consider:
import java.util.*;
import java.text.*;
public class intl38 {
public static void main(String args[])
{
String asLanguageCountry[][] = {
// Western Europe
{ "en", "GB"},
{ "fr", "FR"},
{ "de", "DE"},
{ "es", "ES"},
{ "it", "IT"},
{ "sv", "SE"},
{ "da", "DK"},
{ "nl", "NL"},
// North America
{ "en", "US"},
{ "en", "CA"},
{ "fr", "CA"},
{ "es", "MX"}
};
Locale l;
int i, j;
NumberFormat nf;
// Code
for(i = 0; i < asLanguageCountry.length; i++){
l = new Locale(asLanguageCountry[i][0], asLanguageCountry[i][1]);
System.out.print(l.getDisplayName(Locale.US) + "\t");
nf = NumberFormat.getCurrencyInstance(l);
System.out.print(nf.format(new Double(12345.6789)) + "\n");
}
}
}
intl38.java
Output is shown
below:
English (United Kingdom)
£12,345.68
French (France) 12 345,68
€
German (Germany)
12.345,68 €
Spanish (Spain) 12.345,68
€
Italian (Italy) €
12.345,68
Swedish (Sweden)
12 345,68 kr
Danish (Denmark) kr
12.345,68
Dutch (Netherlands) €
12.345,68
English (United States)
$12,345.68
English (Canada)
$12,345.68
French (Canada) 12 345,68
$
Spanish (Mexico)
$12,345.68
This
output was obtained under JDK 1.4.0 as shown below:
C:\programs\javatest\site>java -version
java version "1.4.0"
Java(TM) 2 Runtime Environment, Standard Edition (build
1.4.0-b92)
Java HotSpot(TM) Client VM (build 1.4.0-b92, mixed
mode)
However, if you are using the old
version of JDK, old currency symbols will be returned as shown
below:
C:\programs\javatest\site>java -version
java version "1.3.1_02"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.1_02-b02)
Java HotSpot(TM) Client VM (build 1.3.1_02-b02, mixed mode)
C:\programs\javatest\site>java intl38
English (United Kingdom) £12,345.68
French (France) 12 345,68 F
German (Germany) 12.345,68 DM
Spanish (Spain) 12.346 Pts
Italian (Italy) L. 12.346
Swedish (Sweden) 12 345,68 kr
Danish (Denmark) kr 12.345,68
Dutch (Netherlands) fl 12.345,68
English (United States) $12,345.68
English (Canada) $12,345.68
French (Canada) 12 345,68 $
Spanish (Mexico) $12,345.68
If
your software requires the Euro symbol (0x20AC in Unicode, 0x80 in codepage
1252), you have to make sure that the user is using a JDK version that supports
it. In addition, if your software runs on the Microsoft platform, the Euro
symbol is supported on Windows XP, Windows 2000, Windows ME, and Windows 98, but
the older versions of Windows require installing Microsoft Euro Currency Support
solutions1 according to the Microsoft website. It is expected that more countries will
join the EU in the future, so if you want to support the Euro symbol, you may
want to keep an eye on the status of the EU membership of the countries that you
are targeting your software.
If
you just want to obtain the currency code for each locale, you can use the
Currency class that is added to JDK 1.4 as shown below.
import java.util.*;
import java.text.*;
public class intl40 {
public static void
main(String args[])
{
String
asLanguageCountry[][] = {
// Western Europe
{ "en", "GB"},
{ "fr", "FR"},
{ "de", "DE"},
{ "es", "ES"},
{ "it", "IT"},
{ "sv", "SE"},
{ "da", "DK"},
{ "nl", "NL"},
// North America
{ "en", "US"},
{ "en", "CA"},
{ "fr", "CA"},
{ "es", "MX"}
};
Locale
l;
int i,
j;
NumberFormat nf;
Currency
cur;
//
Code
for(i = 0;
i < asLanguageCountry.length; i++){
l = new Locale(asLanguageCountry[i][0],
asLanguageCountry[i][1]);
System.out.print(l.getDisplayName(Locale.US) +
"\t");
cur = Currency.getInstance(l);
System.out.print( "\t" +
"ISO-4217
code : " + cur.getCurrencyCode() + "\t" +
"\n");
}
}
}
The
output is shown below:
C:\programs\javatest\site>java intl40
English (United Kingdom) ISO-4217 code : GBP
French (France) ISO-4217 code : EUR
German (Germany) ISO-4217 code : EUR
Spanish (Spain) ISO-4217 code : EUR
Italian (Italy) ISO-4217 code : EUR
Swedish (Sweden) ISO-4217 code : SEK
Danish (Denmark) ISO-4217 code : DKK
Dutch (Netherlands) ISO-4217 code : EUR
English (United States) ISO-4217 code : USD
English (Canada) ISO-4217 code : CAD
French (Canada) ISO-4217 code : CAD
Spanish (Mexico) ISO-4217 code : MXN
In
real world applications, displaying numbers in another currency is likely to
involve exchange rates. JDK doesn't
provide a pre-made exchange rate calculation mechanism, so it is up to you to
implement this.
Collation sequence
In
internationalizing an application, it is important that all the strings are
sorted based on the cultural conventions for each locale.
Shown
below is an example of non locale-sensitive source code:
import java.util.*;
import java.text.*;
public class intl43 {
public static void
main(String args[])
{
String
asLanguageCountry[][] = {
{ "fr", "FR"},
{ "de", "DE"}
};
String
asList[] = {
"a",
"e",
"\u00e9", // e with acute
"\u00df", // German ess-zed
"ss",
"st",
"z"
};
Locale
l;
int i,
j;
//
Code
for(i = 0;
i < asLanguageCountry.length; i++){
l = new Locale(asLanguageCountry[i][0],
asLanguageCountry[i][1]);
System.out.print(l.getDisplayName(Locale.US) +
"\n");
Arrays.sort(asList);
for(j = 0; j < asList.length; j++){
System.out.print( "[" + Integer.toString(j) + "] "
+
asList[j] +
"\n");
}
System.out.print("\n");
}
}
}
intl43.java
Output is shown
below:
C:\programs\javatest\site>java intl43
French (France)
[0] a
[1] e
[2] ss
[3] st
[4] z
[5] ß
[6] é
German (Germany)
[0] a
[1] e
[2] ss
[3] st
[4] z
[5] ß
[6] é
Please note that both "ess-zed" and "e
with acute accent" are sorted after the letter "z".
However, in German, even though
"ess-zed" is a ligature of "s" and "z", it is treated as equivalent of "ss" in
sorting. For example, in
Langenscheidt's German-English dictionary, the word "Mißklang" is sorted after "Mission", but
before "Mist".
So in
the example above, "ß" should be placed before
"st".
Similarly, for French, "é"
should be placed after "e" (for example, in Larousse's French-English
dictionary, "frisé" is listed immediately after
"frise").
To
correct the problem, the following changes were made:
Arrays.sort(asList);
Locale-insensitive code (old)
col =
Collator.getInstance(l);
col.setStrength(Collator.IDENTICAL); //
case-sensitive
col.setDecomposition(Collator.FULL_DECOMPOSITION);
Arrays.sort(asList, col);
Locale-sensitive code (new)
Instead of simply using the natural
order sorting in the Arrays.sort method, we obtain the instance of the
locale-sensitive Collator class and use it to sort the list of strings. The
complete code is shown below:
import java.util.*;
import java.text.*;
public class intl44 {
public static void
main(String args[])
{
String
asLanguageCountry[][] = {
{ "fr", "FR"},
{ "de", "DE"}
};
String
asList[] = {
"a",
"e",
"\u00e9", // e with acute
"\u00df", // German ess-zed
"ss",
"st",
"z"
};
Locale
l;
int i,
j;
Collator
col;
//
Code
for(i = 0;
i < asLanguageCountry.length; i++){
l = new Locale(asLanguageCountry[i][0],
asLanguageCountry[i][1]);
System.out.print(l.getDisplayName(Locale.US) +
"\n");
col = Collator.getInstance(l);
col.setStrength(Collator.IDENTICAL); //
case-sensitive
col.setDecomposition(Collator.FULL_DECOMPOSITION);
Arrays.sort(asList, col);
for(j = 0; j < asList.length; j++){
System.out.print( "[" + Integer.toString(j) + "] "
+
asList[j] +
"\n");
}
System.out.print("\n");
}
}
}
intl44.java
As
shown in the output below, the strings are sorted correctly this
time:
C:\programs\javatest\site>java intl44
French (France)
[0] a
[1] e
[2] é
[3] ss
[4] ß
[5] st
[6] z
German (Germany)
[0] a
[1] e
[2] é
[3] ss
[4] ß
[5] st
[6] z
If
your application simply returns the list of strings in the database, you will
also have to check to see if database is returning the strings in a
locale-sensitive order.
Name format
The
display order of the first name and the last name is also locale-dependent. In English, if you want to display the
name "Mr. John Doe Jr.", the following formats are typically
used:
l John Doe,
l John Doe Jr.
l Doe, John
l Mr. John Doe
l Mr. John Doe Jr.
However, in Japanese, the most common
format will be the last name followed by the first name. The space between the last name and the
first name may be omitted depending on the style guideline that is used for the
document. To cope with this, you may want to implement a class that returns the
names in the String format based on your target locale. If you name the name formatter class
"xNameFormat", the example will be:
sName = sFirstName + " " + sFirstName;
Locale-insensitive code (old)
xNameFormat nf = xNameFormat.getNameInstance(xNameFormat.LONG, lLocale);
sName = nf.format(sLastName, sFirstName);
Locale-sensitive code (new)
Support of pronunciation data for name for the Japanese market
If
your software supports the Japanese market, another issue you may have to
consider is the support of pronunciation data for names. Since one Kanji has multiple ways of
pronouncing it, it is common to have a separate pronunciation field in a
form. This data for pronunciation
is known as "Furigana". What this
means is that if you are storing data in your database, you may have to make
extensive changes to support this feature. The list of the changes will
be:
l Additional columns in database tables or views to store these data
l Additional fields in user interface to enter, look-up and display these data
l Additional code to support these features
Since
the names are expected to be ordered by pronunciation rather than by the code
point of Kanji regardless of whether the pronunciation data itself is displayed,
the cost of making these changes should not be
underestimated.
Since
the cost of implementing these features is high, before you implement these
features, you might want to check with your sales representative or distributors
in Japan to see if this is needed for your product.
Address format
The
format of address is also locale-dependent. If you concatenate the address elements
to a single string, you may want to design a class that formats an address based
on the target locale. This approach
is similar to the xNameFormat class as we discussed
earlier.
One
issue to consider is if your product supports an address lookup from the ZIP
code, the feature has to be extended to support ZIP codes for other
countries. For example, if you want
to support the postal code lookup in Japan, you have to add the 7-digit postal
codes to your database, and implement the mechanism to look it up. When you design the initial schema, you
may want to keep this in mind so that your design can be extensible to support
more countries easily in the future as the need arises.
Unit of measurement - Metric (SI) or pound/feet
If
your product displays units of measurement with any values, you have to make
sure that the metric system can be also used or selected as the main unit of
measurement.
For
printing, if your software supports printing in the Letter size by default, make
sure that A4 can be selected as default for the international market.