ASP.Net(VB)での多言語化対応（ユーザによる切り替え）でやったことまとめ

#概要
VB.NETで作られたWebアプリケーションを多言語化対応した。
具体的には、クライアント側の設定言語でテキストの表示が切り替わるようにした。
調べても微妙な情報しか出ないことが多かったので備忘録。

**やったこと**

 - InitializeCulture()をつかった。
 - WebConfigでglobalizationを設定した。
 - データベースで日本語文字列を抽出している箇所にLangurage属性を追加した。
 - ログイン中のユーザ属性によって言語が切り替わるようにした。
 
**やらなかったこと**

 - `<body>`に対してlang属性の追加
<br>　　　今回のシステムだとページごとに設定が必要で、修正箇所が膨大になるので今回は見送り 
 - javascriptによってcssファイル読み込み参照を変更する処理
<br> 　　　別に悪くはないと思ったが、今回はサーバサイド(VB)でこの処理をした。

#はじめに
前提となる知識など
###クライアント側の言語設定
Windowsの場合、クライアント側の言語設定はブラウザの[インターネットオプション]→[言語]から設定できる。
または[Windowsの設定]→[時刻と言語]→[言語]から表示言語を選択できる
（優先する言語は上位に配置する）
###ISO 639-3
ISOで定められている言語コード。あらゆる言語をアルファベット3文字で表現する。
データベースのLanguage属性にはこちらを使用した。
日本語⇒JPN
英語⇒ENG
中国語⇒ZHO　等々...
Wikipediaに[一覧](https://ja.wikipedia.org/wiki/ISO_639-1%E3%82%B3%E3%83%BC%E3%83%89%E4%B8%80%E8%A6%A7)が載ってるので参考にすると良い。
###ロケールID(LCID)
ISOが国際基準で定められたものであるのに対し、LCIDはMicrosoft発の言語コード。
ISOよりちょっと細かい分類。
リソースファイルのファイル名やカルチャ取得などはこちらを使用した。
日本語⇒jp-jp
英語(U.S.)⇒en-us
中国語⇒zh-cn　等々...
Microsoftの公式ドキュメントに[一覧](https://msdn.microsoft.com/ja-jp/library/cc392381.aspx)が載っている。

#カルチャの設定
###WebConfig
クライアント側の言語設定によってWebページのカルチャを切り替える。
Web.configのSystem.web内に
```<globalization culture="Auto" uiCulture="Auto"/>```
と追加。以下簡単な説明。

**culture**
カレンダー等の表記が変わったりする。
何も設定しない場合、カルチャがサーバーによって決まるので、AWSのサーバでは英語圏になったりする。

**uiCulture**
リソースファイルの取得が切り替わる。
リソースファイル名は`[対象ページ名].aspx.[LCID].resx`としておけばよい。

Autoとすることでクライアント側の言語設定が使用される。
###各ページ
初期状態ではPageクラスの継承関係がPage→Codebehindとなっているが、
Pageクラスを継承したクラスCustomPageを用意し、
Page→CustomPage→Codebehindと継承する事によって全ページにInitializeCulture()を設定できる。

ログイン中のユーザの言語は`User.SelectLang`という名前のセッションに保持しているものとする。
各ページのCodeBehindで動いている.vbファイルに以下の関数を追加

```VB:CustomPage.vb
    Protected Overrides Sub InitializeCulture()
        If Me.Context.Session(Key.User) Is Nothing Then Exit Sub
        Dim UserCulture As String = CultureInfo.CurrentCulture.DisplayName
        If DirectCast(Me.Context.Session(Key.User), User).SelectLang = "JPN" Then UserCulture = "jp-JP"
        If DirectCast(Me.Context.Session(Key.User), User).SelectLang = "ZHO" Then UserCulture = "zh-CN"
        Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(UserCulture)
        Thread.CurrentThread.CurrentUICulture = New CultureInfo(UserCulture)
        MyBase.InitializeCulture()
    End Sub
```

MyBase.InitializeCulture()っていうのがページを表示する前に呼び出されるらしく、
これのオーバライド関数を用意することでページ表示前にカルチャを設定できる。

この関数を作る前にCustomPage.vbの上部で

```VB:CustomPage.vb
Imports System.Globalization
Imports System.Threading
```
を記述する必要がある。




#CSS(Font-Family)の設定
マスターページ使ってるならCSSの読み込みはマスタページだけでやってるかもしれない。
該当のページに以下を記述


```VB:Site.Master.vb
' 読み込むCSSファイルのパスを指定
Dim CssLangPath As String = ""
Select Case CultureInfo.CurrentCulture.ThreeLetterISOLanguageName.ToUpper
   Case "JPN" : CssLangPath = "../Style/jp-JP.css"
   Case "ENG" : CssLangPath = "../Style/en-US.css"
   Case "ZHO" : CssLangPath = "../Style/zh-CN.css"
End Select

' CSSファイル読み込み
   Dim css As New HtmlLink()
   css.Attributes.Add("rel", "stylesheet")
   css.Attributes.Add("type", "text/css")
   css.Attributes.Add("href", arg)
   Me.Page.Header.Controls.Add(css)
```

ちなみにここで読み込むCSSファイルは一行しか書いていない。(指定したい書体のみ)

```css:ja-JP.css
body {font-family: "Helvetica Neue",Arial,～～;}
```

#データベースの設定
データベースで画面に表示する文字列を取得している場合、カルチャを切り替えても日本語が取得される。

Languageカラムをプライマリキーとしてテーブルに付け足して、日本語にはJPN、英語にはENG、、、などと持たせた。
あとはSQLに`Language = 'JPN'など`を引き当てればOK。

#さいごに
ISO使わずにLCIDに統一するか、セッションにLCID持たせた方が改造が少なく済んだかもしれない。