Follow Techotopia on Twitter

On-line Guides
All Guides
eBook Store
iOS / Android
Linux for Beginners
Office Productivity
Linux Installation
Linux Security
Linux Utilities
Linux Virtualization
Linux Kernel
System/Network Admin
Programming
Scripting Languages
Development Tools
Web Development
GUI Toolkits/Desktop
Databases
Mail Systems
openSolaris
Eclipse Documentation
Techotopia.com
Virtuatopia.com
Answertopia.com

How To Guides
Virtualization
General System Admin
Linux Security
Linux Filesystems
Web Servers
Graphics & Desktop
PC Hardware
Windows
Problem Solutions
Privacy Policy

  




 

 

Eclipse RAP Development Guide
Previous Page Home Next Page

How to Internationalize a RAP application

Internationalization in RAP follows the same approach as RCP. However, due to the server-side, multi-user nature of RAP, a few adaptations are necessary. In the following, you will get a step-by-step guide to internationalize the simple Hello World application created in the getting-started chapter. For a more general introduction to internationalization in RCP, see [1].

Why does RAP internationalization differ from RCP?

In RAP we have to deal with different languages for different user sessions. Indeed, the language can also change between requests within the same session. Therefore, we cannot store language related information statically in Message classes as this is done in RCP. Instead, we must use a different instance of the Message class for every language.

Move translatable strings into *.properties files

In RCP, it's quite simple to externalize strings using the Externalize Strings wizard provided by JDT. Unfortunately, this wizard is not yet prepared to externalize strings the RAP way. You can probably benefit from the assistance of the Externalize Strings wizard anyway, but only partly. Until now, you are on your own here. We will now explain how to do it from scratch.

Let's start with the preparations. You probably know the resource bundle accessor classes (usually called Messages). We also use such a class, but instead of accessing a resource bundle, we use the RAP NLS facility to access nationalized strings. We create a class Messages in the package org.eclipse.rap.helloworld with the following initial content:


  public class Messages {
  
    private static final String BUNDLE_NAME
      = "org.eclipse.rap.helloworld.messages"; //$NON-NLS-1$
    
    private Messages() {
      // prevent instantiation
    }
    
    public static Messages get() {
      Class clazz = Messages.class;
      return ( Messages )RWT.NLS.getISO8859_1Encoded( BUNDLE_NAME, clazz );
    }
  }
  
The constant BUNDLE_NAME contains the name (without extension) of a properties file, that contains the mapping from keys to real strings. Note that in contrast to RCP, the class does not extend org.eclipse.osgi.util.NLS. Instances, which can be acquired through the factory method get(), contain fields that hold the translated strings.

In the next step, we create an empty properties file messages.properties in the same package. This properties file follows the conventions of standard ResourceBundle properties files. For each externalized string, there has to be a key entry in the properties file.

Now we are prepared to externalize strings. Let's start with the class HelloWorldView from the hello world example. The class contains one string we'd like to externalize in order to make it translatable:


  public void createPartControl( Composite parent ) {
    Label label = new Label ( parent, SWT.NONE );
    label.setText( "Hello RAP World" );
    label.setSize( 80, 20 );
  }
  
We change the string into the following code:

  public void createPartControl( Composite parent ) {
    Label label = new Label ( parent, SWT.NONE );
    label.setText( Messages.get().HelloWorldView_Message );
    label.setSize( 80, 20 );
  }
  
The key HelloWorldView_Message can be freely chosen, however, the RCP convention is to prefix it with the name of the class that uses it. Now we have to add that key to the Messages class:

  public class Messages {  
    ...
    public String HelloWorldView_Message;
    ...
  
and add a definition to the messages.properties file:

  HelloWorldView_Message = Hello RAP World
  
Note that in contrast to RCP, you must use fields instead of constants in the Messages class, as they are not shared over all user session and thus cannot be accessed in a static way in RAP.

Translate plug-in manifest

Extension definitions in the plug-in manifest file can also contain strings that are subject to internationalization. In order to get this working a few prerequisites are necessary:

  • check out the plug-in org.eclipse.rap.equinox.registry from the RAP CVS
  • also include the plug-in into your workspace.

Also the plug-in manifest file (plugin.xml) may contain translatable strings. Like in RCP, those stings are replaced by unique keys, prefixed with a % sign. The keys are then resolved in a plugin.properties file that resides in the root directory of the plug-in. For example, the internationalized version of the HelloWorld plug-in manifest file contains placeholders for the names of the view and the perspective.


   ...
   <extension
         point="org.eclipse.ui.views">
      <view
            id="org.eclipse.rap.helloworld.helloWorldView"
            class="org.eclipse.rap.helloworld.HelloWorldView"
            name="%helloWorldView_name">
      </view>
   </extension>
   
   <extension
         point="org.eclipse.ui.perspectives">
      <perspective
            id="org.eclipse.rap.helloworld.perspective"
            class="org.eclipse.rap.helloworld.Perspective"
            icon="icons/icon.gif"
            name="%perspective_name">
      </perspective>
   </extension>
  
And here's the plugin.properties:

  helloWorldView_name = Hello World View
  perspective_name = Hello World Perspective
  
To make this work, the OSGi manifest file (MANIFEST.MF) must contain the line:

  Bundle-Localization: plugin
  

Again, RAP needs a special treatment to support the internationalization of extensions because of it's server-side, multi-user nature. The problem is that the Equinox extension registry does the translation on startup and caches the results. In RAP, different sessions may require translations into different languages. In order to allow for this, we had to exploit the compatibility mechanism of the Equinox extension registry. As a side effect, the internationalization of Eclipse 3.2 plug-ins won't work.

To launch it from Eclipse, you need to include the plug-in org.eclipse.equinox.registry as a source plug-in into your workspace. Make sure that this plug-in is also included in the launch configuration (from the workspace, not from the target platform). We hope that we can remove these inconveniences once Equinox supports server-side applications with user sessions.

Create translations of your *.properties files

The last step of the internationalization is to actually translate. The translated strings are contained in localization properties files. These files may also reside in a fragment of its own, together with other localized resources. Localization properties files have a suffix that determines the language, optionally also the country, and a variant (refer to the java.util.Locale Javadoc for these concepts), all preceded by an underscore character. For example, to create a translation to Swiss German, create a copy of the messages.properties file and name it messages_de_CH.properties. Then you can start to translate the contained stings. Be aware that the translated properties files will very likely contain accented characters that are not included in the Latin-1 encoding (ISO-8859-1), which is expected by the RAP NLS support (as well as by the Java ResourceBundle mechanism). Those files can be converted using the native2ascii conversion utility, included with the Java SDK. Alternatively, RAP also allows for UTF-8 encoded properties files to ease the translation into non-latin languages. In this case, you have to change the call to RWT.NLS.getISO8859_1Encoded into RWT.NLS.getUTF8Encoded in the Messages class.

How does RAP select the language for a user session?

Web browsers allow users to set their preferred languages and they pass those preferences in an Accept-Language HTTP header with every request. RAP tries to select one of the requested languages in the preferred order and if this is not possible, it uses the default locale as fallback. The default locale can be set by adding the system property user.language to the launch configuration. If no matching properties file can be found, the default one (messages.properties) takes precedence.

References

  • 1. How to Internationalize your Eclipse Plug-In (Article on Eclipse.org)

  •  
     
      Published under the terms of the Eclipse Public License Version 1.0 ("EPL") Design by Interspire