Stocks.java (Source)

Download Stocks.java source file

View/Download Base (U.S. English) Properties file

View/Download French Properties file

View/Download Spanish Properties file

// Stocks.java - An applet to demonstrate some features of
// internationalization.  Adopted from "Portfolio.java" in
// "Java Examples in a Nutshell" by David Flanagan, O'Reilly
// And Associates, 1997. pp. 280-281.
// Written 1/2000 by Wayne Pollock, Tampa Florida USA.

/*
   <APPLET CODE="Stocks" HEIGHT="350" WIDTH="500">
      <PARAM NAME="Language" VALUE="fr">
      <PARAM NAME="Country" VALUE="FR">
   </APPLET>
*/

import java.applet.*;
import java.awt.*;
import java.text.*;
import java.util.*;

public class Stocks extends Applet
{
   private Locale locale, requestedLocale, defaultLocale;
   private NumberFormat number, price, percent;
   private DateFormat shortDate, fullTime;

   public void init ()
   {
      Position[] positions = new Position[3];
      // Get a calendar for the default time zone & locale:
      Calendar cal = Calendar.getInstance();
      cal.set( 1996, 6, 15 );
      positions[0] = new Position( "XXX", 400, cal.getTime(), 11.90, 13.00 );
      cal.set( 1996, 9, 14 );
      positions[1] = new Position( "YYY", 1100, cal.getTime(), 71.09, 27.25 );
      cal.set( 1991, 6, 27 );
      positions[2] = new Position( "ZZZ", 6000, cal.getTime(), 23.37, 89.12 );
      Date lastQuoteTime = new Date();
      setLocalesAndFormatters();

      // Use a ResourceBundle to get localized text strings.  For simple text
      // strings the ResourceBundle is sufficient, but for complex messages (with
      // embeded variables such as dates), we must turn to the MessageFormat class.

      ResourceBundle msgs = ResourceBundle.getBundle( "StocksMsgs", locale );

      MessageFormat mf = new MessageFormat( msgs.getString( "PortValue" ) );
      mf.setLocale( locale );
      // Due to a Java bug, you can't set a timezone for a MessageFormat.  So
      // you can't use the built-in date formatting, you must create your own
      // DateFormat, then tell the MessageFormat object to use it for a
      // specific argument.  (That's why two copies of lastQuoteTime are used.)

      mf.setFormat( 0, fullTime );
      Object [] msgArgs = { lastQuoteTime, lastQuoteTime };

      String text = "\n\t" + mf.format( msgArgs ) + "\n";
      text += msgs.getString( "Symbol" ) + "\t";
      text += msgs.getString( "Shares" ) + "\t";
      text += msgs.getString( "BoughtOn" ) + "\t";
      text += msgs.getString( "At" ) + "\t";
      text += msgs.getString( "Quote" ) + "\t";
      text += msgs.getString( "Change" ) + "\n";

      for ( int i = 0; i < positions.length; ++i )
      {
         Position pos = positions[i];
         text += pos.symbol + "\t";
         text += number.format( pos.shares ) + "\t";
         text += shortDate.format( pos.purchased ) + "\t\t";
         text += price.format( pos.bought ) + "\t";
         text += price.format( pos.current ) + "\t";
         double change = ( pos.current - pos.bought ) / pos.bought;
         text += percent.format( change ) + "\n";
      }
      
      TextArea ta =  new TextArea( text );
      add( ta );
      setLayout( null );
      ta.setSize( this.getSize() );
      setVisible( true );
   }


   private void setLocalesAndFormatters ()
   {
      // Need to determine what locale (language and country) the
      // user has set.  Even if this returns the non-default locale,
      // it may be that the user has selected a locale we don't
      // support with this program.  A properly internationalized
      // program will have a language menu the user can use to select
      // a proper language (and country variant, such as French-Canadian
      // or French-France.  For now, this method constructs the requested
      // locale from the applet's parameters, and tries to create number
      // and date formatters from it.  Should this fail, we try to construct
      // formatters from the current locale.  If that fails also, we use
      // the standard ENGLISH locale.  Note the final setting of "locale"
      // is the locale used for the date, as this is needed later when
      // constructing a localized message containing a date.

      defaultLocale = getLocale();  // Get the current locale.

      String countryCode = getParameter( "Country" );
      if ( countryCode == null )
         countryCode = "";

      String languageCode = getParameter( "Language" );
      if ( languageCode == null )
         languageCode = defaultLocale.getLanguage();

      requestedLocale = new Locale( languageCode, countryCode );

      // With no arguments the following methods return formatter
      // objects for the default locale.  Other than currency, percent,
      // dates and times, and plain numbers, you must localize the values
      // yourself.  (For example, do we use inches or centimeters?)

      locale = requestedLocale;
      number = NumberFormat.getInstance( locale );
      if ( number == null )  // requested locale not supported, use default:
      {
         locale = defaultLocale;
         number = NumberFormat.getInstance( locale );
      }
      price = NumberFormat.getCurrencyInstance( locale );
      percent = NumberFormat.getPercentInstance( locale );

      // DateFormatters don't necessarily support the same locales as numbers:
      locale = requestedLocale;
      shortDate = DateFormat.getDateInstance( DateFormat.SHORT, locale );
      if ( shortDate == null )  // requested locale not supported, use default:
      {
         locale = defaultLocale;
         shortDate = DateFormat.getDateInstance( DateFormat.SHORT, locale );
      }
      fullTime = DateFormat.getTimeInstance( DateFormat.FULL, locale );

      try {
         TimeZone tz = TimeZone.getTimeZone( System.getProperty( "user.timezone" ) );
         shortDate.setTimeZone( tz );
         fullTime.setTimeZone( tz );
      } catch ( Exception ignored ) {}
   }


   static class Position
   {
      String symbol;              // Symbol (name) of the stock
      int shares;                 // Number of shares held
      Date purchased;             // When purchased
      double bought, current;     // Purchase and current price per share

      Position ( String symbol, int shares, Date purchased, double bought,
                 double current )
      {
         this.symbol = symbol;
         this.shares = shares;
         this.purchased = purchased;
         this.bought = bought;
         this.current = current;
      }
   }
}


Download Base (U.S. English) Properties file

PortValue = Portfolio value as of {0} on {1,date,long}:
Symbol = Symbol
Shares = Shares
BoughtOn = Bought on
At = At
Quote = Quote
Change = Change


Download French Properties file

PortValue = Valeur de brochure en date de {0} sur {1,date,long}:
Symbol = Symbole
Shares = Parts
BoughtOn = Acheté sur
At = À
Quote = Guillemet
Change = Différence


Download Spanish Properties file

PortValue = Valor de la lista en fecha {0} en {1,date,long}:
Symbol = Símbolo
Shares = Partes
BoughtOn = Comprado en
At = En
Quote = Cotización
Change = Diferencia