JMU JMU - Department of Computer Science
Help Tools
Lab: Gaining Experience with Localization/Internationalization


Instructions: Answer the following questions one at a time. After answering each question, check your answer (by clicking on the check-mark icon if it is available) before proceeding to the next question.

Getting Ready: Before going any further, you should:

  1. Setup your development environment.
  2. This lab is a simulation of a part of the process that is being used to create a product named Taxeze for the (hypothetical) company FreeMarket. The team is using an incremental process known as Scrum, which divides the work up into sprints.

    If you have not already done so, you must complete the lab on serialization before you can start this lab. If you have already completed the executable .jar files you should start with that version of the code instead.

  3. Read the sprintable stories.
  4. Read the course help page on Internationalization/Localization and/or the , lecture notes on the same topic.
  5. Briefly review the documentation for the ResourceBundle java.util.ResourceBundle and PropertyResourceBundle java.util.PropertyResourceBundle classes.

1. Tasks: The sprintable stories have been decomposed into the following tasks.
  1. Create a file named Strings_en_US.properties using the resource bundle format in the package taxeze.gui. It must contain all of the String constants in the TaxezeController and TaxezeWindow classes. The name of the constant must be the key and the value of the constant must be the value. Use an = to delimit the key and value. The value must not contain quote characters.
    CALCULATE = Calculate
    DATA_FILES = Data Files
    ERROR = Error
    ERROR_OPENING_FILE = Error Opening File
    EXIT = Exit
    FILE = File
    FILING_STATUS = Filing Status
    INVALID_FILE_TYPE = Invalid File Type
    MARGINAL_TAX_RATE = Marginal tax rate
    OPEN = Open
    READ = Read
    TAX = Tax
    TAXABLE_INCOME = Income
    UTILITIES = Utilities
    WRITE = Write
    
    Expand
  2. Remove the declarations/initializations of the String constants from both TaxezeController and TaxezeWindow.
  3. Add a static ResourceBundle final attribute named STRINGS (with package visibility) to the TaxezeController class.
      static final ResourceBundle STRINGS;
    
    Expand
  4. Add code that reads in the ResourceBundle into the attribute named STRINGS when the class is loaded.
      static final ResourceBundle STRINGS = ResourceBundle.getBundle("taxeze.gui.Strings");
    
    Expand
  5. Replace each String constant in TaxezeController with an appropriate call to STRINGS.getStrings().
        taxFilter = new FileNameExtensionFilter(STRINGS.getString("DATA_FILES"), "tax");
        txsFilter = new FileNameExtensionFilter(STRINGS.getString("DATA_FILES"), "txs");
    
        // ...
    
        if (ac.equals(STRINGS.getString("CALCULATE")))  calculate();
        else if (ac.equals(STRINGS.getString("EXIT")))  System.exit(0);
        else if (ac.equals(STRINGS.getString("OPEN")))  load(txsFilter, STRINGS.getString("OPEN"));
        else if (ac.equals(STRINGS.getString("READ")))  load(taxFilter, STRINGS.getString("READ"));
        else if (ac.equals(STRINGS.getString("WRITE")))  write();
    
    
        // ...
              JOptionPane.showMessageDialog(null, STRINGS.getString("ERROR_OPENING_FILE"), 
                  STRINGS.getString("ERROR"), JOptionPane.ERROR_MESSAGE);
    
           JOptionPane.showMessageDialog(null, STRINGS.getString("INVALID_FILE_TYPE"), 
                STRINGS.getString("ERROR"), JOptionPane.ERROR_MESSAGE);
        // ...
    
        fileChooser.setDialogTitle(STRINGS.getString("WRITE"));
    
        JOptionPane.showMessageDialog(null, STRINGS.getString("ERROR_OPENING_FILE"), STRINGS.getString("ERROR"), JOptionPane.ERROR_MESSAGE);
    
        JOptionPane.showMessageDialog(null, STRINGS.getString("INVALID_FILE_TYPE"), STRINGS.getString("ERROR"), JOptionPane.ERROR_MESSAGE);
    
    
    Expand
  6. Replace each String constant in TaxezeWindow with an appropriate call to STRINGS.getStrings(). (Hint: You may want to add an import static statement to TaxezeWindow.)
    import static taxeze.gui.TaxezeController.*;
    
    // ...
    
    calculateButton = createJButton("Calculate.png", STRINGS.getString("CALCULATE"));
    openButton    = createJButton("Open.png",    STRINGS.getString("OPEN"));
    
    // ...
    
        menu = new JMenu(STRINGS.getString("FILE"));
        {
          item = new JMenuItem(STRINGS.getString("OPEN"));
          item.addActionListener(controller);
          menu.add(item);
    
          item = new JMenuItem(STRINGS.getString("EXIT"));
          item.addActionListener(controller);
          menu.add(item);
        }
        menuBar.add(menu);
    
        menu = new JMenu(STRINGS.getString("UTILITIES"));
        {
          item = new JMenuItem(STRINGS.getString("READ"));
          item.addActionListener(controller);
          menu.add(item);
          
          item = new JMenuItem(STRINGS.getString("WRITE"));
          writeItem = item;
          writeItem.setEnabled(false);
          item.addActionListener(controller);
          menu.add(item);
        }
        menuBar.add(menu);
    
    // ...
    
        entryPanel.add(createTitledComponent(STRINGS.getString("TAXABLE_INCOME"), incomeField),      1,     0.0);
        entryPanel.add(createTitledComponent(STRINGS.getString("FILING_STATUS"), filingStatusField), 2,   100.0);
    
    Expand
  7. Conduct some system tests to make sure you haven't introduced any defects.
  8. Add a static Locale attribute (with package visibility) named LOCALE to the TaxezeController class and initialize it when it is loaded using the static getDefault() method in the Locale class.
      static final Locale         LOCALE  = Locale.getDefault();
    
    Expand
  9. Modify each call to String.format() so that the first parameter is now LOCALE.
          Currency currency = Currency.getInstance(LOCALE);
          results.add(String.format(LOCALE, STRINGS.getString("MARGINAL_TAX_RATE")+": %%%5.2f", marginalRate));
          results.add(String.format(LOCALE, STRINGS.getString("TAX")+": "+currency.getSymbol()+"%10.2f", taxes));
    
    Expand
  10. Conduct some system tests to make sure you haven't introduced any defects.
  11. Did you miss any String literals?
    Yes. Unfortunately we didn't use String constants everywhere.
    Expand
  12. What are the implications of your answer to the previous question?
    If there's any chance that a program will need to be localized/internationalized then there shouldn't be String literals interspersed throughout the code.
    Expand
  13. Create a file for another language. (If you speak another language, feel free to do the translation yourself. If not, a good approach is to use Google Translate.)
  14. Conduct system tests using the second language. Ensure that all of the acceptance criteria are satisfied.

Copyright 2021