Oracle9iAS Portal Developer Kit
How to Build a Multi Language Java Portlet using PDK-Java v2


This article shows you how to build a Java portlet using PDK-Java v2 that can be rendered in different languages. The language used in your portlet will depend upon on the language setting that has been chosen in the Portal that is displaying it. Once you have completed this article you will easily be able to write your portlets to support as many or as few languages as you want them to, or convert your existing portlet to support multiple languages. Once a portlet is written to support multiple languages, it is an easy process to plug in new languages as and when you want to.

ASSUMPTIONS

  1. You have followed through and understood the articles How To Build A Java Portlet Using PDK-Java v2.
  2. All of the assumptions in the above article apply here too.

INTERNATIONALIZING YOUR PORTLET

PROVIDING TRANSLATIONS FOR PORTLET CONTENT

In the previous article How To Build A Java Portlet Using PDK-Java v2 you created a portlet that printed a message on the screen. This message is only available in one language and the text to be displayed is hard-coded in to the portlet's renderer class. To make your portlets available in multiple languages you have to store such language dependent elements in their own classes, known as resource bundles. Below is the show mode renderer class, MyCustomRenderer from the previous article. The language dependent elements are shown in bold.

import java.io.*;
import oracle.portal.provider.v2.*;
import oracle.portal.provider.v2.render.*;
import oracle.portal.provider.v2.render.http.*;

public class MyCustomRenderer extends BaseManagedRenderer
{
public void renderBody(PortletRenderRequest pr) throws PortletException
{
try
{
// Get a writer for this renderer's output
PrintWriter out = pr.getWriter();

// Generate output and send to the writer
out.println("<b>Hi " + pr.getUser().getName() + "!</b><br>");
out.println("This output was generated by my very own renderer!");
        } 
catch (IOException ioe)
{
throw new PortletException(ioe);

}
}
}

Creating Resource Bundles

For each language you want your portlet to be available in, you will need a resource bundle. You will also need to create a 'default' resource bundle that will be used when there is no resource bundle corresponding to the language setting chosen in the portal.

Create A Default Resource Bundle

  1. First create your default resource bundle. Using your favourite text editor, create a Java class called MyProviderBundle, that extends ListResourceBundle from the java.util package. The class should contain a multi-dimensional array of objects, that holds key-value pairs representing each of the language dependent elements from MyCustomRenderer. This is demonstrated in the following code:

    import java.util.ListResourceBundle;

    public class MyProviderBundle extends ListResourceBundle
    {
    public static String HELLO_MSG = "FirstPortletHelloMessage";
    public static String INFO_MSG = "FirstPortletInfoMessage";

    public Object[][] getContents()
    {
    return contents;
    }
    static private final Object[][] contents =
    {
    {HELLO_MSG, "Hi"},
    {INFO_MSG, "This output was generated by my very own renderer!"}
    };
    }

  2. Save MyProviderBundle in the same place as MyCustomRenderer.
  3. Compile MyProviderBundle using the instructions outlined in How To Build A Java Portlet Using PDK-Java v2.

Creating Resource Bundles For Other Supported Languages

Now you must create a resource bundle class for each language you want your portlet to support. Each of these classes must be named the same as your default resource bundle class, but with a language code appended to the end. For example, if you want to support the French language, create a Java class named MyProviderBundle_fr. The language code fr is the same as the code that will be used by the locale object in the portal if the language setting is set to French ( for more information on Locales, see the JavaDoc for java.util.Locale). When you change the language setting in Oracle9iAS Portal, you change the value of the current locale object and therefore the locale object's language code. These language codes adhere to the ISO:639 codes for representation for names of languages.

  1. To create a French resource bundle, create a Java class named MyProviderBundle_fr, as described in the paragraph above.
  2. Using your default resource bundle as a template, replace the English language strings with their French equivalents. An example is given below:

    import java.util.ListResourceBundle;

    public class MyProviderBundle_fr extends ListResourceBundle
    {
    public Object[][] getContents()
    {
    return contents;
    }
    static private final Object[][] contents =
    {
    {MyProviderBundle.HELLO_MSG, "Bonjour"},
    {MyProviderBundle.INFO_MSG, "Ça rendement était produire près de mon véritable propre rendre!"}
        };
    }

  3. Save MyProviderBundle_fr in the same place as MyProviderBundle and MyCustomRenderer.
  4. Compile MyProviderBundle_fr using the instructions outlined in How To Build A Java Portlet Using PDK-Java v2.
  5. Repeat the above four steps for every language that you wish to create a resource bundle for, updating the class name with the appropriate language code and the message strings with their equivalent in the appropriate language.

Updating Your Renderer

To make use of the resource bundles you have just created you now need to update MyCustomRenderer, replacing the hard-coded messages with references that will pick up the messages at run time from the resource bundle that corresponds most closely with the locale object of the portal.

  1. Open up MyCustomRenderer and change it so that it contains the code listed below. Updates are shown in bold text.

    import java.io.*;
    import java.util.ResourceBundle; import oracle.portal.provider.v2.*; import oracle.portal.provider.v2.render.*; import oracle.portal.provider.v2.render.http.*; public class MyCustomRenderer extends BaseManagedRenderer { public void renderBody(PortletRenderRequest pr) throws PortletException { try { // Get a writer for this renderer's output PrintWriter out = pr.getWriter(); // Get a resource bundle object for the current language
    ResourceBundle b = ResourceBundle.getBundle("MyProviderBundle",pr.getLocale());


    // Generate output and send to the writer
    out.println("<b>" + b.getString(MyProviderBundle.HELLO_MSG) + " "
    + pr.getUser().getName() + "!</b><br>");
    out.println(b.getString(MyProviderBundle.INFO_MSG));
    } catch (IOException ioe) { throw new PortletException(ioe); } } }

  2. Save MyCustomRenderer.
  3. Compile MyCustomRenderer using the instructions outlined in How To Build A Java Portlet Using PDK-Java v2.

PROVIDING TRANSLATIONS FOR PORTLET ATTRIBUTES

In your provider's definition file, provider.xml, a number of attributes describing your portlet are defined such as the portlets name and description, these are used in places, for example in your portlet's title bar in show mode and so should be translated too. There are two different ways of providing these translations, which one you choose is up to you. Both of these methods are outlined below:

METHOD 1 - USING RESOURCE BUNDLES AT PROVIDER LEVEL

You can provide translations for your portlet attributes in your resource bundle(s), then specify that you want to use these resource bundle in provider.xml, specifying the keys you have used in your resource bundles. Using this method you can use the keys you want to, and as long as you use different keys for each corresponding attribute in your provider's various portlets you can have just one set of resource bundles that all of your provider's portlets can use.

Updating Your Resource Bundles

  1. Open your default resource bundle, MyProviderBundle.java.
  2. Update it so that it looks like the code example below. Additions to the existing class are shown in bold

    import java.util.ListResourceBundle;

    public class MyProviderBundle extends ListResourceBundle
    {
    public static String HELLO_MSG = "FirstPortletHelloMessage";
    public static String INFO_MSG = "FirstPortletInfoMessage";
    public static String PORTLET_NAME = "FirstPortletName";
    public static String PORTLET_TITLE = "FirstPortletTitle";
    public static String PORTLET_SHORT_TITLE = "FirstPortletShortTitle";
    public static String PORTLET_DESCRIPTION = "FirstPortletDescription";
    public static String TIMEOUT_MESSAGE = "FirstPortletTimeoutMessage";
    public Object[][] getContents() { return contents; } static private final Object[][] contents = { {HELLO_MSG, "Hi"}, {INFO_MSG, "This output was generated by my very own renderer!"}, {PORTLET_NAME, "MyFirstPortlet"},
    {PORTLET_TITLE, "My First Portlet"},
    {PORTLET_SHORT_TITLE, "MyFirstPortlet"},
    {PORTLET_DESCRIPTION, "My first ever portlet, using my own custom renderer"},
    {TIMEOUT_MESSAGE, "Timed out waiting for MyFirstPortlet"}
    }; }

  3. Save and close MyProviderBundle.java.
  4. Open MyProviderBundle_fr.java. Change it so that it contains the code listed below, again, updates are in bold text.

    import java.util.ListResourceBundle;

    public class MyProviderBundle_fr extends ListResourceBundle
    {
    public Object[][] getContents()
    {
    return contents;
    }
    static private final Object[][] contents =
    {
    {MyProviderBundle.HELLO_MSG, "Bonjour"},
    {MyProviderBundle.INFO_MSG, "Ça rendement était produire près de mon véritable propre rendre!"},
    {MyProviderBundle.PORTLET_NAME, "MonPremierPortlet"},
    {MyProviderBundle.PORTLET_TITLE, "Mon Premier Portlet"},
    {MyProviderBundle.PORTLET_SHORT_TITLE, "MonPremierPortlet"},
    {MyProviderBundle.PORTLET_DESCRIPTION, "Mon premièrement jamais portlet, l'utilisation de mon propre renderer de coutume"},
    {MyProviderBundle.TIMEOUT_MESSAGE, "Chronométré hors attendre MyFirstPortlet"}
    }; }

  5. Save and close MyProviderBundle_fr.java.
  6. Compile both MyProviderBundle.java and MyProviderBundle_fr.java using the instructions outlined in How To Build A Java Portlet Using PDK-Java v2.

Updating Provider.xml

  1. Open up the provider.xml file you created in How To Build A Java Portlet Using PDK-Java v2.
  2. Update the file as shown below, all additions are shown in bold.
    <?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?>
    <?providerDefinition version="3.1"?>
    <provider class="oracle.portal.provider.v2.DefaultProviderDefinition">
    <session>false</session>
    <portlet class="oracle.portal.provider.v2.DefaultPortletDefinition">
    <id>1</id>
    <resource>MyProviderBundle</resource>
    <nameKey>FirstPortletName</nameKey>
    <titleKey>FirstPortletTitle</titleKey>
    <ShortTitleKey>FirstPortletShortTitle</ShortTitleKey>
    <descriptionKey>FirstPortletDescription</descriptionKey>
    <timeout>10</timeout> <timeoutMessageKey>FirstPortletTimeoutMessage</timeoutMessageKey> <renderer class="oracle.portal.provider.v2.render.RenderManager"> <showPage class="MyCustomRenderer"/> </renderer> </portlet> </provider>
  3. Save and close provider.xml.

METHOD 2 - CREATING RESOURCE BUNDLES AT PORTLET LEVEL.

PDK Java-v2 defines a set of resource bundle keys that you can use for providing translations for your portlet attributes. Making use of these keys means that you don't have to specify the resource bundle keys you have used in your provider.xml file, as we did in the method 1 example. However, this does mean that you will have to provide a separate set of resource bundles for each portlet in your provider as the keys you use for each portlet will need to be the same, but their values will differ.

Updating Your Resource Bundles

  1. Open your default resource bundle, MyProviderBundle.java.
  2. Update it so that it looks like the code example below. Updates to the existing class are shown in bold

    import java.util.ListResourceBundle;
    import oracle.portal.provider.v2.PortletConstants;

    public class MyProviderBundle extends ListResourceBundle
    {
    public static String HELLO_MSG = "FirstPortletHelloMessage";
    public static String INFO_MSG = "FirstPortletInfoMessage";

    public Object[][] getContents()
    {
    return contents;
    }
    static private final Object[][] contents =
    {
    {HELLO_MSG, "Hi"},
    {INFO_MSG, "This output was generated by my very own renderer!"},
    {PortletConstants.NAME, "MyFirstPortlet"},
    {PortletConstants.TITLE, "My first portlet"},
    {PortletConstants.SHORTTITLE, "MyFirstPortlet"},
    {PortletConstants.DESCRIPTION, "My first ever portlet, using my own custom renderer"},
    {PortletConstants.TIMEOUTMSG, "Timed out waiting for MyFirstPortlet"}
    }; }

  3. Save and close MyProviderBundle.java.
  4. Open MyProviderBundle_fr.java. Change it so that it contains the code listed below, again, updates are in bold text.

    import java.util.ListResourceBundle;
    import oracle.portal.provider.v2.PortletConstants;

    public class MyProviderBundle_fr extends ListResourceBundle
    {
    public Object[][] getContents()
    {
    return contents;
    }
    static private final Object[][] contents =
    {
    {MyProviderBundle.HELLO_MSG, "Bonjour"},
    {MyProviderBundle.INFO_MSG, "Ça rendement était produire près de mon véritable propre rendre!"},
    {PortletConstants.NAME, "MonPremierPortlet"},
    {PortletConstants.TITLE, "Mon Premier Portlet"},
    {PortletConstants.SHORTTITLE, "MonPremierPortlet"},
    {PortletConstants.DESCRIPTION, "Mon premièrement jamais portlet, l'utilisation de mon propre renderer de coutume"},
    {PortletConstants.TIMEOUTMSG, "Chronométré hors attendre MyFirstPortlet"}
    }; }

  5. Save and close MyProviderBundle_fr.java.
  6. Compile both MyProviderBundle.java and MyProviderBundle_fr.java using the instructions outlined in How To Build A Java Portlet Using PDK-Java v2.

Updating Provider.xml

  1. Open up the provider.xml file you created in How To Build A Java Portlet Using PDK-Java v2.
  2. Update the file as shown below, all updates are shown in bold.
    <?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?>
    <?providerDefinition version="3.1"?>
    <provider class="oracle.portal.provider.v2.DefaultProviderDefinition">
    <session>false</session>
    <portlet class="oracle.portal.provider.v2.DefaultPortletDefinition">
    <id>1</id>
    <resource>MyProviderBundle</resource>
    <timeout>10</timeout>
    <renderer class="oracle.portal.provider.v2.render.RenderManager">
    <showPage class="MyCustomRenderer"/>
    </renderer>
    </portlet>
    </provider>
  3. Save and close provider.xml.

For more information on Java Internationalization see the Internationalization trail of the JavaTM Tutorial.

CONFIGURING OC4J

To update your portlet's provider and install that provider into OC4J, see the article Packaging and Deploying Your Provider, updating the provider with the files that you have changed and created in this tutorial.

VIEWING THE PORTLET

Once you have updated your provider and reinstalled it into OC4J, refresh the portal page containing your portlet. To see your resource bundles working, add the "Set Language" portlet to your page and try changing the language setting to French. Remember that the default resource bundle is English, and that selecting any other language that doesn't have a corresponding resource bundle will result in the portlet being displayed in English.


Revision History: