-
Notifications
You must be signed in to change notification settings - Fork 0
MS_ResourceFiles
- 戻る(国際化対応項目)
-
リソースファイル(マネージリソースファイル)は、
-
文字列や画像などのリソース情報を Key-Value で保持する、
拡張子が .resources または .resx のファイルのことである。 -
いろいろな言語のリソースファイルを用意すると、
多言語対応のアプリケーションを作成できる。 -
アセンブリ・ファイル(dll, exe)に含められる。
-
-
参考
- リソースファイルからリソースを取得する: .NET Tips: C#, VB.NET
http://dobon.net/vb/dotnet/programing/resourcemanager.html
- リソースファイルからリソースを取得する: .NET Tips: C#, VB.NET
補足(2 つの用途): リソースファイルには、
性質の異なる 2 つの用途が混在しているため、
先に切り分けておくと読みやすい。① 埋め込みリソース(画像・アイコン・テキスト) → 「1 ファイルにまとめて配布したい」という配置の話 ② ローカライズ(多言語対応) → 「言語ごとに文言を差し替えたい」という国際化の話本ページは①を特徴で、②を多言語対応で扱っている。
実務で主に使われるのは②である
(①は現在、埋め込みリソース(EmbeddedResource)を直接使う方が多い)。
-
*.resx ファイル と *.designer.cs(vb)ファイルから成る。
-
*.resx ファイル
埋め込まれたリソースとして埋め込まれる XML ファイル。 -
*.designer.cs(vb)ファイル
埋め込まれたリソースを読み取るコードが自動生成される。
補足(ビルド時の流れ):
.resxがどう変換されるかを
押さえておくと、後述のサテライト アセンブリの話が理解しやすい。Strings.resx ──(ResGen)──> Strings.resources ──┐ Strings.ja.resx ──(ResGen)──> Strings.ja.resources ─┤ ↓ Strings.resources → 本体アセンブリ(MyApp.dll)に埋め込み Strings.ja.resources → [AL.exe](MS_NuGetMSB3086) で ja\MyApp.resources.dll(サテライト)を生成 Strings.Designer.cs ← ResXFileCodeGenerator が自動生成 (ResourceManager 経由でアクセスする厳密に型指定されたプロパティ)
AL.exeが見つからないと MSB3086 になるのは、
このサテライト アセンブリ生成の段階である。
-
アセンブリ・ファイル(dll, exe)に含められるため、改ざんされにくい。
-
ただし、リソースファイルの修正を反映するには再ビルドが必要。
※ ILSpy 等の逆アセンブルツールにてリソースファイルの内容が
抽出されることは防げない
補足(隠蔽の目的で使わない): 原文自身が注記している通り、
リソースは容易に抽出できる(ILSpy で丸見え)。リソースファイルが提供するのは ・「うっかり編集される」ことの防止(設定ファイルと違い、外に出ない) ・配布物の一体化 であって、 ・秘密情報の保護 ではない。接続文字列・API キーをリソースに入れてはならない。
それらは .NET Core config の
ユーザー シークレット / 環境変数 / Key Vault に置く。また、「再ビルドが必要」という性質は運用上の制約でもある。
文言を運用中に変えたい場合は、
DB や外部ファイルから読む仕組み(後述のIStringLocalizerの
カスタム実装等)を検討する。
-
リソースファイルを dll に含めることにより、実行時に差し替えが可能
-
参考
- ResourceManager.ReleaseAllResources メソッド (System.Resources)
https://learn.microsoft.com/ja-jp/dotnet/api/system.resources.resourcemanager.releaseallresources
- ResourceManager.ReleaseAllResources メソッド (System.Resources)
移行メモ(表現): 「実行中の差し替えが可能」は、
サテライト アセンブリ(ja\MyApp.resources.dll)を
差し替えられる、という意味である
(本体アセンブリに埋め込んだ既定リソースは差し替えられない)。
ReleaseAllResources()でキャッシュを解放すれば
次回のアクセスで再読み込みされるが、
ファイルがロックされている場合は差し替え自体ができない点に注意する。
リソースファイルに画像などのバイナリファイルを文字列と同様に含めることが可能である。
この際、BASE64 エンコードされた文字列が resx ファイルに格納される。
- 参考
- リソースファイルからリソースを取得する: .NET Tips: C#, VB.NET
http://dobon.net/vb/dotnet/programing/resourcemanager.html
- リソースファイルからリソースを取得する: .NET Tips: C#, VB.NET
補足(バイナリは別ファイル参照が望ましい):
.resxに
BASE64 で直接埋め込むと、
.resxが肥大し、差分が読めなくなる(Git で扱いにくい)- マージ競合が解決不能になる
という問題が出る。
.resxからは「ファイルへの相対パス」で参照する形
(Visual Studio の既定動作)にしておく方がよい。<data name="Logo" type="System.Resources.ResXFileRef, System.Windows.Forms"> <value>Resources\logo.png;System.Drawing.Bitmap, System.Drawing</value> </data>**単に「DLL に画像を埋め込みたい」**だけなら、
.resxを使わずEmbeddedResourceで足りる。<ItemGroup> <EmbeddedResource Include="Assets\logo.png" /> </ItemGroup>using var s = Assembly.GetExecutingAssembly() .GetManifestResourceStream("MyApp.Assets.logo.png");
カルチャを使用し、対応したリソースファイルから
情報を取得することで文言や、UI 要素の多言語対応が可能となる(詳細は後述)。
リソースファイルの作成方法には下記の様なものがある。
-
Visual Studio でリソースを作成、編集できる。
-
通常 Key-Value だが、画像 / アイコン / テキスト・ファイルも追加できる。
- 参考
- Visual Studioでリソースを管理する: .NET Tips: C#, VB.NET
http://dobon.net/vb/dotnet/programing/vsresource.html
- Visual Studioでリソースを管理する: .NET Tips: C#, VB.NET
- 参考
-
Visual Studio でリソース中に改行コードを入れる方法
リソース作成画面にて
[Shift]+[Enter]キー
を押下すると改行コードを挿入できる。
- 参考
- 文字列のリソースに改行コードを埋め込むには?[VS 2005、VS 2008] - @IT
http://www.atmarkit.co.jp/fdotnet/dotnettips/825resourcesstrlf/resourcesstrlf.html
- 文字列のリソースに改行コードを埋め込むには?[VS 2005、VS 2008] - @IT
リソースファイルを作成する API が用意されている。
- 参考
- プログラムによる .resx ファイルの使用
https://learn.microsoft.com/ja-jp/dotnet/core/extensions/work-with-resx-files-programmatically- .resx ファイルの作成
- プログラムによる .resx ファイルの使用
.txt ファイルからリソースファイルを作成する Resgen.exe が用意されている。
- 参考
- @IT:.NET TIPS [ASP.NET]リソース・ファイル活用で国際化対応サイトを構築するには? - C# VB.NET Webフォーム
http://www.atmarkit.co.jp/fdotnet/dotnettips/192aspmultilang/aspmultilang.html - Resgen.exe (リソース ファイル ジェネレーター)
https://learn.microsoft.com/ja-jp/dotnet/framework/tools/resgen-exe-resource-file-generator
- @IT:.NET TIPS [ASP.NET]リソース・ファイル活用で国際化対応サイトを構築するには? - C# VB.NET Webフォーム
補足(翻訳のやり取りは XLIFF / CSV で): 実務では、
翻訳会社や現地担当者とファイルをやり取りする必要がある。
.resxをそのまま渡すのは扱いにくいため、
中間形式に変換するのが一般的である。
形式 用途 XLIFF 翻訳業界の標準形式。多くの翻訳ツールが対応 CSV / Excel 手軽。社内翻訳向け Multilingual App Toolkit Visual Studio 拡張。 .resx↔ XLIFFキーの命名規則を先に決めておくことが重要で、
後から一括変換するのは非常に手間がかかる。
リソースファイルの使用方法には下記の様なものがある。
-
*.resx ファイルを開く。
-
カスタム・ツールを設定する。
- ダブルクリックしてデザイナの DDL から Internal or Public を選択する。
- プロパティ・グリッドのカスタム・ツールに以下を設定する。
- ResXFileCodeGenerator(Internal)
- PublicResXFileCodeGenerator(Public)
-
これにより、
- *.resx ファイルと、
- *.designer.cs(vb)ファイルが
グループ化される。
移行メモ(表記): 原文の「デザイナの DDL」は
**ドロップダウン リスト(DDL)**を指すと読めるが、
データベースの DDL と紛らわしいため注記しておく
(実際にはリソース エディター上部の「アクセス修飾子」の
ドロップダウンを指す)。
-
Internal
エントリ・アセンブリ ※1 内でのみ使用する場合コチラを選択する。
(※ 1: 現在の AppDomain のエントリポイントを含むアセンブリ) -
Public
-
他のアセンブリで利用する場合コチラを選択する。
-
この場合、双方のアセンブリのルート名前空間を一致させる必要がある。
-
c# - What does MissingManifestResourceException mean and how to fix it? - Stack Overflow
https://stackoverflow.com/questions/1327692/what-does-missingmanifestresourceexception-mean-and-how-to-fix-it
-
補足(
MissingManifestResourceExceptionの原因): 原文が
参考に挙げているこの例外は、リソース周りで最頻出のトラブルである。原因の大半は「リソース名の解決に失敗している」 期待される名前: <既定の名前空間>.<フォルダ>.<ファイル名> 例: MyApp.Resources.Strings 【よくあるずれ】 ・プロジェクトの既定の名前空間を変更した ・.resx を別フォルダに移動した ・ビルド アクションが「埋め込まれたリソース」になっていない ・ライブラリ側とアプリ側でルート名前空間が違う(原文の指摘)確認方法:
// 実際に埋め込まれているリソース名を列挙する foreach (var n in Assembly.GetExecutingAssembly().GetManifestResourceNames()) Console.WriteLine(n);
ResourceManagerを自分で作る場合は、
この名前を正確に渡す必要がある。var rm = new ResourceManager("MyApp.Resources.Strings", typeof(SomeTypeInThatAssembly).Assembly);
-
*.designer.cs(vb)に実装された、
プロパティ・プロシージャ経由でリソースにアクセスできる。 -
リソースファイルを使用する API が用意されている。
-
参考
- プログラムによる .resx ファイルの使用
https://learn.microsoft.com/ja-jp/dotnet/core/extensions/work-with-resx-files-programmatically- リソースを列挙する
- 特定のリソースを取得する
- .resx ファイルをバイナリ .resources ファイルに変換する
- プログラムによる .resx ファイルの使用
- リソースの名前に "="(半角イコール) を含めることができません。
- リソースの値に LF(Line Feed) を含めることができません。
移行メモ(制限の背景): これらは
.txt形式(Resgen.exeが扱うname=value形式)の制限であり、
.resx(XML)では該当しない
(.resxなら=も LF も格納できる)。
原文のテキストファイルからリソースファイルを作成する方法に
対応する注意事項と読むのが妥当である。
スレッド毎に保持している CurrentUICulture に設定されている
カルチャを使用して、
対応したリソースファイルから情報を取得することで文言や、
UI 要素の多言語対応が可能となる。
補足(
CurrentCultureとCurrentUICultureは別物): 混同されやすいが、
役割が明確に分かれている。
CurrentCultureCurrentUICulture用途 書式(日付・数値・通貨・並べ替え) リソースの選択(文言) 例 1,234.56/2026/08/19Strings.ja.resxを選ぶ設定元 OS の地域設定 OS の表示言語 // 日本語 UI・米国式の数値書式、という組み合わせもあり得る Thread.CurrentThread.CurrentUICulture = new CultureInfo("ja-JP"); // 文言 Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US"); // 書式**「文言は日本語なのに日付が
8/19/2026になる」**といった現象は、
この 2 つを取り違えていることが原因である。
R1.resx 既定カルチャ用リソースファイル
├R1.ja.resx 日本語用リソースファイル
├R1.en.resx 英語用リソースファイル
├R1.zh-Hans.resx 簡体字中国語用リソースファイル
└R1.zh-Hant.resx 繁体字中国語用リソースファイル
R2.resx 既定カルチャ用リソースファイル
├R2.ja-JP.resx 日本語(日本)用リソースファイル
└R2.en-US.resx 英語(米国)用リソースファイル
補足(「既定カルチャ」に何を入れるか): 拡張子なしの
R1.resxに
何語を入れるかは、設計判断である。
方針 利点 欠点 英語を既定にする 国際的に無難。未翻訳でも読める 日本語のみの案件では冗長 日本語を既定にする 国内案件では自然 未対応言語で日本語が出る キー名だけ入れる 未翻訳が一目で分かる 事故時に表示が崩壊する
NeutralResourcesLanguage属性で
「既定リソースは何語か」を明示しておくと、
その言語ではサテライトの探索をスキップするため起動が速くなる。[assembly: NeutralResourcesLanguage("ja-JP", UltimateResourceFallbackLocation.MainAssembly)]
- 使用するリソースファイルをシステムが判断することを指す。
- CurrentUICulture のカルチャと一致するリソースファイルが
存在しない場合、親カルチャ用のリソースファイルを順に検索する。
補足(探索の順序): 具体的には次の順に探す。
CurrentUICulture = "zh-Hant-TW" の場合 ① zh-Hant-TW\MyApp.resources.dll (特定カルチャ) ② zh-Hant\MyApp.resources.dll (中立カルチャ) ③ zh\MyApp.resources.dll (親) ④ 本体アセンブリの既定リソース (最終フォールバック) ④ にも無ければ MissingManifestResourceException下位カルチャで差分のみ定義できる(原文の記述)のは、
この段階的な探索によるものである。R1.resx : Yes / No / Cancel / Save / Delete R1.ja.resx : はい / いいえ / キャンセル ← Save/Delete は未定義 → 日本語環境では Save/Delete は英語のまま表示される
- Parent プロパティで上位のカルチャを取得可能なので単純なアルゴリズムで作成可能。
- また、メッセージを言語毎に用意するのであれば
TwoLetterISOLanguageName プロパティで 2 階層目の値を取得することが可能なため、
その値で分岐すれば良い。
- ローカリゼーション用リソースの階層編成
https://learn.microsoft.com/ja-jp/dotnet/core/extensions/localization
-
サテライトアセンブリ(*.resources.dll という名称)
でカルチャ名フォルダに配置される。 -
サテライト アセンブリの作成
https://learn.microsoft.com/ja-jp/dotnet/core/extensions/create-satellite-assemblies
補足(配置と配布の注意点): サテライト アセンブリは
アプリの実行フォルダ直下のカルチャ名フォルダに置かれる。bin\Release\net8.0\ MyApp.dll ja\MyApp.resources.dll en\MyApp.resources.dll zh-Hans\MyApp.resources.dll実務上の注意:
論点 内容 配布漏れ カルチャ フォルダのコピー忘れで「英語になる」 不要な言語 SatelliteResourceLanguagesで絞れる(サイズ削減)単一ファイル発行 サテライトも埋め込まれる(.NET 5+) NuGet で配る NuGetパッケージの開発と公開 の Localized Package <!-- 日本語と英語だけを出力する(他言語のサテライトを作らない) --> <PropertyGroup> <SatelliteResourceLanguages>ja;en</SatelliteResourceLanguages> </PropertyGroup>NuGet パッケージが多言語のサテライトを持っていると
出力が膨らむため、上記で絞るのは実用的な最適化である。
リソースファイルを使用することで、UI の多言語対応が可能である。
Windows FormsとASP.NET Web Formsで
実装の方法が異なる。
ASP.NETの場合
補足(ASP.NET Core の方式/最新化): ASP.NET Core では
IStringLocalizer/IViewLocalizerという抽象を通す方式に
変わっている。// Program.cs builder.Services.AddLocalization(o => o.ResourcesPath = "Resources"); builder.Services.AddControllersWithViews() .AddViewLocalization() .AddDataAnnotationsLocalization(); var cultures = new[] { "ja", "en" }; app.UseRequestLocalization(new RequestLocalizationOptions() .SetDefaultCulture("ja") .AddSupportedCultures(cultures) .AddSupportedUICultures(cultures));public class HomeController(IStringLocalizer<HomeController> L) : Controller { public IActionResult Index() { ViewData["Title"] = L["Welcome"]; ... } }@inject IViewLocalizer L <h1>@L["Welcome"]</h1>本ページとの主な違い:
.NET Framework ASP.NET Core アクセス Designer.csの型付きプロパティIStringLocalizer(DI)キーが無いとき 例外 キー名がそのまま返る(落ちない) カルチャの決定 スレッドに設定 RequestLocalizationMiddleware(URL / Cookie / ヘッダー)差し替え サテライト DLL IStringLocalizerを自作(DB / JSON も可)**「キーが無くても落ちない」**のは実務上大きな違いで、
未翻訳の項目があっても画面は表示される
(代わりに、未翻訳の検出は別途行う必要がある)。また、
IStringLocalizerを自作すれば
DB や JSON から文言を読めるため、
本ページのメッセージ等の隠蔽化が可能で述べた
「再ビルドが必要」という制約を回避できる。
- グローバリゼーションとローカリゼーション
https://learn.microsoft.com/ja-jp/dotnet/core/extensions/globalization-and-localization - .NET アプリのグローバリゼーション
https://learn.microsoft.com/ja-jp/dotnet/core/extensions/globalization - .NET アプリのローカリゼーション
https://learn.microsoft.com/ja-jp/dotnet/core/extensions/localization - Windows フォームのグローバル化
https://learn.microsoft.com/ja-jp/dotnet/desktop/winforms/advanced/globalizing-windows-forms - ASP.NET Core のグローバリゼーションおよびローカリゼーション
https://learn.microsoft.com/ja-jp/aspnet/core/fundamentals/localization - WPF のグローバライズとローカライズ
https://learn.microsoft.com/ja-jp/dotnet/desktop/wpf/advanced/wpf-globalization-and-localization-overview
- Visual Studioでリソースを管理する
https://dobon.net/vb/dotnet/programing/vsresource.html - .resxファイル(XMLリソースファイル)を作成する、読み込む
https://dobon.net/vb/dotnet/programing/resxresourcewriter.html
Tags: 移行, .NET開発, 国際化対応
このWikiは「Open棟梁Project」,「OSSコンソーシアム 開発基盤部会」によって運営されています。