tech fielders 2009/9/18 lt
DESCRIPTION
「Silverlight 3 アプリの国際化」のハマりどころTRANSCRIPT
「Silverlight 3 アプリの国際化のハマりどころ
⼋⽊照朗 / terurou株式会社コスモルート
DSTokai / FLOSS桜⼭ / DeLLa.JS / Python東海
1
⾃⼰紹介
2
⾃⼰紹介
• 株式会社コスモルート(名古屋の会社)に勤務– Enterprise RIA エンジニア(JavaScript、Silverlight)
– いちおう研究開発要員(WEB技術全般)
– たまにプロジェクトマネージャも
– 現在は Silverlight 3 開発案件のため、東京に常駐中
• 昨⽇から急にインフラ要員になりましたけどね…!
• DSTokai(東海地⽅のメタコミュニティ)管理⼈
3
⾃⼰紹介
⽐較的最近の活動
• Tech Fielders インタビュー #23– IronPython は、⽤途によって凄く便利な道具になる
http://www.microsoft.com/japan/powerpro/TF/interview/23_1.mspx
– 他の⽅と⽐較すると、明らかに⼀⼈だけ浮いている…
• PHP 逆引きレシピ(翔泳社)を執筆– PHP本の中では⼀番売れてるらしいです
4
さて、本題。
5
さて、本題。
Silverlight 3 アプリケーションを国際化する際の基本的な⼿順とハマリどころをまとめてきました。
6
さて、本題。
ライトニングトークのネタになる程度には⼿順がめんどくさくて、ハマります…。
7
さて、本題。
ちなみに今⽇のスライド、調⼦に乗って作ってたら37枚になりました。たぶん時間⾜りません。
8
国際化の⼿順
9
国際化の⼿順
1.プロジェクトファイルに対応する⾔語(カルチャ)を記述
2.アセンブリリソースファイル(.resx)を作成3.XAMLにリソース埋め込む4.【実⾏時】表⽰する⾔語(カルチャ)を指定
※基本的にはMSDNの⼿順の変形です。 Silverlight ベースのアプリケーションのローカライズ http://msdn.microsoft.com/ja-jp/library/cc838238%28VS.95%29.aspx
10
国際化の⼿順
⽇本語(ja-JP)と英語(en-US)に対応させる例をベースに解説していきます。
11
国際化の⼿順
1.プロジェクトファイルに対応する⾔語(カルチャ)を記述
プロジェクトファイル(.csproj, .vbproj)をお好みのテキストエディタで開いて、<SupportedCultures> に対応させたいカルチャ名を記述します。
Visual Studio 単独では設定不可能!
12
国際化の⼿順
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <ProductVersion>9.0.30729</ProductVersion> <SchemaVersion>2.0</SchemaVersion> <ProjectGuid>{87702BBC-F726-481B-AE35-18F56F6EEF4D}</ProjectGuid> <ProjectTypeGuids>{A1591282-1198-4647-A2B1-27E5FF5F6F3B};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids> <OutputType>Library</OutputType> <AppDesignerFolder>Properties</AppDesignerFolder> <RootNamespace>i18n</RootNamespace> <AssemblyName>i18n</AssemblyName> <TargetFrameworkVersion>v3.5</TargetFrameworkVersion> <SilverlightApplication>true</SilverlightApplication> <SupportedCultures>ja-JP;en-US</SupportedCultures> <XapOutputs>true</XapOutputs> <GenerateSilverlightManifest>true</GenerateSilverlightManifest> <XapFilename>i18n.xap</XapFilename> <SilverlightManifestTemplate>Properties\AppManifest.xml</SilverlightManifestTemplate> <SilverlightAppEntry>i18n.App</SilverlightAppEntry> <TestPageFileName>TestPage.html</TestPageFileName> <CreateTestPage>true</CreateTestPage> <ValidateXaml>true</ValidateXaml>
・・・
<SupportedCultures>ja-JP;en-US</SupportedCultures>
セミコロンで区切ると複数カルチャを指定できます。
13
国際化の⼿順
2.アセンブリリソースファイル(.resx)を作成
ソリューションエクスプローラの右クリックメニューから [追加] → [新しい項⽬] を選択し、
[アセンブリリソースファイル]を選択します。
14
国際化の⼿順
⽇本語(ja-JP)、英語(en-US)に対応する場合は以下のように3つのリソースファイルを作成します。
• Resource.resx(インバリアントカルチャ⽤)• Resource.ja-JP.resx• Resource.en-US.resx
※インバリアントカルチャとは特定の⾔語/地域に 依存していないカルチャのことです。
15
国際化の⼿順
Resouce.resx を開いて、アクセス修飾⼦ をPublic に変更します。(初期値は Internal )
Resouce.ja-JP.resx、Resouce.en-US.resx はコード⽣成なし のままにしておきます。
16
国際化の⼿順
3つのリソースファイルに置き換え⽂字列を同じ名前で追加します。
Resource.resx Resource.ja-JP.resx Resource.en-US.resx
17
国際化の⼿順
3.XAMLにリソース埋め込む
App.xaml の <App.Resouces> にリソースを埋め込んで、Bindingするだけなのですが…。
アセンブリリソースファイルの⾃動⽣成コードはなぜかコンストラクタが internal なので、そのままでは XAML に埋め込めません…。これはバグなのか仕様なのか…。
18
国際化の⼿順
• ⾃動⽣成コードのコンストラクタを public にする– リソースを変更する度にアクセス修飾⼦が internal に
戻されてしまう…。
• リソースをプロパティとするクラスを作る– MSDN の⼿順ではこちらの⼿順を紹介
– Binding の際のパス⽂字列が⻑くなる…。
解決するには以下のどちらかを⾏います。
19
国際化の⼿順
リソースをプロパティとするクラスを作る場合は、
こんな感じに定義します。
public class LocalizedResouce{ public LocalizedResouce() { }
private static Resource resource = new Resource();
public Resource Resource { get { return resource; } }}
20
国際化の⼿順
<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:resources="clr-namespace:i18n" x:Class="i18n.App"> <Application.Resources> <resources:Resource x:Key="Resource" /> </Application.Resources></Application>
あとは App.xaml にリソースを埋め込み、
⾃動⽣成コードを public にした場合 <resources:Resource x:Key="Resource" />
クラスを作った場合 <resources:Resource x:Key="LocalizedResource" />
21
国際化の⼿順
<TextBlock Text="{Binding NameLabel, Source={StaticResource Resouce}}" />
置き換え箇所で Binding していきます。
<TextBlock Text="{Binding Resource.NameLabel, Source={StaticResource LocalizedResouce}}" />
⾃動⽣成コードを public にした場合
クラスを作った場合
22
国際化の⼿順
CJK(中国語、⽇本語、韓国語)対応
<UserControl Language="ja-JP" />
CJKを適切に表⽰するためには更に設定が必要です。
ルート要素で以下のように指定します。
23
国際化の⼿順
4.【実⾏時】表⽰する⾔語(カルチャ)を指定
2つの指定⽅法があります。
• HTMLの<object>要素内で指定
• プログラム中で指定
24
国際化の⼿順
HTMLの<object>要素内でカルチャを指定
<object data="data:application/x-silverlight-2," type="application/x-silverlight-2"
width="100%" height="100%">
<param name="source" value="Sample.xap"/>
<param name="onError" value="onSilverlightError" />
<param name="background" value="white" />
<param name="minRuntimeVersion" value="3.0.40624.0" />
<param name="autoUpgrade" value="true" />
<param name="culture" value="ja-JP" />
<param name="uiculture" value="ja-JP" />
<a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=3.0.40624.0"
style="text-decoration:none">
<img src="http://go.microsoft.com/fwlink/?LinkId=108181"
alt="Microsoft Silverlight を入手" style="border-style:none"/>
</a>
</object>
<param name="culture" value="ja-JP" /><param name="uiculture" value="ja-JP" />
25
国際化の⼿順
プログラム中でカルチャを指定
private void Application_Startup(object sender, StartupEventArgs e)
{
Thread.CurrentThread.CurrentCulture = new CultureInfo("ja-JP");
Thread.CurrentThread.CurrentUICulture = new CultureInfo("ja-JP");
this.RootVisual = new MainPage();
}
Thread.CurrentThread.CurrentCulture
= new CultureInfo("ja-JP");
Thread.CurrentThread.CurrentUICulture
= new CultureInfo("ja-JP");
26
国際化の⼿順
以上で基本的な⼿順は完了です。
⾮常に簡単でしたね!
27
補⾜(注意するポイント)
28
補⾜(注意するポイント)
XP と Vista/7 ではデフォルトカルチャの
解決ルールが異なるため、環境によって挙動が
変わってしまう場合があります。
カルチャは明⽰的に初期値を指定しましょう。
1.カルチャ指定時の注意点
29
追記(2009/09/30) この部分の記載内容は誤りです。
補⾜(注意するポイント)
カルチャを何も指定せずにアプリを実⾏。
• XP → インバリアントカルチャ
• Vista/7 → OSのカルチャ設定に依存? ⽇本語版では ja-JP になった。
実際に遭遇したケース
30
追記(2009/09/30) この部分の記載内容は誤りです。
補⾜(注意するポイント)
また、ja-JP と en-US しか⽤意していないのに
fr-FR などを指定した場合も同じ挙動に…。
31
追記(2009/09/30)
補⾜(注意するポイント)
アセンブリリソースを⽤意していない
カルチャを表⽰⾔語として指定した場合、
読み込まれるカルチャが環境によって
異なる。(OSに依存している…?)
実際に遭遇したケース
32
追記(2009/09/30)
補⾜(注意するポイント)
Resource.rexs と Resource.ja-JP.resx の
2つを⽤意し、en-US を指定した場合
• XP → インバリアントカルチャ
• Vista/7 → ⽇本語版OSでは ja-JP
33
補⾜(注意するポイント)
普通に Binding すると、こういう⾔語切り替えUIは実装できない。
2.アセンブリリソースファイルの⾃動⽣成コードはINotifyPropertyChanged、DependencyPropertyではない。
34
補⾜(注意するポイント)
• Binding しない。プログラムで代⼊する。NameLabelTextBlock.Text = Resource.NameLabel.toString();
• ⾃動⽣成コードをラッッピングする。カルチャを切り替えたタイミングで INotifyPropertyChanged, DependencyProperty が動作するように。
解決策
35
補⾜(注意するポイント)
ちなみに私は全部 Binding に切り替えた後で、
気がついちゃったので、⾃動⽣成コードから
INotifyPropertyChanged な動的クラスを⽣成する
ジェネレータを作ることで解決しました。
36
まとめ
37
まとめ
開発者が意識することが多すぎです。
マイクロソフトさんには是⾮改善して頂きたい。
※これを⾔うために国際化なんて地味なネタでライトニングトークに
申し込んだとか、そうでないとか。
38
ご清聴ありがとうございました