SlideShare a Scribd company logo
「Silverlight 3 アプリの国際化の
                       ハマりどころ

                            ⼋⽊照朗 / terurou
                           株式会社コスモルート
      DSTokai / FLOSS桜⼭ / DeLLa.JS / Python東海
⾃⼰紹介




  1
⾃⼰紹介


 • 株式会社コスモルート(名古屋の会社)に勤務
  – Enterprise RIA エンジニア(JavaScript、Silverlight)

  – いちおう研究開発要員(WEB技術全般)

  – たまにプロジェクトマネージャも

  – 現在は Silverlight 3 開発案件のため、東京に常駐中

       • 昨⽇から急にインフラ要員になりましたけどね…!

 • DSTokai(東海地⽅のメタコミュニティ)管理⼈


                       2
⾃⼰紹介


 ⽐較的最近の活動
 • Tech Fielders インタビュー #23
   – IronPython は、⽤途によって凄く便利な道具になる
    http://www.microsoft.com/japan/powerpro/TF/interview/23_1.mspx

   – 他の⽅と⽐較すると、明らかに⼀⼈だけ浮いている…

 • PHP 逆引きレシピ(翔泳社)を執筆
   – PHP本の中では⼀番売れてるらしいです




                                  3
さて、本題。




   4
さて、本題。




 Silverlight 3 アプリケーションを国際化する際の
 基本的な⼿順とハマリどころをまとめてきました。




                 5
さて、本題。




   ライトニングトークのネタになる程度には
   ⼿順がめんどくさくて、ハマります…。




            6
さて、本題。




 ちなみに今⽇のスライド、調⼦に乗って作ってたら
 37枚になりました。たぶん時間⾜りません。




             7
国際化の⼿順




   8
国際化の⼿順


 1.プロジェクトファイルに対応する⾔語
  (カルチャ)を記述
 2.アセンブリリソースファイル(.resx)を作成
 3.XAMLにリソース埋め込む
 4.【実⾏時】表⽰する⾔語(カルチャ)を指定


  ※基本的にはMSDNの⼿順の変形です。
   Silverlight ベースのアプリケーションのローカライズ
   http://msdn.microsoft.com/ja-jp/library/cc838238%28VS.95%29.aspx



                                   9
国際化の⼿順




   ⽇本語(ja-JP)と英語(en-US)に
   対応させる例をベースに解説していきます。




               10
国際化の⼿順


 1.プロジェクトファイルに対応する⾔語
   (カルチャ)を記述

  プロジェクトファイル(.csproj, .vbproj)を
  お好みのテキストエディタで開いて、
  <SupportedCultures> に対応させたい
  カルチャ名を記述します。


  Visual Studio 単独では設定不可能!

                  11
国際化の⼿順

 <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>
          <SupportedCultures>ja-JP;en-US</SupportedCultures>
     <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>PropertiesAppManifest.xml</SilverlightManifestTemplate>
     <SilverlightAppEntry>i18n.App</SilverlightAppEntry>
     <TestPageFileName>TestPage.html</TestPageFileName>
     <CreateTestPage>true</CreateTestPage>
     <ValidateXaml>true</ValidateXaml>
                   ・
                   ・
                   ・




                                                                 12
国際化の⼿順

 2.アセンブリリソースファイル(.resx)を作成

  ソリューションエクスプローラの
  右クリックメニューから
  [追加] → [新しい項⽬] を選択し、


  [アセンブリリソースファイル]を
  選択します。



               13
国際化の⼿順



⽇本語(ja-JP)、英語(en-US)に対応する場合は
以下のように3つのリソースファイルを作成します。

  • Resource.resx(インバリアントカルチャ⽤)
  • Resource.ja-JP.resx
  • Resource.en-US.resx

 ※インバリアントカルチャとは特定の⾔語/地域に
  依存していないカルチャのことです。
                      14
国際化の⼿順


 Resouce.resx を開いて、アクセス修飾⼦ を
 Public に変更します。(初期値は Internal )




  Resouce.ja-JP.resx、Resouce.en-US.resx は
  コード⽣成なし のままにしておきます。


                      15
国際化の⼿順


 3つのリソースファイルに置き換え⽂字列を
 同じ名前で追加します。

 Resource.resx   Resource.ja-JP.resx   Resource.en-US.resx




                            16
国際化の⼿順

 3.XAMLにリソース埋め込む

 App.xaml の <App.Resouces> にリソースを
 埋め込んで、Bindingするだけなのですが…。


 アセンブリリソースファイルの⾃動⽣成コードは
 なぜかコンストラクタが internal なので、
 そのままでは XAML に埋め込めません…。
 これはバグなのか仕様なのか…。

                 17
国際化の⼿順

 解決するには以下のどちらかを⾏います。

 • ⾃動⽣成コードのコンストラクタを public にする
  – リソースを変更する度にアクセス修飾⼦が internal に
   戻されてしまう…。

 • リソースをプロパティとするクラスを作る
  – MSDN の⼿順ではこちらの⼿順を紹介

  – Binding の際のパス⽂字列が⻑くなる…。



                 18
国際化の⼿順

 リソースをプロパティとするクラスを作る場合は、

 こんな感じに定義します。

  public class LocalizedResouce
  {
     public LocalizedResouce()
     {
     }

      private static Resource resource = new Resource();

      public Resource Resource { get { return resource; } }
  }



                                  19
国際化の⼿順


 あとは App.xaml にリソースを埋め込み、
  <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>


  ⾃動⽣成コードを public にした場合
     <resources:Resource x:Key="Resource" />

  クラスを作った場合
     <resources:Resource x:Key="LocalizedResource" />



                                           20
国際化の⼿順


 置き換え箇所で Binding していきます。

 ⾃動⽣成コードを public にした場合
  <TextBlock Text="{Binding NameLabel, Source={StaticResource Resouce}}" />


 クラスを作った場合
  <TextBlock Text="{Binding Resource.NameLabel,
                            Source={StaticResource LocalizedResouce}}" />




                                    21
国際化の⼿順


 CJK(中国語、⽇本語、韓国語)対応


 CJKを適切に表⽰するためには更に設定が必要です。

 ルート要素で以下のように指定します。

  <UserControl Language="ja-JP" />




                           22
国際化の⼿順

 4.【実⾏時】表⽰する⾔語(カルチャ)を指定

 2つの指定⽅法があります。

  • HTMLの<object>要素内で指定

  • プログラム中で指定




                23
国際化の⼿順

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="culture" value="ja-JP" />
     <param name="onError" value="onSilverlightError" />
     <param name="background" value="white" />
               <param name="uiculture" value="ja-JP" />
     <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>




                                                       24
国際化の⼿順

プログラム中でカルチャを指定

 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");



                                                     25
国際化の⼿順




     以上で基本的な⼿順は完了です。

     ⾮常に簡単でしたね!




            26
補⾜(注意するポイント)




     27
補⾜(注意するポイント)


 1.カルチャ指定時の注意点


  XP と Vista/7 ではデフォルトカルチャの

  解決ルールが異なるため、環境によって挙動が

  変わってしまう場合があります。

  カルチャは明⽰的に初期値を指定しましょう。




                28
補⾜(注意するポイント)

追記(2009/09/30) この部分の記載内容は誤りです。
  実際に遭遇したケース


  カルチャを何も指定せずにアプリを実⾏。

  • XP → インバリアントカルチャ

  • Vista/7 → OSのカルチャ設定に依存?
         ⽇本語版では ja-JP になった。



               29
補⾜(注意するポイント)

追記(2009/09/30) この部分の記載内容は誤りです。




  また、ja-JP と en-US しか⽤意していないのに

  fr-FR などを指定した場合も同じ挙動に…。




                30
補⾜(注意するポイント)

追記(2009/09/30)
  実際に遭遇したケース


   アセンブリリソースを⽤意していない

   カルチャを表⽰⾔語として指定した場合、

   読み込まれるカルチャが環境によって

   異なる。(OSに依存している…?)



                 31
補⾜(注意するポイント)

追記(2009/09/30)

   Resource.rexs と Resource.ja-JP.resx の

   2つを⽤意し、en-US を指定した場合

      • XP → インバリアントカルチャ

      • Vista/7 → ⽇本語版OSでは ja-JP




                     32
補⾜(注意するポイント)



 2.アセンブリリソースファイルの⾃動⽣成コードは
 INotifyPropertyChanged、DependencyProperty
 ではない。

  普通に Binding すると、こういう⾔語切り替え
  UIは実装できない。




                     33
補⾜(注意するポイント)



  解決策

  • Binding しない。プログラムで代⼊する。
   NameLabelTextBlock.Text = Resource.NameLabel.toString();

  • ⾃動⽣成コードをラッッピングする。
   カルチャを切り替えたタイミングで
   INotifyPropertyChanged, DependencyProperty が
   動作するように。



                             34
補⾜(注意するポイント)




 ちなみに私は全部 Binding に切り替えた後で、

 気がついちゃったので、⾃動⽣成コードから

 INotifyPropertyChanged な動的クラスを⽣成する

 ジェネレータを作ることで解決しました。




                 35
まとめ




 36
まとめ




 開発者が意識することが多すぎです。
 マイクロソフトさんには是⾮改善して頂きたい。

 ※これを⾔うために国際化なんて地味なネタでライトニングトークに
  申し込んだとか、そうでないとか。




                37
ご清聴ありがとうございました




      38

More Related Content

Tech Fielders 2009/9/18 LT