.NET アプリのリソースの取得

ローカライズされたリソースを NET アプリで使用する場合は、既定カルチャまたはニュートラル カルチャ用のリソースをメイン アセンブリと共にパッケージ化し、アプリでサポートされている言語またはカルチャごとに個別のサテライト アセンブリを作成することが理想的です。 名前付きリソースには、次のセクションで説明する ResourceManager クラスを使用してアクセスすることができます。 目的のリソースをメイン アセンブリおよびサテライト アセンブリに埋め込まない場合でも、 .resources バイナリ ファイルには直接アクセスすることができます。詳細については、「.resources ファイルからのリソースの取得」セクションを参照してください。

アセンブリからのリソースの取得

ResourceManager クラスでは、実行時にリソースにアクセスすることができます。 文字列リソースを取得するには ResourceManager.GetString メソッドを使用し、文字列以外のリソースを取得するには ResourceManager.GetObject メソッドまたは ResourceManager.GetStream メソッドを使用します。 各メソッドには、次の 2 つのオーバーロードが含まれます。

  • 唯一のパラメーターがリソースの名前を含む文字列であるオーバーロード。 メソッドでは、現在のカルチャ用にそのリソースの取得を試みます。 詳細については、 GetString(String)メソッド、 GetObject(String)メソッド、および GetStream(String) メソッドを参照してください。

  • 2 つのパラメーターを持つオーバー ロード。1 つは、リソースの名前が含まれる文字列で、もう 1 つは、リソースが取得されるカルチャを表す CultureInfo オブジェクトです。 そのカルチャ用に設定されたリソースが見つからない場合、リソース マネージャーはフォールバック規則を使用して適切なリソースを取得します。 詳細については、 GetString(String, CultureInfo)メソッド、 GetObject(String, CultureInfo)メソッド、および GetStream(String, CultureInfo) メソッドを参照してください。

リソース マネージャーでは、アプリケーションでカルチャ固有のリソースを取得する方法を、リソース フォールバック プロセスを使用して制御します。 詳細については、リソースのパッケージ化と展開に関するページの「リソース フォールバック プロセス」セクションを参照してください。 ResourceManager オブジェクトをインスタンス化する方法については、 ResourceManager クラスに関するトピックの「ResourceManager オブジェクトのインスタンス化」セクションを参照してください。

文字列データの取得の例

次の例では、 GetString(String) メソッドを呼び出すことで、現在の UI カルチャの文字列リソースを取得します。 ここでは、英語 (米国) カルチャ用のニュートラル文字列リソースと、フランス語 (フランス) カルチャおよびロシア語 (ロシア) カルチャ用のローカライズされたリソースが対象となります。 次の英語 (米国) リソースは、Strings.txt という名前のファイルに入っています。

TimeHeader=The current time is

フランス語 (フランス) リソースは、Strings.fr-FR.txt という名前のファイルに入っています。

TimeHeader=L'heure actuelle est

ロシア語 (ロシア) リソースは、Strings.ru-RU.txt という名前のファイルに入っています。

TimeHeader=Текущее время —

この例のソース コード (C# バージョンのコードについては GetString.cs という名前のファイルに、Visual Basic バージョンのコードについては GetString.vb という名前のファイルに入っています) では、4 つのカルチャの名前を含む文字列配列が定義されます。具体的には、リソースが提供されている 3 つのカルチャと、スペイン語 (スペイン) カルチャです。 ランダムに 5 回実行されるループでは、これらのカルチャのいずれかを選択し、それを Thread.CurrentCulture プロパティと CultureInfo.CurrentUICulture プロパティに割り当てます。 次に、 GetString(String) メソッドを呼び出して、ローカライズされた文字列を取得します。この文字列は時刻と一緒に表示されます。

using System;
using System.Globalization;
using System.Resources;
using System.Threading;

[assembly: NeutralResourcesLanguageAttribute("en-US")]

public class Example
{
   public static void Main()
   {
      string[] cultureNames = { "en-US", "fr-FR", "ru-RU", "es-ES" };
      Random rnd = new Random();
      ResourceManager rm = new ResourceManager("Strings",
                               typeof(Example).Assembly);

      for (int ctr = 0; ctr <= cultureNames.Length; ctr++) {
         string cultureName = cultureNames[rnd.Next(0, cultureNames.Length)];
         CultureInfo culture = CultureInfo.CreateSpecificCulture(cultureName);
         Thread.CurrentThread.CurrentCulture = culture;
         Thread.CurrentThread.CurrentUICulture = culture;

         Console.WriteLine("Current culture: {0}", culture.NativeName);
         string timeString = rm.GetString("TimeHeader");
         Console.WriteLine("{0} {1:T}\n", timeString, DateTime.Now);
      }
   }
}
// The example displays output like the following:
//    Current culture: English (United States)
//    The current time is 9:34:18 AM
//
//    Current culture: Español (España, alfabetización internacional)
//    The current time is 9:34:18
//
//    Current culture: русский (Россия)
//    Текущее время — 9:34:18
//
//    Current culture: français (France)
//    L'heure actuelle est 09:34:18
//
//    Current culture: русский (Россия)
//    Текущее время — 9:34:18
Imports System.Globalization
Imports System.Resources
Imports System.Threading

<Assembly: NeutralResourcesLanguageAttribute("en-US")>

Module Example
    Public Sub Main()
        Dim cultureNames() As String = {"en-US", "fr-FR", "ru-RU", "es-ES"}
        Dim rnd As New Random()
        Dim rm As New ResourceManager("Strings", GetType(Example).Assembly)

        For ctr As Integer = 0 To cultureNames.Length
            Dim cultureName As String = cultureNames(rnd.Next(0, cultureNames.Length))
            Dim culture As CultureInfo = CultureInfo.CreateSpecificCulture(cultureName)
            Thread.CurrentThread.CurrentCulture = culture
            Thread.CurrentThread.CurrentUICulture = culture

            Console.WriteLine("Current culture: {0}", culture.NativeName)
            Dim timeString As String = rm.GetString("TimeHeader")
            Console.WriteLine("{0} {1:T}", timeString, Date.Now)
            Console.WriteLine()
        Next
    End Sub
End Module
' The example displays output similar to the following:
'    Current culture: English (United States)
'    The current time is 9:34:18 AM
'    
'    Current culture: Español (España, alfabetización internacional)
'    The current time is 9:34:18
'    
'    Current culture: русский (Россия)
'    Текущее время — 9:34:18
'    
'    Current culture: français (France)
'    L'heure actuelle est 09:34:18
'    
'    Current culture: русский (Россия)
'    Текущее время — 9:34:18

次のバッチ ( .bat) ファイルは、この例をコンパイルし、適切なディレクトリにサテライト アセンブリを生成します。 C# 言語とコンパイラの場合は、コマンドが提供されています。 Visual Basic の場合は、 cscvbcに変更し、 GetString.csGetString.vbに変更します。

resgen strings.txt
csc GetString.cs -resource:strings.resources

resgen strings.fr-FR.txt
md fr-FR
al -embed:strings.fr-FR.resources -culture:fr-FR -out:fr-FR\GetString.resources.dll

resgen strings.ru-RU.txt
md ru-RU
al -embed:strings.ru-RU.resources -culture:ru-RU -out:ru-RU\GetString.resources.dll

現在の UI カルチャがスペイン語 (スペイン) である場合、この例で表示されるのは英語リソースです。スペイン語のリソースは利用できず、この例の既定のカルチャは英語であるということが理由です。

オブジェクト データの取得の例

オブジェクト データを取得するには、 GetObject メソッドと GetStream メソッドを使用します。 プリミティブ データ型、シリアル化可能なオブジェクト、およびバイナリ形式で格納されているオブジェクト (画像など) が取得対象となります。

次の例では、 GetStream(String) メソッドを使用して、アプリの開始スプラッシュ ウィンドウで使用されるビットマップを取得します。 CreateResources.cs (C# の場合) または CreateResources.vb (Visual Basic の場合) に入っている次のソース コードは、シリアル化された画像を含む .resx ファイルを生成します。 この場合、画像は SplashScreen.jpg という名前のファイルから読み込まれます。ファイル名を変更して、独自の画像に置き換えることができます。

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Resources;

public class Example
{
   public static void Main()
   {
      Bitmap bmp = new Bitmap(@".\SplashScreen.jpg");
      MemoryStream imageStream = new MemoryStream();
      bmp.Save(imageStream, ImageFormat.Jpeg);

      ResXResourceWriter writer = new ResXResourceWriter("AppResources.resx");
      writer.AddResource("SplashScreen", imageStream);
      writer.Generate();
      writer.Close();
   }
}
Imports System.Drawing
Imports System.Drawing.Imaging
Imports System.IO
Imports System.Resources

Module Example
    Public Sub Main()
        Dim bmp As New Bitmap(".\SplashScreen.jpg")
        Dim imageStream As New MemoryStream()
        bmp.Save(imageStream, ImageFormat.Jpeg)

        Dim writer As New ResXResourceWriter("AppResources.resx")
        writer.AddResource("SplashScreen", imageStream)
        writer.Generate()
        writer.Close()
    End Sub
End Module

次のコードでは、リソースを取得して画像を PictureBox コントロール内に表示します。

using System;
using System.Drawing;
using System.IO;
using System.Resources;
using System.Windows.Forms;

public class Example
{
   public static void Main()
   {
      ResourceManager rm = new ResourceManager("AppResources", typeof(Example).Assembly);
      Bitmap screen = (Bitmap) Image.FromStream(rm.GetStream("SplashScreen"));

      Form frm = new Form();
      frm.Size = new Size(300, 300);

      PictureBox pic = new PictureBox();
      pic.Bounds = frm.RestoreBounds;
      pic.BorderStyle = BorderStyle.Fixed3D;
      pic.Image = screen;
      pic.SizeMode = PictureBoxSizeMode.StretchImage;

      frm.Controls.Add(pic);
      pic.Anchor = AnchorStyles.Top | AnchorStyles.Bottom |
                   AnchorStyles.Left | AnchorStyles.Right;

      frm.ShowDialog();
   }
}
Imports System.Drawing
Imports System.IO
Imports System.Resources
Imports System.Windows.Forms

Module Example
    Public Sub Main()
        Dim rm As New ResourceManager("AppResources", GetType(Example).Assembly)
        Dim screen As Bitmap = CType(Image.FromStream(rm.GetStream("SplashScreen")), Bitmap)

        Dim frm As New Form()
        frm.Size = new Size(300, 300)

        Dim pic As New PictureBox()
        pic.Bounds = frm.RestoreBounds
        pic.BorderStyle = BorderStyle.Fixed3D
        pic.Image = screen
        pic.SizeMode = PictureBoxSizeMode.StretchImage

        frm.Controls.Add(pic)
        pic.Anchor = AnchorStyles.Top Or AnchorStyles.Bottom Or
                     AnchorStyles.Left Or AnchorStyles.Right

        frm.ShowDialog()
    End Sub
End Module

次のバッチ ファイルを使用すると、C# の例をビルドできます。 Visual Basic の場合は、 cscvbcに変更し、さらにソース コード ファイルの拡張子を .cs から .vbに変更します。

csc CreateResources.cs
CreateResources

resgen AppResources.resx

csc GetStream.cs -resource:AppResources.resources

次の例では、 ResourceManager.GetObject(String) メソッドを使用して、カスタム オブジェクトを逆シリアル化します。 この例では、次に示す PersonTableという名前の構造体が定義されている UIElements.cs (Visual Basic の場合は UIElements.vb) という名前のソース コード ファイルを使用しています。 この構造体は、ローカライズされたテーブル列名を表示する一般的なテーブル表示ルーチンでの使用を目的としています。 PersonTable 構造体は、 SerializableAttribute 属性でマークされています。

using System;

[Serializable] public struct PersonTable
{
   public readonly int nColumns;
   public readonly string column1;
   public readonly string column2;
   public readonly string column3;
   public readonly int width1;
   public readonly int width2;
   public readonly int width3;

   public PersonTable(string column1, string column2, string column3,
                  int width1, int width2, int width3)
   {
      this.column1 = column1;
      this.column2 = column2;
      this.column3 = column3;
      this.width1 = width1;
      this.width2 = width2;
      this.width3 = width3;
      this.nColumns = typeof(PersonTable).GetFields().Length / 2;
   }
}
<Serializable> Public Structure PersonTable
    Public ReadOnly nColumns As Integer
    Public Readonly column1 As String
    Public ReadOnly column2 As String
    Public ReadOnly column3 As String
    Public ReadOnly width1 As Integer
    Public ReadOnly width2 As Integer
    Public ReadOnly width3 As Integer

    Public Sub New(column1 As String, column2 As String, column3 As String,
                   width1 As Integer, width2 As Integer, width3 As Integer)
        Me.column1 = column1
        Me.column2 = column2
        Me.column3 = column3
        Me.width1 = width1
        Me.width2 = width2
        Me.width3 = width3
        Me.nColumns = Me.GetType().GetFields().Count \ 2
    End Sub
End Structure

CreateResources.cs (Visual Basic の場合は CreateResources.vb) という名前のファイルに入っている次のコードは、UIResources.resx という名前の XML リソース ファイルを作成します。このリソース ファイルには、テーブルのタイトルに加えて、英語にローカライズされたアプリに関する情報を含む PersonTable オブジェクトが格納されます。

using System;
using System.Resources;

public class CreateResource
{
   public static void Main()
   {
      PersonTable table = new PersonTable("Name", "Employee Number",
                                          "Age", 30, 18, 5);
      ResXResourceWriter rr = new ResXResourceWriter(@".\UIResources.resx");
      rr.AddResource("TableName", "Employees of Acme Corporation");
      rr.AddResource("Employees", table);
      rr.Generate();
      rr.Close();
   }
}
Imports System.Resources

Module CreateResource
    Public Sub Main()
        Dim table As New PersonTable("Name", "Employee Number", "Age", 30, 18, 5)
        Dim rr As New ResXResourceWriter(".\UIResources.resx")
        rr.AddResource("TableName", "Employees of Acme Corporation")
        rr.AddResource("Employees", table)
        rr.Generate()
        rr.Close()
    End Sub
End Module

GetObject.cs (GetObject.vb) という名前のソース コード ファイルに含まれる次のコードは、リソースを取得し、コンソールに表示します。

using System;
using System.Resources;

[assembly: NeutralResourcesLanguageAttribute("en")]

public class Example
{
   public static void Main()
   {
      string fmtString = String.Empty;
      ResourceManager rm = new ResourceManager("UIResources", typeof(Example).Assembly);
      string title = rm.GetString("TableName");
      PersonTable tableInfo = (PersonTable) rm.GetObject("Employees");

      if (! String.IsNullOrEmpty(title)) {
         fmtString = "{0," + ((Console.WindowWidth + title.Length) / 2).ToString() + "}";
         Console.WriteLine(fmtString, title);
         Console.WriteLine();
      }

      for (int ctr = 1; ctr <= tableInfo.nColumns; ctr++) {
         string columnName = "column"  + ctr.ToString();
         string widthName = "width" + ctr.ToString();
         string value = tableInfo.GetType().GetField(columnName).GetValue(tableInfo).ToString();
         int width = (int) tableInfo.GetType().GetField(widthName).GetValue(tableInfo);
         fmtString = "{0,-" + width.ToString() + "}";
         Console.Write(fmtString, value);
      }
      Console.WriteLine();
   }
}
Imports System.Resources

<Assembly: NeutralResourcesLanguageAttribute("en")>

Module Example
    Public Sub Main()
        Dim fmtString As String = String.Empty
        Dim rm As New ResourceManager("UIResources", GetType(Example).Assembly)
        Dim title As String = rm.GetString("TableName")
        Dim tableInfo As PersonTable = DirectCast(rm.GetObject("Employees"), PersonTable)

        If Not String.IsNullOrEmpty(title) Then
            fmtString = "{0," + ((Console.WindowWidth + title.Length) \ 2).ToString() + "}"
            Console.WriteLine(fmtString, title)
            Console.WriteLine()
        End If

        For ctr As Integer = 1 To tableInfo.nColumns
            Dim columnName As String = "column" + ctr.ToString()
            Dim widthName As String = "width" + ctr.ToString()
            Dim value As String = CStr(tableInfo.GetType().GetField(columnName).GetValue(tableInfo))
            Dim width As Integer = CInt(tableInfo.GetType().GetField(widthName).GetValue(tableInfo))
            fmtString = "{0,-" + width.ToString() + "}"
            Console.Write(fmtString, value)
        Next
        Console.WriteLine()
    End Sub
End Module

次のバッチ ファイルを実行することで、必要なリソース ファイルとアセンブリをビルドし、アプリケーションを実行することができます。 /r 構造体に関する情報にアクセスできるように、 PersonTable オプションを使用して Resgen.exe を指定し、UIElements.dll への参照を含める必要があります。 C# を使用している場合は、 vbc コンパイラ名を cscに置換し、 .vb 拡張子を .csに置換します。

vbc -t:library UIElements.vb
vbc CreateResources.vb -r:UIElements.dll
CreateResources

resgen UIResources.resx  -r:UIElements.dll
vbc GetObject.vb -r:UIElements.dll -resource:UIResources.resources

GetObject.exe

サテライト アセンブリのバージョン サポート

既定では、 ResourceManager オブジェクトは、要求されたリソースを取得するとき、メイン アセンブリのバージョン番号と一致するバージョン番号を持つサテライト アセンブリを検索します。 アプリを展開したら、メイン アセンブリまたは特定のリソース サテライト アセンブリを更新することをお勧めします。 .NET Framework では、メイン アセンブリとサテライト アセンブリのバージョン管理をサポートしています。

メイン アセンブリのバージョン管理のサポートは、SatelliteContractVersionAttribute 属性で指定されます。 この属性をアプリのメイン アセンブリで指定すると、サテライト アセンブリを更新しなくてもメイン アセンブリの更新および再展開を行うことができます。 メイン アセンブリを更新すると、メイン アセンブリのバージョン番号はインクリメントされますが、サテライト コントラクト バージョン番号はそのままで変わりありません。 リソース マネージャーは、要求されたリソースを取得するとき、この属性で指定されたサテライト アセンブリのバージョンを読み込みます。

発行者ポリシー アセンブリでは、サテライト アセンブリのバージョン管理をサポートしています。 メイン アセンブリを更新することなく、サテライト アセンブリの更新および再展開を行うことができます。 サテライト アセンブリを更新すると、そのバージョン番号はインクリメントされ、発行者ポリシー アセンブリと一緒に出力されます。 発行者ポリシー アセンブリ内では、新しいサテライト アセンブリが旧バージョンと互換性があるように指定します。 リソース マネージャーでは、 SatelliteContractVersionAttribute 属性を使用してサテライト アセンブリのバージョンを特定しますが、アセンブリ ローダーは、発行元ポリシーで指定されたサテライト アセンブリのバージョンにバインドします。 発行者ポリシー アセンブリの詳細については、発行者ポリシー ファイルの作成に関するページを参照してください。

アセンブリの完全なバージョン管理サポートを有効にするには、 グローバル アセンブリ キャッシュ 内に厳密な名前を付けたアセンブリを展開し、アプリケーション ディレクトリ内に厳密な名前を持たないアセンブリを展開することをお勧めします。 厳密な名前を付けたアセンブリをアプリケーション ディレクトリに展開すると、更新時に、サテライト アセンブリのバージョン番号をインクリメントできなくなります。 そのため、インプレース更新を実行する必要があります。インプレース更新では、既存のコードを更新されたコードに置き換えて、同じバージョン番号を維持します。 たとえば、サテライト アセンブリのバージョン 1.0.0.0 を、完全に指定されたアセンブリ名 "myApp.resources, Version=1.0.0.0, Culture=de, PublicKeyToken=b03f5f11d50a3a" で更新する場合は、完全に指定された同じアセンブリ名 "myApp.resources, Version=1.0.0.0, Culture=de, PublicKeyToken=b03f5f11d50a3a" でコンパイルされた更新済みの myApp.resources.dll で上書きします。 サテライト アセンブリ ファイルに対してインプレース更新を使用すると、サテライト アセンブリのバージョンをアプリケーションで正確に特定するのが難しくなります。

アセンブリのバージョン管理の詳細については、「アセンブリのバージョン管理」と「ランタイムがアセンブリを検索する方法」を参照してください。

.resources ファイルからのリソースの取得

サテライト アセンブリにリソースを展開しないように選択した場合でも、 ResourceManager オブジェクトを使用して、.resources ファイルからリソースに直接アクセスすることができます。 そのためには、.resources ファイルを正しく展開する必要があります。 次に、 ResourceManager.CreateFileBasedResourceManager メソッドを使用して ResourceManager オブジェクトをインスタンス化し、スタンドアロンの .resources ファイルを含むディレクトリを指定します。

.resources ファイルの展開

アプリケーション アセンブリとサテライト アセンブリに .resources ファイルを埋め込むと、各サテライト アセンブリのファイル名は同じになりますが、各サテライト アセンブリが配置される場所はそれぞれのカルチャを反映するサブディレクトリとなります。 これに対して、.resources ファイルからリソースに直接アクセスする場合は、すべての .resources ファイルを単一のディレクトリ (通常は、アプリケーション ディレクトリのサブディレクトリ) に配置することができます。 アプリの既定の .resources ファイルの名前は、ルート名のみで構成され、カルチャ名はありません (たとえば、strings.resources)。 ローカライズされた各カルチャのリソースが格納されるファイルの名前は、ルート名の後にカルチャが続きます (たとえば、strings.ja.resources または strings.de-DE.resources)。

次の図では、ディレクトリ構造内のどこにリソース ファイルを配置する必要があるかを示しています。 また、.resource ファイルの名前付け規則が与えられます。

アプリケーションのメイン ディレクトリを示す図。

リソース マネージャーの使用

リソースを作成し、それを適切なディレクトリに配置したら、 ResourceManager メソッドを呼び出して、リソースを使用する CreateFileBasedResourceManager(String, String, Type) オブジェクトを作成します。 最初のパラメーターでは、アプリの既定の .resources ファイルのルート名を指定します (前のセクションの例では、"strings" でした)。 2 番目のパラメーターでは、リソースの場所を指定します (前の例では "Resources")。 3 番目のパラメーターでは、使用する ResourceSet 実装を指定します。 3 番目のパラメーターが nullである場合、既定のランタイム ResourceSet が使用されます。

注意

ASP.NET アプリを展開する場合には、スタンドアロン .resources ファイルを使用しないでください。 このファイルを使用すると、ロックの問題が生じ、XCOPY 展開が破損する恐れがあります。 ASP.NET リソースの展開先はサテライト アセンブリにすることをお勧めします。 詳細については、「 ASP.NET Web Page Resources Overview」を参照してください。

ResourceManager オブジェクトをインスタンス化したら、前述したように GetStringメソッド、 GetObjectメソッド、 GetStream メソッドを使用してリソースを取得します。 ただし、.resources ファイルからリソースを直接取得することは、アセンブリから埋め込みリソースを取得することとは異なります。 .resources ファイルからリソースを取得する場合、 GetString(String)メソッド、 GetObject(String)メソッド、および GetStream(String) メソッドは、現在のカルチャに関係なく、常に既定のカルチャのリソースを取得します。 アプリケーションの現在のカルチャまたは特定のカルチャのリソースを取得するには、GetString(String, CultureInfo) メソッド、GetObject(String, CultureInfo) メソッド、または GetStream(String, CultureInfo) メソッドを呼び出して、どのカルチャのリソースを取得するのかを指定する必要があります。 現在のカルチャのリソースを取得するには、 CultureInfo.CurrentCulture プロパティの値を culture 引数として指定します。 リソース マネージャーは、 cultureのリソースを取得できない場合、標準的なリソース フォールバック規則を使用して適切なリソースを取得します。

使用例

次の例では、リソース マネージャーが .resources ファイルからリソースを直接取得する方法を示しています。 この例は、英語 (米国) カルチャ、フランス語 (フランス) カルチャ、ロシア語 (ロシア) カルチャ用の 3 つのテキスト ベースのリソース ファイルで構成されます。 英語 (米国) は、この例の既定のカルチャです。 このリソースは、次の Strings.txt という名前のファイルに格納されています。

Greeting=Hello
Prompt=What is your name?

フランス語 (フランス) カルチャのリソースは、次の Strings.fr-FR.txt という名前のファイルに格納されています。

Greeting=Bon jour
Prompt=Comment vous appelez-vous?

ロシア語 (ロシア) カルチャのリソースは、次の Strings.ru-RU.txt という名前のファイルに格納されています。

Greeting=Здравствуйте
Prompt=Как вас зовут?

この例のソース コードを次に示します。 この例では、英語 (米国)、英語 (カナダ)、フランス語 (フランス)、およびロシア語 (ロシア) カルチャ用の CultureInfo オブジェクトをインスタンス化し、それぞれを現在のカルチャとします。 次に、 ResourceManager.GetString(String, CultureInfo) メソッドで、 CultureInfo.CurrentCulture プロパティの値を culture 引数として指定して、カルチャ固有の適切なリソースを取得します。

using System;
using System.Globalization;
using System.Resources;
using System.Threading;

[assembly: NeutralResourcesLanguage("en-US")]

public class Example
{
   public static void Main()
   {
      string[] cultureNames = { "en-US", "en-CA", "ru-RU", "fr-FR" };
      ResourceManager rm = ResourceManager.CreateFileBasedResourceManager("Strings", "Resources", null);

      foreach (var cultureName in cultureNames) {
         Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(cultureName);
         string greeting = rm.GetString("Greeting", CultureInfo.CurrentCulture);
         Console.WriteLine("\n{0}!", greeting);
         Console.Write(rm.GetString("Prompt", CultureInfo.CurrentCulture));
         string name = Console.ReadLine();
         if (! String.IsNullOrEmpty(name))
            Console.WriteLine("{0}, {1}!", greeting, name);
      }
      Console.WriteLine();
   }
}
// The example displays output like the following:
//       Hello!
//       What is your name? Dakota
//       Hello, Dakota!
//
//       Hello!
//       What is your name? Koani
//       Hello, Koani!
//
//       Здравствуйте!
//       Как вас зовут?Samuel
//       Здравствуйте, Samuel!
//
//       Bon jour!
//       Comment vous appelez-vous?Yiska
//       Bon jour, Yiska!
Imports System.Globalization
Imports System.Resources
Imports System.Threading

<Assembly: NeutralResourcesLanguageAttribute("en-US")>

Module Example
    Public Sub Main()
        Dim cultureNames() As String = {"en-US", "en-CA", "ru-RU", "fr-FR"}
        Dim rm As ResourceManager = ResourceManager.CreateFileBasedResourceManager("Strings", "Resources", Nothing)

        For Each cultureName In cultureNames
            Console.WriteLine()
            Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(cultureName)
            Dim greeting As String = rm.GetString("Greeting", CultureInfo.CurrentCulture)
            Console.WriteLine("{0}!", greeting)
            Console.Write(rm.GetString("Prompt", CultureInfo.CurrentCulture))
            Dim name As String = Console.ReadLine()
            If Not String.IsNullOrEmpty(name) Then
                Console.WriteLine("{0}, {1}!", greeting, name)
            End If
        Next
        Console.WriteLine()
    End Sub
End Module
' The example displays output like the following:
'       Hello!
'       What is your name? Dakota
'       Hello, Dakota!
'       
'       Hello!
'       What is your name? Koani
'       Hello, Koani!
'       
'       Здравствуйте!
'       Как вас зовут?Samuel
'       Здравствуйте, Samuel!
'       
'       Bon jour!
'       Comment vous appelez-vous?Yiska
'       Bon jour, Yiska!

この例の C# バージョンをコンパイルするには、次のバッチ ファイルを実行します。 Visual Basic を使用している場合は、cscvbc に置換し、.cs 拡張子を .vb に置換します。

md Resources
resgen Strings.txt Resources\Strings.resources
resgen Strings.fr-FR.txt Resources\Strings.fr-FR.resources
resgen Strings.ru-RU.txt Resources\Strings.ru-RU.resources

csc Example.cs

関連項目