リソースのパッケージ化と配置

.NET Framework は、ハブ アンド スポーク モデルを使用してリソースのパッケージ化と配置を行います。 ハブは、ローカライズできない実行可能コードと、ニュートラルまたは既定のカルチャと呼ばれる単一のカルチャのリソースを含むメイン アセンブリです。 既定のカルチャとは、アプリケーションで使用されるフォールバック カルチャです。 各スポークは、単一のカルチャ用のリソースを含むが、コードはまったく含まないサテライト アセンブリにつながります。

このモデルにはいくつかのメリットがあります。

  • アプリケーションを配置した後で、新しいカルチャ用のリソースを徐々に追加していくことができます。 アプリケーションの開発後に、カルチャ固有のリソースを開発するために長時間を要する場合があります。このモデルを使用すると、まずメイン アプリケーションをリリースし、後日にカルチャ固有のリソースをリリースできます。

  • アプリケーションのサテライト アセンブリを更新または変更するときに、アプリケーションを再コンパイルしなくても済みます。

  • アプリケーションは、特定のカルチャに必要なリソースを含むサテライト アセンブリだけを読み込みます。 このため、システム リソースの使用率を大幅に下げることができます。

ただし、このモデルにはデメリットもあります。

  • 複数のリソース セットを管理する必要があります。

  • 複数の構成をテストする必要があるので、アプリケーションのテストにかかる初期費用が増大します。 しかし、長い期間で捉えると、複数の国際バージョンを平行してテストおよび保守するよりも、複数のサテライトを持つ 1 つのコア アプリケーションをテストする方が簡単で負荷もかかりません。

リソースの名前付け規則

アプリケーションのリソースをパッケージ化するときには、共通言語ランタイムが要求するリソースの名前付け規則を使用して、各リソースに名前を付ける必要があります。 ランタイムはカルチャのシグネチャ、つまり名前によってリソースを識別します。 各カルチャには一意の名前が付けられます。この名前は、言語と関連付けられた 2 文字の小文字のカルチャ名と、必要に応じて、国または地域と関連付けられた 2 文字の大文字のサブカルチャ名の組み合わせで構成されます。 サブカルチャ名がある場合は、カルチャ名の後ろにダッシュ (-) で区切って続けます。 たとえば、日本の日本語を表す ja-JP、米国の英語を表す en-US、ドイツのドイツ語を表す de-DE (オーストリアのドイツ語を表す de-AT などのフォールバック カルチャとは異なります) などがあります。 カルチャ名の一覧については、CultureInfo クラスを参照してください。

リソース フォールバック プロセス

リソースをパッケージ化および配置するためのハブ アンド スポーク モデルは、代替プロセスを使用して適切なリソースを検索します。 アプリケーションのユーザーが、利用不可能な ResourceSet を要求した場合、共通言語ランタイムはカルチャの階層を検索して、ユーザーの要求に最も近いフォールバック リソースを探し、リソースが何も見つからない場合に最後の手段として例外を発生させます。 階層の各レベルにおいて、適切なリソースが見つかった場合、ランタイムはそのリソースを使用します。 リソースが見つからない場合、次のレベルへ移って検索が続行されます。

検索のパフォーマンスを向上させるには、NeutralResourcesLanguageAttribute 属性をメイン アセンブリに適用して、メイン アセンブリで使用するニュートラル言語の名前を渡します。

リソース フォールバック プロセスは、次のように段階的に実行されます。

  1. ランタイムは、まずグローバル アセンブリ キャッシュの中に、アプリケーション用に要求されたカルチャと一致するアセンブリがあるかどうかをチェックします。

    グローバル アセンブリ キャッシュには、多数のアプリケーションによって共有されるリソース アセンブリを格納できます。 このため、作成するすべてのアプリケーションのディレクトリ構造内に、特定のリソース セットを含める必要がなくなります。 アセンブリへの参照が検出されると、そのアセンブリの中に要求されたリソースがあるかどうかが検索されます。 要求されたリソースがアセンブリ内に見つかった場合、ランタイムはそのリソースを使用します。 リソースが見つからなかった場合、ランタイムは検索を続行します。

  2. 次に、ランタイムは現在実行されているアセンブリのディレクトリの中に、要求されたカルチャと一致するディレクトリがあるかどうかをチェックします。 ディレクトリが見つかった場合、そのディレクトリの中に、要求されたカルチャ用の有効なサテライト アセンブリがあるかどうかが検索されます。 次に、見つかったサテライト アセンブリの中で、要求されたリソースが検索されます。 アセンブリ内でリソースが見つかった場合、ランタイムはそのリソースを使用します。 リソースが見つからなかった場合、ランタイムは検索を続行します。

  3. 次に、ランタイムはもう一度グローバル アセンブリ キャッシュを検索しますが、今度は要求されたリソースの親アセンブリを見つけようとします。 グローバル アセンブリ キャッシュ内に親アセンブリが存在する場合、ランタイムはそのアセンブリの中で、要求されたリソースを検索します。

    親は、適切なフォールバック カルチャとして定義されています。 どのようなリソースでも例外が発生しなければよいという前提のもとで、親アセンブリが最適な代替リソース候補と見なされます。 このプロセスを使用して、リソースを再利用することもできます。 要求されたりソースを子のカルチャがローカライズする必要がない場合、特定のリソースを親のレベルだけに含めれば済みます。 たとえば、en (ニュートラルの英語)、en-GB (英国で話される英語)、および en-US (米国で話される英語) 用のサテライト アセンブリを作成する場合、サテライト en に共通の用語を組み込み、サテライト en-GB および en-US には、共通用語と異なる用語に関するオーバーライドだけを含めることができます。

  4. ランタイムは次に、現在実行されているアセンブリのディレクトリの中に、親ディレクトリが含まれるかどうかをチェックします。 親ディレクトリが存在する場合、そのディレクトリの中で、親カルチャ用の有効なサテライト アセンブリが検索されます。 アセンブリが見つかった場合、そのアセンブリの中で要求されたリソースが検索されます。 リソースが見つかった場合、ランタイムはそのリソースを使用します。 リソースが見つからなかった場合、ランタイムは検索を続行します。

  5. 次に、ランタイムは上記の手順に従って、可能性のある各レベルにおいて親アセンブリを検索します。 各カルチャの親は 1 つだけですが、親がさらにその上に親を持っている場合もあります。

  6. もともと指定されたカルチャとそのすべての親を検索してもリソースが見つからない場合は、既定 (フォールバック) カルチャ用のリソースが使用されます。 .NET Framework Version 2.0 から、リソースの最終フォールバック位置として、メイン アセンブリではなくサテライト アセンブリを指定できるようになりました。 UltimateResourceFallbackLocation 列挙体で NeutralResourcesLanguageAttribute を使用することにより、リソースの最終フォールバック位置をメイン アセンブリ内にするか、サテライト アセンブリ内にするかを制御できます。

    メモメモ

    既定のリソースは、メイン アセンブリと共にコンパイルされる唯一のリソースです。NeutralResourcesLanguageAttribute を使用してサテライト アセンブリを指定しない限り、メイン アセンブリが最終フォールバック (最終の親) になります。したがって、メイン アセンブリ内に必ず既定のリソース セットを含めておくことを強くお勧めします。これにより、例外がスローされることがなくなります。既定のリソース ファイルを含めておくことにより、すべてのリソース用のフォールバック リソースを用意して、カルチャに固有のリソースではなくても、少なくとも 1 つは利用できるリソースが確実に存在するようにしておくことができます。

  7. 最後に、既定 (フォールバック) カルチャ用のリソースが見つけからなかった場合、ランタイムはリソースが見つからなかったことを示す例外を発生させます。

要求されたリソースの検索がどのように行われるのかを示す例として、ユーザーがメキシコのスペイン語用にローカライズされたリソースを要求した場合を考えてみます。 上記のリソース名前付け規則に従い、まずランタイムはグローバル アセンブリ キャッシュ内で、要求されたカルチャ "es-MX" と一致するアセンブリを検索します。 見つからなかった場合、次にランタイムは現在実行されているアセンブリのディレクトリの中で、"es-MX" ディレクトリを検索します。 それにも失敗すると、ランタイムはもう一度グローバル アセンブリ キャッシュの中で、適切なフォールバック カルチャ、この場合は "es" (スペイン語) を反映している親アセンブリを検索します。 親アセンブリが見つからなかった場合、ランタイムは親アセンブリを含む可能性のあるすべてのレベルで、一致するリソースが見つかるまで "es-MX" カルチャを検索します。 リソースが見つからなかった場合、既定のカルチャ用のリソースが使用されます。

サテライト アセンブリへの最終フォールバック

.NET Framework Version 2.0 から、オプションでメイン アセンブリからリソースを削除し、固有のカルチャに対応するサテライト アセンブリから最終フォールバック リソースを検索するように指定できるようになりました。 このフォールバック プロセスを制御するには、NeutralResourcesLanguageAttribute を使用します。 NeutralResourcesLanguageAttribute クラスには、ResourceManager がフォールバック リソースを抽出する場所としてメイン アセンブリとサテライト アセンブリのいずれかを指定する追加の UltimateResourceFallbackLocation パラメーターを受け取る新しいコンストラクターが追加されました。

クラス レベルで属性を適用する方法の例を次に示します。

[assembly: NeutralResourcesLanguageAttribute("de" , UltimateResourceFallbackLocation.Satellite)]

このコードでは、ResourceManager に対し、最終フォールバック位置について、現在実行しているアセンブリのディレクトリの "de" サブディレクトリでリソースを検索するように指示しています。

パッケージ化に関して提案される代替手段

期間または予算の制約によっては、アプリケーションでサポートするすべてのサブカルチャについてリソース セットを作成できない場合があります。 そのような場合には、親カルチャ用に単一のサテライト アセンブリを作成しておけば、関連するすべてのサブカルチャがそのアセンブリを使用できます。 たとえば、サテライト アセンブリ English (en) を用意しておくと、地域固有の English リソースを要求するユーザーがそのアセンブリを取得できます。地域固有の German リソースを要求するユーザーについてはサテライト アセンブリ German (de) を用意します。 たとえば、ドイツのドイツ語 (de-DE)、オーストリアのドイツ語 (de-AT)、およびスイスのドイツ語 (de-CH) に対する要求には、サテライト アセンブリ German (de) をフォールバック アセンブリとして用意できます。 メイン アセンブリと共にコンパイルする既定のリソースは注意深く選択してください。 既定のリソースは最終的なフォールバック リソースなので、ほとんどのアプリケーション ユーザーから要求されるリソースを既定リソースとしておくことが必要です。 そうしておくことで、配置されるリソースはカルチャに固有ではなくなりますが、アプリケーションのローカライズ費用を大幅に削減できます。

参照

概念

アプリケーションのリソース

グローバル アセンブリ キャッシュ

サテライト アセンブリの作成