SDSU CS 596 Java Programming
Fall Semester, 1998
Internationalization
To Lecture Notes Index
© 1998, All Rights Reserved, SDSU & Roger Whitney
San Diego State University -- This page last updated 21-Dec-98

Contents of Doc 32, Internationalization


References


Graphic Java 1.2 Volume I: AWT 3 rd Edition, Geary, Chapter 11 (pp. 457-464)

Java in a Nutshell , 2nd Ed. David Flanager, Chapter 11

The Java Programming Language , 2 ed., Arnold & Gosling, Chapter 16

On-line Java Documentation

Listen Here!S-dec2 49secs, Q-dec3 2mins Doc 32, Internationalization Slide # 2

Internationalization

Formatting



Are dates formatted as:
10/13/97
13/10/97
13.10.97

Are numbers formatted as:
1,234.56
1.234,56
1;234.56


Listen Here!S-dec2 3mins Doc 32, Internationalization Slide # 3
Java's Solution

An instances of the java.util.Locale class contains the rules for a language in a location

Each Java virtual machine has a default instance of the Locale class, which should be for the local language rules in the current country

java.text.NumberFormat

Formats numbers, currency, and percents using the default Locale rules

For finer control over formatting numbers use java.text.DecimalFormat

java.text.DateFormat

Formats dates and time using the default Locale rules

Dates and times can be formatted in FULL, LONG, MEDIUM, and SHORT versions

For finer control over formatting dates use java.text.SimpleDateFormat

Doc 32, Internationalization Slide # 4
java.util.Locale

You create a Locale object using one of the two constructors of this class:

Locale(String language, String country)
Locale(String language, String country, String variant)

The first argument to both constructors is a valid ISO Language Code. These codes are the lower-case two-letter codes as defined by ISO-639. You can find a full list of these codes at a number of sites, such as:

http://www.ics.uci.edu/pub/ietf/http/related/iso639.txt

The second argument to both constructors is a valid ISO Country Code. These codes are the upper-case two-letter codes as defined by ISO-3166. You can find a full list of these codes at a number of sites, such as:

http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html

Listen Here!S-dec2 1min Doc 32, Internationalization Slide # 5

Languages and Countries Available in JDK1.2RC1

Country
Code
Language
Code
Albania
AL
Albanian
sq
Algeria
DZ
Arabic
ar
Argentina
AR
Spanish
es
Australia
AU
English
en
Austria
AT
German
de
Bahrain
BH
Arabic
ar
Belarus
BY
Byelorussian
be
Belgium
BE
Dutch
nl
Belgium
BE
French
fr
Bolivia
BO
Spanish
es
Brazil
BR
Portuguese
pt
Bulgaria
BG
Bulgarian
bg
Canada
CA
English
en
Canada
CA
French
fr
Chile
CL
Spanish
es
China
CN
Chinese
zh
Colombia
CO
Spanish
es
Costa Rica
CR
Spanish
es
Croatia
HR
Croatian
hr
Czech Republic
CZ
Czech
cs
Denmark
DK
Danish
da
Dominican Republic
DO
Spanish
es
Ecuador
EC
Spanish
es
Egypt
EG
Arabic
ar
El Salvador
SV
Spanish
es
Estonia
EE
Estonian
et
Finland
FI
Finnish
fi
France
FR
French
fr
Germany
DE
German
de
Greece
GR
Greek
el
Guatemala
GT
Spanish
es
Honduras
HN
Spanish
es
Hong Kong
HK
Chinese
zh
Hungary
HU
Hungarian
hu
Iceland
IS
Icelandic
is
Iraq
IQ
Arabic
ar

Doc 32, Internationalization Slide # 6

Country
Code
Language
Code
Ireland
IE
English
en
Israel
IL
Hebrew
iw
Italy
IT
Italian
it
Italy
IT
Italian
it
Japan
JP
Japanese
ja
Jordan
JO
Arabic
ar
Kuwait
KW
Arabic
ar
Latvia
LV
Latvian (Lettish)
lv
Lebanon
LB
Arabic
ar
Libya
LY
Arabic
ar
Lithuania
LT
Lithuanian
lt
Luxembourg
LU
French
fr
Luxembourg
LU
German
de
Macedonia
MK
Macedonian
mk
Mexico
MX
Spanish
es
Morocco
MA
Arabic
ar
Netherlands
NL
Dutch
nl
New Zealand
NZ
English
en
Nicaragua
NI
Spanish
es
Norway
NO
Norwegian
no
Oman
OM
Arabic
ar
Panama
PA
Spanish
es
Paraguay
PY
Spanish
es
Peru
PE
Spanish
es
Poland
PL
Polish
pl
Portugal
PT
Portuguese
pt
Puerto Rico
PR
Spanish
es
Qatar
QA
Arabic
ar
Romania
RO
Romanian
ro
Russia
RU
Russian
ru
Saudi Arabia
SA
Arabic
ar
Slovakia
SK
Slovak
sk
Slovenia
SI
Slovenian
sl
South Africa
ZA
English
en
South Korea
KR
Korean
ko

Doc 32, Internationalization Slide # 7

Country
Code
Language
Code
Spain
ES
Catalan
ca
Spain
ES
Spanish
es
Sudan
SD
Arabic
ar
Sweden
SE
Swedish
sv
Switzerland
CH
French
fr
Switzerland
CH
German
de
Switzerland
CH
Italian
it
Syria
SY
Arabic
ar
Taiwan
TW
Chinese
zh
Thailand
TH
Thai
th
Tunisia
TN
Arabic
ar
Turkey
TR
Turkish
tr
Ukraine
UA
Ukrainian
uk
United Arab Emirates
AE
Arabic
ar
United Kingdom
GB
English
en
United States
US
English
en
Uruguay
UY
Spanish
es
Venezuela
VE
Spanish
es
Yemen
YE
Arabic
ar
Yugoslavia
YU
Serbian
sr
Yugoslavia
YU
Serbo-Croatian
sh

Listen Here!S-dec2 2mins, Q-dec3 5mins Doc 32, Internationalization Slide # 8
Using the Default Locale to Format
import java.text.*;
class FormatUsingLocalRules
   {
   public static void main( String args[] ) throws Exception
      {
      NumberFormat number = NumberFormat.getInstance(  );
      NumberFormat currency = 
            NumberFormat.getCurrencyInstance(  );
      DateFormat shortDate = 
            DateFormat.getDateInstance(DateFormat.SHORT);
      DateFormat fullTime = 
            DateFormat.getTimeInstance(DateFormat.FULL );
      
      System.out.println( "Number: " + number.format( 123456 ));
      System.out.println( "Currency: " + 
                              currency.format( 1234.56 ));
      System.out.println( "ShortDate: " + 
                              shortDate.format( new Date() ));
      System.out.println( "FullTime: " + 
                              fullTime.format( new Date() ));
      }
   }
Output
Number: 123,456
Currency: $1,234.56
ShortDate: 10/13/97
FullTime: 5:15:42 oclock PM PDT

Listen Here!S-dec2 33secs, Q-dec10 3mins Doc 32, Internationalization Slide # 9
International Example

Explicitly use other locales to show that they are different

Usually you do not want to use locales explicitly, usually:

Use the default give by the VM or
Set the default to what you want

class FormatExplicitlyCallingDifferentLocale
   {
   public static void main( String args[] )
      {
      System.out.println( "-------US English------");
      internationalPrint( Locale.getDefault() );
      System.out.println( "-------Canadian English------");
      internationalPrint( new Locale("en", "CA" ));
      System.out.println( "-------Spanish Spanish------");
      internationalPrint( new Locale("es", "ES" ));
      System.out.println( "-------German German------");
      internationalPrint( new Locale("de", "DE" ));
      }
//internationalPrint on next slide

Listen Here!S-dec2 53secs, Q-dec10 4mins Doc 32, Internationalization Slide # 10
//International Example - continued

   public static void internationalPrint( Locale custom )
      {
      NumberFormat number = 
               NumberFormat.getInstance( custom );
      NumberFormat currency = 
               NumberFormat.getCurrencyInstance( custom );
      DateFormat shortDate = DateFormat.getDateInstance(
                            DateFormat.SHORT, custom );
      DateFormat fullDate = DateFormat.getDateInstance( 
                           DateFormat.FULL, custom );
      DateFormat shortTime = DateFormat.getTimeInstance( 
                           DateFormat.SHORT, custom );
      DateFormat longTime = DateFormat.getTimeInstance(
                           DateFormat.LONG,custom );
      System.out.println( "Number: " + 
                        number.format( 123456 ));
      System.out.println( "Currency: " + 
                        currency.format( 1234.56 ));
      System.out.println( "ShortDate: " + 
                        shortDate.format( new Date() ));
      System.out.println( "FullDate: " + 
                        fullDate.format( new Date() ));
      System.out.println( "ShortTime: " + 
                        shortTime.format( new Date() ));
      System.out.println( "LongTime: " + 
                        longTime.format( new Date() ));
      }
   }

Listen Here!S-dec2 2mins Doc 32, Internationalization Slide # 11
//International Example - continued

Output
-------US English------
Number: 123,456
Currency: $1,234.56
ShortDate: 10/12/97
FullDate: Sunday, October 12, 1997
ShortTime: 9:45 PM
LongTime: 9:45:46 PM PDT
-------Canadian English------
Number: 123;456
Currency: $1;234.56
ShortDate: 12/10/97
FullDate: Sunday, October 12, 1997
ShortTime: 9:45 PM
LongTime: 9:45:46 PDT PM
-------Spanish Spanish------
Number: 123.456
Currency: 1.234,56 Pts
ShortDate: 13/10/97
FullDate: lunes 13 de octubre de 1997
ShortTime: 6:45
LongTime: 6:45:46 GMT+02:00
-------German German------
Number: 123.456
Currency: 1.234,56 DM
ShortDate: 13.10.97
FullDate: Montag, 13. Oktober 1997
ShortTime: 06:45
LongTime: 06:45:46 GMT+02:00

Listen Here!S-dec2 1min, Q-dec10 2mins Doc 32, Internationalization Slide # 12
Parsing Numbers/Dates Etc.

import java.text.*;
import java.util.Locale;
public class Test
   {
   public static void main( String args[] ) throws Exception 
      {
      Locale Spain = new Locale("es", "ES" );
      NumberFormat spanishFormat = 
               NumberFormat.getInstance( Spain );
      
      Number parsed = spanishFormat.parse( "123.456,5");
      System.out.println( parsed.floatValue() );
      
      parsed = spanishFormat.parse( "123.4.5.6,5");
      System.out.println( parsed.floatValue() );
      }
   }
Output
123456.5
123456.5

Listen Here!S-dec2 5mins, Q-dec10 7mins Doc 32, Internationalization Slide # 13

Static and Dynamic Text


import java.text.MessageFormat;
import java.util.Date;
class Test
   {
   public static void main( String args[] ) throws Exception
      {
      Object[] dynamicText = {"Roger",new Date() };
      
      String staticText = "{0}, it is {1,time,short}";
      String publicMessage = 
         MessageFormat.format(staticText, dynamicText);
      System.out.println( publicMessage );
      }
   }
Output
Roger, it is 10:03 PM

Doc 32, Internationalization Slide # 14

Internationalization of Text


In Java, you can write programs that will display text in the native language of the country in which the program is being run

The programmer has to supply the translations into each language

At run time the program will select the proper language, assuming the program uses correctly the internationalization features of the JDK

The translations of the text can be placed in data files or in special classes


Listen Here!S-dec7 4mins, Q-dec10 3mins Doc 32, Internationalization Slide # 15

Hello World Example with Just Classes


import java.util.ResourceBundle;
// The main program, will display either German, Spanish
// or English depending on where you run the program
class HelloWorld
   {
   public static void main( String args[] )   
      {
      ResourceBundle greetings = 
         ResourceBundle.getBundle( "Greetings" );
      
      System.out.println( greetings.getString( "hello" ));
      }
   }
// The default language, if the local language and/or country 
// can not be found this one will be used
import java.util.ListResourceBundle;
public class Greetings extends ListResourceBundle  
   {
   public Object[][] getContents()  
      {
      return new Object[][] 
         {
            { "hello", "Hello World!" },
            { "language", "English" },
            { "key", "value" } // can have as many pairs as needed
         };
      }
   }

Listen Here!S-dec7 1min, Q-dec10 2mins Doc 32, Internationalization Slide # 16
//Hello World - Continued

// Append _language code to base class name for a language
// Append _language_country to base class to indicate both 
// langauge and country
// de = 2 letter ISO-639 code for German
public class Greetings_de extends ListResourceBundle 
   {
   public Object[][] getContents()  
      {
      return new Object[][]   
         {
            { "hello", "Hallo, Welt!" },
            { "language", "Deutsch" }
         };
      }
   }
// de = 2 letter ISO-639 code for Spanish
public class Greetings_es extends ListResourceBundle 
   {
   public Object[][] getContents() 
      {
      return new Object[][]   
         {
            { "hello", "\u00A1Hola mundo!" },
            { "language", "Espa\u00F1ol" }
         };
      }
   }
// \u00A1 = inverted !   \u00BF = inverted ?
// \u00D1 = N with a tilde  \u00F1 = n with a tilde

Listen Here!S-dec7 6mins, Q-dec10 2mins Doc 32, Internationalization Slide # 17
Hello World Tested

import java.util.Locale;
import java.util.ResourceBundle;
class ThreeHellos
   {
   public static void main( String args[] )
      {
      foreignTest( );
      Locale.setDefault(  new Locale("es", "ES" ));
      foreignTest();
      Locale.setDefault(  new Locale("de", "DE" ));
      foreignTest( );
      }
      
   public static void foreignTest( )
      {
      ResourceBundle greetings = 
                     ResourceBundle.getBundle( "Greetings");
      
      System.out.println( "----" + 
                           greetings.getString( "language") + 
                           "----");
      System.out.println( greetings.getString( "hello" ));
      }
   }
Output
----English----
Hello World!
----Español----
¡Hola mundo!
----Deutsch----
Hallo, Welt!

Doc 32, Internationalization Slide # 18
Warning about Class Structure

Here are two ways to structure the Greetings class. The first was used just to save room on the slide (I print these out on 8.5 by 11 paper using 18-point font size). The first creates the array each time the method getContents is called (unless the compiler optimizes the call). The second only creates the array once, hence should be more efficient. I do not have any data to indicate what impact this would have on a program.

public class Greetings extends ListResourceBundle  
   {
   public Object[][] getContents()  
      {
      return new Object[][] 
         {
            { "hello", "Hello World!" },
            { "language", "English" },
         };
      }
   }

public class Greetings extends ListResourceBundle  
   {
   static final Object[][] contents =
         {
            { "hello", "Hello World!" },
            { "language", "English" },
            { "key", "value" } // can have as many pairs as needed
         };
   public Object[][] getContents()  
      {
      return contents;
      }
   }


Listen Here!Q-dec10 7mins Doc 32, Internationalization Slide # 19

Hello World Example - Using Files


Replace the classes Greetings, Greetings_de, Greetings_es with the following files below

Then either ThreeHellos or HelloWorld will work the same

In file Greetings.properties
hello = Hello World!
language = English


In file Greetings_es.properties
hello = \u00A1Hola mundo!
language = Espa\u00F1ol
# \u00A1 = Unicode for inverted "!"
# \u00F1 = Unicode for n with tilde

In Greetings_de.properties
hello = Hallo, Welt!
language = Deutsch


Doc 32, Internationalization Slide # 20

A More Complex Example


In file Greetings.properties
hello = Hello World!
language = English
publicService = {0}, it is {1,time,short}, do you know where your children are?

In file Greetings_es.properties
hello = \u00A1Hola mundo!
language = Espa\u00F1ol
publicService = {0}, son las {1,time,short} -- \u00BFsabes donde estan tus hijos?

# \u00A1 = inverted !   
# \u00BF = inverted ?
# \u00F1 = n with a tilde

In Greetings_de.properties
hello = Hallo, Welt!
language = Deutsch
publicService = {0}, es ist {1,time,short}. Weisst Du, wo Deine Kinder sind?

Doc 32, Internationalization Slide # 21
Testing the Different Locales

import java.text.MessageFormat;
import java.util.Date;
import java.util.Locale;
import java.util.ResourceBundle;
import java.util.ListResourceBundle;
class HelloWithPublicService
   {
   static Object[] dynamicData = {
         System.getProperty( "user.name" ),
         new Date()
         };
   public static void main( String args[] )
      {
      foreignTest( );
      Locale.setDefault(  new Locale("es", "ES" ));
      foreignTest();
      Locale.setDefault(  new Locale("de", "DE" ));
      foreignTest( );
      }
      

Doc 32, Internationalization Slide # 22
// HelloWithPublicService - Continued

   public static void foreignTest( )
      {
      ResourceBundle greetings = 
            ResourceBundle.getBundle( "Greetings");
      MessageFormat publicMessage;
      publicMessage = new MessageFormat(
                              greetings.getString( "publicService"));
      
      System.out.println( "----" + greetings.getString( "language") + 
                           "----");
      System.out.println( greetings.getString( "hello" ));
      System.out.println( publicMessage.format( dynamicData ));
      }
   }
Output
----English----
Hello World!
Roger Whitney, it is 10:11 PM, do you know where your children are?
----Español----
¡Hola mundo!
Roger Whitney, son las 6:11 -- ¿sabes donde estan tus hijos?
----Deutsch----
Hallo, Welt!
Roger Whitney, es ist 06:11. Weisst Du, wo Deine Kinder sind?


Copyright © 1998 SDSU & Roger Whitney, 5500 Campanile Drive, San Diego, CA 92182-7700 USA.
All rights reserved.

visitors since 02-Dec-98