次の方法で共有


.NET アプリでリソースを取得する

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

アセンブリからリソースを取得する

ResourceManager クラスは、実行時にリソースへのアクセスを提供します。 ResourceManager.GetString メソッドを使用して文字列リソースを取得し、ResourceManager.GetObjectまたはResourceManager.GetStreamメソッドを使用して文字列以外のリソースを取得します。 各メソッドには、次の 2 つのオーバーロードがあります。

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

  • リソースの名前を含む文字列と、リソースを取得するカルチャを表す CultureInfo オブジェクトの 2 つのパラメーターを持つオーバーロード。 そのカルチャのリソース セットが見つからない場合、リソース マネージャーはフォールバック ルールを使用して適切なリソースを取得します。 詳細については、 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では、リソースが使用可能な 3 つのカルチャとスペイン語 (スペイン) カルチャの 4 つのカルチャの名前を含む文字列配列を定義します。 5 回実行されるループは、これらのカルチャの 1 つをランダムに選択し、 Thread.CurrentCultureCultureInfo.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: {culture.NativeName}");
         string timeString = rm.GetString("TimeHeader");
         Console.WriteLine($"{timeString} {DateTime.Now:T}\n");
      }
   }
}
// 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) という名前のファイルの次のコードは、テーブル タイトルと、英語用にローカライズされたアプリの情報を含む PersonTable オブジェクトを格納する UIResources.resx という名前の XML リソース ファイルを作成します。

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構造体に関する情報にアクセスできるように、Resgen.exe に UIElements.dll への参照を提供するには、PersonTable オプションを使用する必要があります。 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 Files のデプロイ

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

次の図は、リソース ファイルがディレクトリ構造内のどこにあるかを示しています。 また、.resource ファイルの名前付け規則も提供します。

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

リソース マネージャーを使用する

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

スタンドアロンの .resources ファイルを使用して ASP.NET アプリをデプロイしないでください。 これにより、ロックの問題が発生し、XCOPY の展開が中断される可能性があります。 サテライト アセンブリに ASP.NET リソースをデプロイすることをお勧めします。 詳細については、「 ASP.NET Web ページ リソースの概要」を参照してください。

ResourceManager オブジェクトをインスタンス化したら、前に説明したように、GetStringGetObject、および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{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

こちらも参照ください