Writing Multi-Lingual Applications with Compiled JavaFX Script

The Happy New Year post broached the subject of writing internationalized applications in compiled JavaFX Script, as it covered the topic of locale-dependent formatting. This post will introduce you to the proposal for string literal translation in compiled JavaFX Script, which provides a simple and powerful mechanism to support the creation of multilingual applications. The current version of this proposal has been implemented in compiled JavaFX Script, so I'd like to use it to change yesterday's Bag the GridBag example into a multilingual application. The following screenshots show the UI after changing my computer's locale to French-France. Note: I took some French in school, but am by no means a French speaker, so if you have any suggestions for alternative translations, please post a comment.


Stringtranslation

Here is the dialog box with my information filled in:

Stringtranslation_dialog


The Modified Program

As you may have read in the proposal, to indicate that a given string is translatable, you prefix the string literal with two hash characters (##). Here is the CompiledGroupPanel.fx program from yesterday's post (renamed to StringTranslationExample.fx) with the strings that I chose to translate prefixed with ##.

/*
* StringTranslationExample.fx
*
* Developed 2008 by James L. Weaver (jim.weaver at lat-inc.com)
* to serve as a compiled JavaFX Script example of
* string literal translation.
*/

import javafx.ui.*;
import java.lang.System;

Frame {
var dlg:Dialog
var firstName:String
var lastName:String
var favoriteBand:String
var favoriteMovie:String
title: ##"Bag the GridBag"
width: 400
height: 250
visible: true
menubar:
MenuBar {
menus: [
Menu {
text: ##"Options"
items: [
MenuItem {
text: ##"Favorites..."
action:
function():Void {
dlg = Dialog {
modal: true
title: ##"Favorite Things"
visible: true
content:
GroupPanel {
var firstNameRow = Row { alignment: Alignment.BASELINE }
var lastNameRow = Row { alignment: Alignment.BASELINE }
var favoriteBandRow = Row { alignment: Alignment.BASELINE }
var favoriteMovieRow = Row { alignment: Alignment.BASELINE }
var labelsColumn = Column {
alignment: Alignment.TRAILING
}
var fieldsColumn = Column {
alignment: Alignment.LEADING
}
rows: [
firstNameRow,
lastNameRow,
favoriteBandRow,
favoriteMovieRow
]
columns: [
labelsColumn,
fieldsColumn
]
content: [
SimpleLabel {
row: firstNameRow
column: labelsColumn
text: ##"First Name:"
},
TextField {
row: firstNameRow
column: fieldsColumn
columns: 15
background: Color.WHITE
focusTraversalKeysEnabled: true
value: bind firstName with inverse
},
SimpleLabel {
row: lastNameRow
column: labelsColumn
text: ##"Last Name:"
},
TextField {
row: lastNameRow
column: fieldsColumn
columns: 15
background: Color.WHITE
focusTraversalKeysEnabled: true
value: bind lastName with inverse
},
SimpleLabel {
row: favoriteBandRow
column: labelsColumn
text: ##"Favorite Band:"
},
TextField {
row: favoriteBandRow
column: fieldsColumn
columns: 20
background: Color.WHITE
focusTraversalKeysEnabled: true
value: bind favoriteBand with inverse
},
SimpleLabel {
row: favoriteMovieRow
column: labelsColumn
text: ##"Favorite Movie:"
},
TextField {
row: favoriteMovieRow
column: fieldsColumn
columns: 25
background: Color.WHITE
value: bind favoriteMovie with inverse
}
]
}
buttons: [
Button {
text: ##"OK"
defaultButton: true
action:
function():Void {
System.out.println("First Name: {firstName}
Last Name: {lastName}
Favorite Band: {favoriteBand}
Favorite Movie: {favoriteMovie}");
dlg.hide();
}
}
]
};
}
}
]
}
]
}
onClose:
function():Void {
System.exit(0);
}
}

The FX Properties File

One feature that makes this mechanism very easy is that the string itself is the key for the key/value pair that supplies the translated string. Here is the FX properties file that I created for this example:

@charset "ISO-8859-1";
/*
* StringTranslationExample_fr.fxproperties
*
* Developed 2008 by James L. Weaver (jim.weaver at lat-inc.com)
* to serve as a compiled JavaFX Script example of
* string literal translation.
* Note: I don't speak much French, so please suggest corrections
*/

"Bag the GridBag" = "Mettez le GridBag dans un sac"
"Options" = "Options"
"Favorites..." = "Favoris..."
"Favorite Things" = "Choses Préférées"
"First Name:" = "Prénom:"
"Last Name:" = "Dernier Nom:"
"Favorite Band:" = "Bande Préférée:"
"Favorite Movie:" = "Film Préféré:"
"OK" = "OK"

Notice that the first line in the FX properties file contains the ISO-8859-1 character set. Also the name of an FX properties file is the same as the JavaFX Script program, with an underscore and the locale (_fr) appended to the name, and an extension of fxproperties. If French-France is the current locale, the FX properties file named StringTranslationExample_fr.fxproperties will be consulted. If there are no files that reflect the current locale, then the string literals from the program will be used.

JavaFX Script Boot Camp Announcement

As a heads-up, I will be offering a JavaFX Script 2.5 day "boot camp" on Wednesday, April 9 through Friday, April 11, 2008 (ending at noon) in Indianapolis, Indiana. This course is designed to get you quickly up to speed in JavaFX Script application development. A primary reference for this course is my JavaFX Script book, but the course has its own syllabus which includes material covered in the book as well as up to the minute developments in compiled JavaFX Script. Registration will open soon, and for this pilot class I am accepting 12 students. The cost of this pilot class will be 900 USD per student. Additional students from the same organization will be 600 USD. You'll need to bring your laptop computer with the latest versions of the JavaFX Script downloads (which I'll specify in more detail as the class date approaches). The prerequisite for the class will be the completion of a JavaFX Script programming assignment that I'll post soon to this weblog. I'm looking forward to teaching this class and hope that you can attend!

0 comments:

Post a Comment