S-JIS[2013-01-05] 変更履歴

Eclipseプラグイン 多言語対応

Eclipseプラグイン開発の多言語対応(国際化)について。


マニフェストファイルの文字列の外部化

マニフェストファイル(MANIFEST.MFplugin.xml)にはメニューやツールチップ等の文言を書くことがある。
この文字列を外部のプロパティーファイルに記述し、環境に応じて文言を切り替えることが出来る。


文字列の外部化

マニフェストファイル内にある文言で外部化が必要なものを自動的に抽出してプロパティーファイルを作ることが出来る。

  1. plugin.xml(またはMANIFEST.MF)を右クリックしてポップアップメニューを出し、「PDEツール(O)」→「ストリングの外部化(E)」をクリックして「ストリングの外部化」ダイアログを 開く。
  2. 対象ファイル(plugin.xmlとMANIFEST.MF)を選択して「次へ」。
  3. 生成されるbundle.propertiesの内容が表示されるので、「完了」。

すると、Eclipse3.7では「プロジェクト/OSGI-INF/l10n/bundle.properties」というファイルが作られる。

OSGI-INF/l10n/bundle.properties

#Properties file for com.example.eclipse.plugin.hello
actionSet.label = \u30B5\u30F3\u30D7\u30EB\u306E\u30A2\u30AF\u30B7\u30E7\u30F3\u30FB\u30BB\u30C3\u30C8
menu.label = \u30B5\u30F3\u30D7\u30EB\u30FB\u30E1\u30CB\u30E5\u30FC(&M)
action.label = \u30B5\u30F3\u30D7\u30EB\u30FB\u30A2\u30AF\u30B7\u30E7\u30F3(&S)
action.tooltip = Hello, Eclipse world
page.name = plugin-example1
page.name.0 = plugin-example1
Bundle-Name = Plugin-example1

プロパティーファイルなのでUnicodeエスケープされているが、実質は以下の様なもの。

#Properties file for com.example.eclipse.plugin.hello
actionSet.label = サンプルのアクション・セット
menu.label = サンプル・メニュー(&M)
action.label = サンプル・アクション(&S)
action.tooltip = Hello, Eclipse world
page.name = plugin-example1
page.name.0 = plugin-example1
Bundle-Name = Plugin-example1

マニフェストファイルでは、外部文字列を参照する箇所は「%プロパティー名」に置き換わっている。

META-INF/MANIFEST.MF:

〜
Bundle-Name: %Bundle-Name

plugin.xml:

<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.4"?>
<plugin>

   <extension
         point="org.eclipse.ui.actionSets">
      <actionSet
            label="%actionSet.label"
            visible="true"
            id="com.example.eclipse.plugin.Hello.actionSet">
         <menu
               label="%menu.label"
               id="sampleMenu">
            <separator
                  name="sampleGroup">
            </separator>
         </menu>
         <action
               label="%action.label"
               icon="icons/sample.gif"
               class="com.example.eclipse.plugin.hello.actions.HelloAction"
               tooltip="%action.tooltip"
               menubarPath="sampleMenu/sampleGroup"
               toolbarPath="sampleGroup"
               id="com.example.eclipse.plugin.hello.actions.HelloAction">
         </action>
      </actionSet>
   </extension>
   <extension
         point="org.eclipse.core.runtime.preferences">
      <initializer class="com.example.eclipse.plugin.hello.preference.HelloPreferenceInitializer" />
   </extension>
   <extension
         point="org.eclipse.ui.preferencePages">
      <page
            class="com.example.eclipse.plugin.hello.preference.HelloPreferencePage1"
            id="com.example.eclipse.plugin.hello.preference.page"
            name="%page.name">
      </page>
   </extension>
   <extension
         point="org.eclipse.ui.propertyPages">
      <page
            class="com.example.eclipse.plugin.hello.property.HelloProjectPropertyPage"
            id="com.example.eclipse.plugin.hello.property.page"
            name="%page.name.0">
         <enabledWhen>
            <instanceof value="org.eclipse.core.resources.IProject" />
         </enabledWhen>
      </page>
   </extension>

</plugin>

各国語対応プロパティーファイルの作成

bundle.propertiesに対し、各国の言語専用のプロパティーファイルを用意する。
日本語の場合はbundle_ja.propertiesというファイル名のファイルを(手動で)作ればよい。

OSGI-INF/l10n/bundle.properties:

#Properties file for com.example.eclipse.plugin.hello
actionSet.label = sample action set
menu.label = sample menu(&M)
action.label = sample action(&S)
action.tooltip = Hello, Eclipse world!
page.name = plugin-example1
page.name.0 = plugin-example1
Bundle-Name = Plugin-example1

OSGI-INF/l10n/bundle_ja.properties:

#Properties file for com.example.eclipse.plugin.hello
actionSet.label = \u30b5\u30f3\u30d7\u30eb\u306e\u30a2\u30af\u30b7\u30e7\u30f3\u30fb\u30bb\u30c3\u30c8
menu.label = \u30b5\u30f3\u30d7\u30eb\u30fb\u30e1\u30cb\u30e5\u30fc(&M)
action.label = \u30b5\u30f3\u30d7\u30eb\u30fb\u30a2\u30af\u30b7\u30e7\u30f3(&S)
action.tooltip = \u6700\u521d\u306e\u30b5\u30f3\u30d7\u30eb
page.name = \u30b5\u30f3\u30d7\u30eb\u30d7\u30e9\u30b0\u30a4\u30f31
page.name.0 = \u30b5\u30f3\u30d7\u30eb\u30d7\u30e9\u30b0\u30a4\u30f31
#Properties file for com.example.eclipse.plugin.hello
actionSet.label = サンプルのアクション・セット
menu.label = サンプル・メニュー(&M)
action.label = サンプル・アクション(&S)
action.tooltip = 最初のサンプル
page.name = サンプルプラグイン1
page.name.0 = サンプルプラグイン1

Javaソース内の文字列の外部化

マニフェストファイルの外部化と同様に、Javaソース内の文字列を外部化することが出来る。
(これはPDE(プラグイン開発)の機能ではなく、普通のJavaプロジェクトの機能)

  1. パッケージエクスプローラー上で対象のJavaソースを右クリックし、ポップアップメニューの「ソース(S)」→「ストリングの外部化(E)」をクリックして「ストリングの外部化」ダイアログを開く。
  2. 候補の文字列の中から、外部化しないものを「無視」する。(チェックをクリックして「×」印にするか、「無視」ボタンを押す)
    また、外部化するものに対し、置き換えられる定数名(キー)を指定する。(指定しないと連番になってしまう)
    (なお、外部化した後でも、再度同じJavaソースに同じ外部化の手順を行うことにより、定数名を変更することも出来る)
  3. 「次へ」で確認画面になるので、「完了」。

これで、選択したソースファイルが書き換えられ、同時に作られたMessages.javaのフィールドを参照するようになる。(Eclipse3.7の場合)

元のJavaソース:

public class HelloPreferenceInitializer extends AbstractPreferenceInitializer {

	public static final String KEY_TITLE = "HELLO_TITLE";
	public static final String KEY_MESSAGE = "HELLO_MESSAGE";

	@Override
	public void initializeDefaultPreferences() {
		IPreferenceStore store = Activator.getDefault().getPreferenceStore();
		store.setDefault(KEY_TITLE, "plugin-example1");
		store.setDefault(KEY_MESSAGE, "Hello, Eclipse world");
	}
}

外部化されたJavaソース:

public class HelloPreferenceInitializer extends AbstractPreferenceInitializer {

	public static final String KEY_TITLE = "HELLO_TITLE"; //$NON-NLS-1$
	public static final String KEY_MESSAGE = "HELLO_MESSAGE"; //$NON-NLS-1$

	@Override
	public void initializeDefaultPreferences() {
		IPreferenceStore store = Activator.getDefault().getPreferenceStore();
		store.setDefault(KEY_TITLE, Messages.HelloPreferenceInitializer_TITLE);
		store.setDefault(KEY_MESSAGE, Messages.HelloPreferenceInitializer_MESSAGE);
	}
}

KEY_TITLEとKEY_MESSAGEは独自に使っているキー名なので外部化対象から外した。(「$NON-NLS-1$」というコメントが追加されている)
"plugin-example1""Hello, Eclipse world"は外部化されたので、Messagesを参照するようになっている。

Messages.java(パッケージは元のJavaソースと同一):

import org.eclipse.osgi.util.NLS;

public class Messages extends NLS {
	private static final String BUNDLE_NAME = "com.example.eclipse.plugin.hello.preference.messages"; //$NON-NLS-1$
	public static String HelloPreferenceInitializer_TITLE;
	public static String HelloPreferenceInitializer_MESSAGE;
	static {
		// initialize resource bundle
		NLS.initializeMessages(BUNDLE_NAME, Messages.class);
	}

	private Messages() {
	}
}

静的初期化子によってフィールド(文字列)を初期化するようになっている。

messages.properties(パッケージ(配置場所)は元のJavaソースと同一):

HelloPreferenceInitializer_TITLE=plugin-example1
HelloPreferenceInitializer_MESSAGE=Hello, Eclipse world

messages_ja.propertiesを(手動で)作ることにより、日本語用のプロパティーを用意する。

messages_ja.properties(パッケージ(配置場所)はmessages.propertiesと同一):

HelloPreferenceInitializer_TITLE=\u30d7\u30e9\u30b0\u30a4\u30f3\u30b5\u30f3\u30d7\u30eb1
HelloPreferenceInitializer_MESSAGE=\u3053\u3093\u306b\u3061\u306f\u3001\u65e5\u8755\u4e16\u754c\uff01
HelloPreferenceInitializer_TITLE=プラグインサンプル1
HelloPreferenceInitializer_MESSAGE=こんにちは、日蝕世界!

多言語対応のテスト

テスト実行の実行時引数を変える事によって、特定の言語環境で実行することが出来る。

  1. メニューバーの「実行(R)」→「実行構成(N)」で、「実行構成」ダイアログを開く。
  2. 左側のツリーから対象のEclipseアプリケーションを選択する。
  3. 右側の「引数」タブを選択する。
  4. 「プログラムの引数(A)」で「-nl」を指定する。(デフォルトでは「${target.nl}」になっている)
    -os ${target.os} -ws ${target.ws} -arch ${target.arch} -nl ${target.nl} -consoleLog
    ↓
    -os ${target.os} -ws ${target.ws} -arch ${target.arch} -nl ja -consoleLog

「-nl」をjaとかenとかにすればよい。


Eclipseプラグインへ戻る / Eclipseへ戻る / 技術メモへ戻る
メールの送信先:ひしだま