|
|
||
John O'Conner's BlogApril 2004 ArchivesGroovy? Are you serious?Posted by joconner on April 27, 2004 at 12:02 AM | Permalink | Comments (12)You've seen the titles in the bookstore: Rock Gardening for Dummies, Needlepoint for Dummies, etc. If ever I'm tempted to pick one of them up, I quickly put it back on the shelf...and of course I could never let myself actually buy one regardless of the quality. OK, I know that I shouldn't judge a book by its cover (or title), but I just can't get past the name. Something about dummies just offends me, or maybe targets me just a bit too accurately on some subjects. Whatever the reason, I'm affected by the name, and yes, I'm a little ashamed to admit it. I wonder how many others are affected in the same way. Now for another secret...deep breath...I'm affected similarly by Groovy. You know...it's the latest Java-like scripting language that targets the Java platform. Yes, I think the platform could use a quick, easy scripting language. I've no problem with that idea. I don't even have an issue with Groovy, the actual tool/language/environment. But couldn't it have a different name? Groovy? I wonder how many people have just overlooked it so far because of its silly name? Is it irresponsible to overlook it for that reason? Yes, most definitely. But will some of you? Come on, be honest. Doesn't the name put you off just a little? Can serious professionals use something that sounds so silly? I18n How-to: ResourceBundle namingPosted by joconner on April 23, 2004 at 04:46 PM | Permalink | Comments (4)Two types of ResourceBundles are provided in the Java platform:
Starting were we left off, let's assume we have text strings in a bundle named Once you've loaded the bundle, you can retrieve the localizable text with res.getString("SOME_KEY"). However, how do you create a localized file, and how do you retrieve that bundle?
Create a localized bundle by translating all resource text and placing it in a separate resource bundle. If your original bundle is named GreetingResource.properties, your new bundle should be named GreetingResource_
The first two lowercase letters of the
When you load bundles, the JRE will search for appropriate bundle for your locale even if you do not specify a locale in the method. Be careful that you do not include the locale designation within the bundle name argument. For example,
If you want to specify a locale in the method, you must provide the locale as a second argument: In brief,
I18n How-to: Just get started!Posted by joconner on April 19, 2004 at 11:31 PM | Permalink | Comments (6)Developers and project managers make lots of excuses for not internationalizing an application. But it's easier to get started than you might imagine. Don't worry too much about all your difficult questions...you'll never begin. Just get started! Although there are several steps to creating a fully internationalized application, you can start by separating localizable text from your core business logic. You should place that text in a separate file, either a PropertyResourceBundle or a ListResourceBundle. Since a PropertyResourceBundle is so much more simple, I'll start with that. Let's pretend you're creating a simple application with a single button and a text field. When the user presses the button, the application will display a simple greeting. Your application might start like this:
package com.joconner.demo;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Greeting extends JFrame {
JButton btnGreeting = new JButton();
JTextField tfGreeting = new JTextField();
ResourceBundle res = GridBagLayout layout = new GridBagLayout();
public Greeting() {
try {
btnGreeting.setText("Show Greeting");
this.setTitle("I18n Demo");
btnGreeting.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
tfGreeting.setText("Hello, world!");
}
});
this.getContentPane().setLayout(layout);
this.getContentPane().add(btnGreeting, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0
,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
this.getContentPane().add(tfGreeting, new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0
,GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
catch(Exception ex) {
ex.printStackTrace();
}
}
public static void main(String[] args) {
Greeting app = new Greeting();
app.pack();
app.show();
}
}
To get started with internationalization, you first need to pull all the localizable text from the source code. For this app, it's simple; you just have 3 strings:
Put these strings in a PropertyResourceBundle. A PropertyResourceBundle is a simple text file with key/value pairs. Let's name our bundle "GreetingResources.properties" and we'll place it in the same package as our application's .java file. Proving 3 keys for each string, the property bundle will look like this: BTN_TEXT=Show Greeting! GREETING=Hello, world! TITLE=I18n Demo Now we have to touch up the original source code to use our new ResourceBundle. The modified code is below:
package com.joconner.demo;
import javax.swing.*;
import java.awt.*;
import java.util.ResourceBundle;
import java.awt.event.*;
public class Greeting extends JFrame {
JButton btnGreeting = new JButton();
JTextField tfGreeting = new JTextField();
ResourceBundle res = ResourceBundle.getBundle("com.joconner.demo.GreetingResources");
GridBagLayout layout = new GridBagLayout();
public Greeting() {
try {
String btnGreetingText = res.getString("BTN_TEXT");
btnGreeting.setText(btnGreetingText);
String title = res.getString("TITLE");
this.setTitle(title);
btnGreeting.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
String tfGreetingText = res.getString("GREETING");
tfGreeting.setText(tfGreetingText);
}
});
this.getContentPane().setLayout(layout);
this.getContentPane().add(btnGreeting, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0
,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
this.getContentPane().add(tfGreeting, new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0
,GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
catch(Exception ex) {
ex.printStackTrace();
}
}
public static void main(String[] args) {
Greeting app = new Greeting();
app.pack();
app.show();
}
}
You'll notice that we've done 3 new things:
Now believe it or not, you've started to internationalize your application with these easy steps! You can now localize the PropertyResourceBundle file into multiple languages, and the Java platform will find the localized bundle for you. In my next blog tip, I'll discuss how to name your bundles for multiple localizations of the same resources.
Want more information about resource bundles? Check this out: Unicode 4.0 support in J2SE 1.5Posted by joconner on April 16, 2004 at 01:08 AM | Permalink | Comments (1)The JavaTM platform has always supported Unicode, but the newest changes for Unicode 4.0 deserve special comment. Unicode itself has evolved to support over a million different code points or basic characters. The code point range is now 0x0000 through 0x10FFFF. Some major changes were required for J2SE 1.5 to provide support for all Unicode 4.0 code points. Since changes could potentially affect the Java language itself, the Java Community Process was used to determine how the platform should change. JSR 204 was created for that purpose. In summary, you'll find the following changes for Unicode 4.0 in Java 1.5:
Hey, that's a code unit, not a character! Java created the
New low-level APIs in Under the hood, high level APIs now work with surrogate pairs! And you'll not have to learn any new API to get the benefit either. For example, String.toUpperCase() will now work with surrogate pairs that represent supplementary characters. Regular expressions, collation APIs, and all the text rendering in the 2D APIs can now property process, sort, and display supplementary characters without any changes to your application. Of course, you'll need an appropriate font to see those new blocks of characters. No char is an island. The Java platform will begin to show a clear bias towards "char sequence" APIs instead of single char API. A char sequence is a char[], String, StringBuffer, or other structure that can hold 2 or more char values. Why the bias? Well, a char just isn't everything it used to be. Characters typically aren't standalone entities...they usually come in a group. Characters can be composed of multiple char values include combing marks(accents, tone marks, etc) or surrogate pairs that represent the new supplementary characters. Operations like uppercasing have always had the potential to produce multiple char values. For example, uppercasing the German 'ß' doesn't generate just one char; it creates "SS", which is a string, not a single char at all. So char sequences are definitely the right way to process characters. What's this mean to you? Well...it depends. If your applications have primarily used char based APIs, you may have considerable work to update to char sequenced based methods. However, if your application mostly uses Strings, StringBuffers, or char[]s either as method arguments or as return values, you may not have much to do at all. Most developers will be somewhere in the middle, so it will probably require a litte work from everyone to properly support all of the Unicode characters in your application. Regardless of where you are, you can be assured that the underlying support is there when you decide you need it. For more information, please see the following:
| ||
|
|