Monday Jan 26, 2009

文字列リテラルのローカリゼーション記法がJavaFX Script言語リファレンスに。

JavaFX 1.0がリリースされてから既にしばらく経ちますが、ようやく"##"シンタックスについてのセクションをJavaFXランゲージリファレンスに追加できたのでblogでご紹介します。リファレンスの"String"タイプの章の"Localization of String Literal"の部分がそれです。基本的に以前紹介したプロポーザルのままです。

もし何かお気づきの点がありましたらコメントまで。

String literal localization in JavaFX Script Language Reference

It's been a while since JavaFX 1.0 was released. Now I finally had some time writing up a section in the JavaFX language reference about the "##" syntax. Take a look at the "String" type, and look for the section named "Localization of String Literal". It's basically based on the contents of the original syntax proposal.

If you have any comments, please leave them in this entry comment area. Thanks!

Tuesday Feb 12, 2008

JavaFX Scriptの「より簡単な」ローカリゼーション機能

前回のエントリーで、JavaFX Script言語の文字列リテラルの簡単なローカリゼーションの提案について説明しました。現時点でその実装が OpenJFXコンパイラリポジトリにコミットされたので、実際にどう動いているかをみてみることができます。例としてこのリポジトリにあるJavaFXBallsというデモを日本語にローカライズしてみました(このローカリゼーション自体もリポジトリに入っています)。

左下のボタンのテキスト、「ストップ」がソースコード上どうなっているかというと、ボタンのオブジェクトリテラルを作っているところのコードは:

text: bind if (not test._is_running) then ##"Start" else ##"Stop"

で、それに対応するJavaFXプロパティファイルのエントリーは:

"Stop" = "ストップ"

これだけ、です。

さて、今現在考えているのは、この機能をソースコードの文字列リテラルのローカリゼーションだけではなく、より一般的なローカリゼーション機能として使えないかということ。例えばJavaFXのランタイムライブラリとして、javafx.util.StringLocalizerというクラスを作り、その APIで、

package javafx.util;

public class StringLocalizer {

    public attribute key: String;
    public attribute locale: java.util.Locale;
    public attribute packageName: String;
    public attribute propertiesName: String;
    public attribute defaultString: String;

    // this is lazily bound to the above attributes.
    public function localizedString(): String;

    public static function associate(packageName: String,
                                     scriptFileName: String,
                                     properties: String): Void;
}

としたらどうでしょう。これらのAPIを使うことにより、次のようなことが可能になるはずです。

// ローカリゼーションオブジェクトの作成。
var localizer = StringLocalizer{ key: "Hello, World!" };

// "Hello, World!"のデフォルトロケール用の翻訳を出力。
System.out.println(localizer.localizedString());

// "Duke"のデフォルトロケール用の翻訳を出力。
localizer.key = "Duke";
System.out.println(localizer.localizedString());

// "Duke"のフランス語の翻訳を出力。
localizer.locale = Locale.FRENCH;
System.out.println(localizer.localizedString());

// "Duke"のフランス語の翻訳を、"foo/bar/MyBundle_fr.fxproperties"
// から探してきて出力。
localizer.packageName = "foo.bar";
localizer.propertiesName = "MyBundle";
System.out.println(localizer.localizedString());

また、"associate()"スタティック関数を使うことにより、JavaFX Scriptのソースファイル(またはJavaFXのパッケージごと)をJavaFXプロパティにマップすることができます。これにより文字列リテラルのローカリゼーションを探すプロパティファイルを指定できるようになります(デフォルトではソースのJavaFX Scriptファイルと同じ名前・場所のJavaFXプロパティファイルから探します)。このスタティック関数を使うことで、アプリケーションのプロパティファイルをどのようにパッケージするかを柔軟に指定できるようになるのです。一つのプロパティファイルで全アプリケーションのローカリゼーションを保持するか、ソースファイルごとにプロパティファイルを持つか、あるいはその中間か、など。

これはまだまだアイディアの段階で、実際にコミットするときにはもっと洗練されていると思いますが、この機能によって「より簡単に」JavaFX Scriptのローカリゼーションが可能になれば、と思っています。

\*Easier\* localization in JavaFX Script

In the last blog entry, I explained the proposal for an easy way to localize string literals in JavaFX Script language. Now the implementation for it is in the OpenJFX Compiler's repository, let's take a look at this feature in action. As an example, I localized the JavaFXBalls demo into Japanese (it's in the repository as well):

You see the text in the button at the bottom left corner reading "ストップ", which means "Stop". In this button's object literal creation, the source code looks like:

text: bind if (not test._is_running) then ##"Start" else ##"Stop"

And it's JavaFX properties file entry is simply:

"Stop" = "ストップ"

Now, we are planning to extend this string literal localization proposal into a generic string localization runtime library function. Suppose that there is a JavaFX runtime library class, e.g., javafx.util.StringLocalizer, and it has the following APIs:

package javafx.util;

public class StringLocalizer {

    public attribute key: String;
    public attribute locale: java.util.Locale;
    public attribute packageName: String;
    public attribute propertiesName: String;
    public attribute defaultString: String;

    // this is lazily bound to the above attributes.
    public function localizedString(): String;

    public static function associate(packageName: String, 
                                     scriptFileName: String,
                                     properties: String): Void;
}

With these utility APIs, you could do something like:

// Object creation
var localizer = StringLocalizer{ key: "Hello, World!" };

// This prints localized text for "Hello, World!" for the default locale
System.out.println(localizer.localizedString()); 

// This prints localized text for "Duke" for the default locale
localizer.key = "Duke";
System.out.println(localizer.localizedString()); 

// This prints localized text for "Duke" for the French locale
localizer.locale = Locale.FRENCH;
System.out.println(localizer.localizedString()); 

// This prints localized text for "Duke", from 
// the FX properties file "foo/bar/MyBundle_fr.fxproperties
localizer.packageName = "foo.bar";
localizer.propertiesName = "MyBundle";
System.out.println(localizer.localizedString()); 

Also, with the "associate()" static function, you could associate a JavaFX Script source file (or a javafx package) to a JavaFX properties file so that the string literal localization consults the associated JavaFX properties file for searching the localized text. (By default, the JavaFX properties file with the same name/location as the source file is searched). This static function would provide developers with the granularity of how the JavaFX properties files are packaged. You could provide one single JavaFX properties for your entire application, or one properties file for each source script file, or in between.

This is still a rough idea and needs to be refined. But I'd hope this would contribute to an \*easier\* localization in JavaFX.

Thursday Jan 10, 2008

JavaFX Scriptの簡単なローカリゼーション機能

またまたしばらく間が空いてしまいましたが、ここ最近はずっとJavaFX Scriptの国際化についての仕事をしています。JavaFX ScriptはJavaをベースにしたスクリプト言語なわけで、もちろんJavaに本来備わっている国際化に関する機能はすべて使えるわけですが、JavaFX ScriptからいちいちJavaの機能を呼び出して国際化関連のことを行うのはスクリプト言語らしくないし、さらにJava言語とJavaFX言語が混在してバグの元になりかねません。そこでJavaFX言語の仕様策定中ということもあり、その中に入れてしまいたいのがリテラル文字列を簡単にローカライズできる仕組みです。ある文字列をローカライズする場合、Javaでは普通、

    import java.util.ResourceBundle;

    static final String GREETINGS_KEY = "HELLO_WORLD";

    String greetings;
    try {
        ResourceBundle rb = ResourceBundle.getBundle("foo.bar.resources.My_Resource");
        greetings = rb.getString(GREETINGS_KEY);
    } catch (MissingResourceException mre) {
        greetings = "Hello, World!";
    }

の様に書くと思いますが、いま模索中なのがGNUのgettext()関数のように、引数となる文字列がそのままデフォルトの翻訳になるような仕組みです。上のコードをそのシンタックスで表記すると、

    var greetings = ##"Hello, World!";

たったの一行。シンプルでしょ?ここで"##"はリテラル文字列に働く単項演算子のような役割をします。この演算子がつくと実行時にこのリテラル文字列"Hello, World!"をキーとして適当な翻訳を探します。お気づきの方もいると思いますが、PropertyResourceBundleはホワイトスペース' 'をデリミタとして解釈するため、実は"Hello, World!"はキーとはなり得ないんです。そこで提案したいのがJavaFX Script用の新しいリソースバンドルのフォーマット。このフォーマットは単純に次のようなフォームを取ります。

    <JavaFX string literal> = <JavaFX string literal>
e.g.,
    "Hello, World!" = "こんにちは、世界!"

さらにボーナスとして考えているのは、このFX propertiesのデフォルトのエンコーディングを"UTF-8"にしようというもの。これで今まで頭を痛めてきた"ISO-8859-1" & native2asciiの呪縛から解放されるでしょう。他のエンコーディングを指定したい場合は、ファイルの頭にCSS形式のエンコーディング宣言(@charset "<IANA defined charset name>";)を入れてあげればそれに従うようにします。

ただこの方式には問題が一つあり、スクリプト内に同じリテラル文字列があり、それぞれ別の翻訳をさせたい場合(例えば2つの"File"というリテラル文字列をそれぞれ名詞、動詞として翻訳したい場合)に困ってしまいます。この問題を解決するためにオプションとしてキーを明示的に指定できるようにしました。#[FILE_NOUN]"File"のように、大括弧でくくって明示的なキーを指定します。

まあこんな所ですが、プロポーザル(英語です)とプロトタイプ実装をPlanet JFX wikiに置いてみたんで、どうぞおためしください。それとコメント、感想もよろしく!

Easy localization in JavaFX Script

I've been recently working on the internationalization of the JavaFX Script, which is a scripting language based on Java. Although all the Java internationalization features are definitely available from JavaFX Script program as it runs on top of a Java runtime, it would not be very scripting language like, and could be error prone because of the complexity of mixing Java and JavaFX. One of the features that I would like to have in the JavaFX Script is an easy way to localize strings in the JavaFX source. In Java, it's like:

    import java.util.ResourceBundle;

    static final String GREETINGS_KEY = "HELLO_WORLD";

    String greetings;
    try {
        ResourceBundle rb = ResourceBundle.getBundle("foo.bar.resources.My_Resource");
        greetings = rb.getString(GREETINGS_KEY);
    } catch (MissingResourceException mre) {
        greetings = "Hello, World!";
    }

Instead, we are thinking of a new easier way to localize strings in the JavaFX Script. It would be pretty much like GNU's gettext() function where the key itself becomes the default translation. So the above code would be written in JavaFX Script like:

    var greetings = ##"Hello, World!";

Yep, just one line. How simple is that! Here "##" works like a unary operator to the string literal, in which it looks for the proper localized string with the key of "Hello, World!". Some of you might notice that PropertyResourceBundle recognizes a white space ' ' as the delimiter, so "Hello, World!" cannot be a key in it. You are correct. So what we would like to provide is a new resource bundle format for the JavaFX script. It simply accepts the form of property as

    <JavaFX string literal> = <JavaFX string literal>
e.g.,
    "Hello, World!" = "こんにちは、世界!"

In addition as a bonus, this FX properties file's default encoding is "UTF-8" (yay!) and yet also accepts the CSS style encoding declaration (@charset "<IANA defined charset name>";)

There could possibly be an issue of ambiguous meaning for short words. For example, "File" could both mean "to file" and "file (as a noun)". To address this situation, you can optionally insert an explicit key which will be used for resource look up. This optional key can be specified within a pair of square brackets, e.g., ##[FILE_NOUN]"File".

I wrote a proposal and prototype implementation at Planet JFX wiki, so you might want to try it out. Comments are welcome as I'd like to know what you think!

About

naotoj

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today
News

No bookmarks in folder

Blogroll