Silverlight 2.0 可以發展多語系的應用程式,只要透過資源檔即可做到 Localization 的能力,但是...它卻有一個討厭的缺陷,想知道是何種缺陷,就點進來看吧。
在 Silverlight 2.0 中發展多語系應用程式,其實就像在 Windows Forms,或像在 ASP.NET Web Form 那樣容易,只要新增對應語系的資源檔,即可做到即時套用多語系介面的能力,例如若要在 Silverlight 發展多國語系介面,你的專案可能會看起來像這樣:
Silverlight Project
-- Resources (資料夾)
-- StringTable.resx (預設語系,例如繁體中文)
-- StringTable.en-us.resx (英文)
-- StringTable.fr.resx (法文)
-- StringTable.zh-cn.resx (簡體中文)
然後依照 key-value 的方式去定義各語系的字串,即可完成語系文字部份的定義,然後,在 XAML 中導入資源檔,例如(下面的範例省略了一些內容,但省略的都是新增時就會有的):
<UserControl xmlns:Res="clr-namespace:MyProject.Resources">
<UserControl.Resources>
<Res:StringTable x:Name="StringTable"></Res:StringTable>
</UserControl.Resources>
<Grid>
<TextBlock Text="{Binding MyString, Source={StaticResource, StringTable}}" />
</Grid>
</UserControl>
即可顯示預設的語系字串中,以 MyString 為名稱的字串內容,若要顯示英文語系,則在程式中變更 Thread.CurrentThread.CurrentCulture 屬性值即可,例如:
using System.Globalization;
Thread.CurrentThread.CurrentUICulture = new Culture("en-us");
Thread.CurrentThread.CurrentCulture = new Culture("en-us");
若要在程式中讀資源字串,則可以用這個方法:
using System.Resources;
using System.Reflection;
ResourceManager rm = new ResourceManager("AverMediaFtpManagerUICtls.Resources.StringLibrary", Assembly.GetExecutingAssembly());
string result = rm.GetString(ResourceID);
rm = null;
return result;
一切看起來是多麼的美好,但是如果你修改到預設資源語系的字串檔,只要有新增 key 或刪除 key 的話,Silverlight Tools 會自動覆寫資源檔後置的程式碼檔案,這在 Windows Forms 其實沒有問題的,但在 Silverlight 中卻會造成無法載入資源的錯誤狀況(即字串都消失了)。
原因出在 StringTable.Designer.cs 這個檔案中(看你的資源檔怎麼命名的),把它打開來看會看到類似下列的程式碼:
public class StringTable
{
...
internal StringTable() // 這段就是問題所在
{
....
}
....
}
由於 StringTable 的建構式被設定為 internal,而 Silverlight Tools 預設又將資源檔建成另一個 DLL (像是 \bin\zh-tw\MyProject.resources.dll),internal 的設定會讓主程式無法載入資源 DLL,解決方式是將 internal 改成 public 就可以了:
public class StringTable
{
...
public StringTable() // 這樣就正常了
{
....
}
....
}
但讀者要切記的是,每次對資源檔中的字串做增刪時,這個程式宣告都會自動變回 internal,所以要記得將它改回來,否則在程式中所有套用資源的字串都會不見 ...
PS: 若讀者不知道如何做 Silverlight 2.0 的 Localization,可參考:
http://msdn.microsoft.com/zh-tw/library/cc838238(VS.95).aspx