# General Translation Knowledge Base: .NET アプリで .resx ファイルを翻訳するには？
URL: https://generaltranslation.com/ja/kb/translate-resx-files.mdx
Docs index: https://generaltranslation.com/llms.txt
Description: ニュートラルな .resx ファイルごとに、Resources.fr.resx のようなカルチャ名付きのコピーを作成し、各エントリの値だけを翻訳します。名前、コメント、{0} などのプレースホルダーは変更しないでください。.NET はカルチャごとにサテライトアセンブリをビルドし、fr-CA → fr → ニュートラルファイルの順にフォールバックします。General Translation の CLI を使えば、ニュートラルな翻訳元ファイルからこれらのカルチャファイルを生成できます。
Category: 翻訳
Last updated: 2026-10-28
Authors: General Translation Team
Published: 2026-10-28

.resx ファイルは、名前付きリソースを列挙した XML ファイルです。`Resources.resx` のようなニュートラルファイルにはデフォルト言語のテキストを格納し、各翻訳は `Resources.fr.resx` のようにファイル名にカルチャを含めて同じ場所に配置します。翻訳ファイルには同じ名前が並び、値だけが翻訳されています。実行時には `ResourceManager` が現在の UI カルチャに一致するファイルを選択し、見つからないリソースは親カルチャをたどってフォールバックします。

## .resx ファイルの中身

各リソースは `<data>` 要素で表されます。`name` 属性はコードから参照するキー、`<value>` はテキスト本体で、任意の `<comment>` にはそのテキストの用途を翻訳者向けに記述します。以下は抜粋です (実際のファイルでは、先頭に Visual Studio が自動で書き込むスキーマブロックと `<resheader>` エントリも含まれます) 。

```xml title="Resources/SharedResource.resx"
<data name="Checkout" xml:space="preserve">
  <value>Checkout</value>
  <comment>Button that starts payment for the items in the cart.</comment>
</data>
<data name="ItemsInCart" xml:space="preserve">
  <value>You have {0} items in your cart.</value>
  <comment>{0} is the number of items.</comment>
</data>
```

フランス語のファイルにも同じ `name` 属性があり、値がフランス語になっています。変わるのは文字列の値だけです。名前は参照用のキーです。また、画像など文字列以外のリソースは `type` 属性を持ち、多くの場合 `mimetype` 属性も持っていますが、通常はそのまま残します。XML を整形式に保ち、定義済みの形式から外れないようにする必要があるため、Microsoft は .resx ファイルを手作業ではなく Visual Studio で編集することを推奨しています ([Microsoft: Create resource files](https://learn.microsoft.com/en-us/dotnet/core/extensions/create-resource-files)) 。

## .NET が適切な翻訳を見つける仕組み

各翻訳ファイルには、ニュートラルファイルと同じルート名を付け、拡張子の前にカルチャを入れます (例: `Resources.fr.resx`、`Resources.fr-CA.resx`) 。ビルドすると、ニュートラルリソースはメインアセンブリに埋め込まれ、各カルチャはカルチャ名を冠したフォルダ内のサテライトアセンブリ (例: `fr/MyApp.resources.dll`) としてコンパイルされます。

アプリが文字列を要求すると、.NET はまず要求されたカルチャのサテライトアセンブリを探し、見つからなければその親カルチャ、さらにその親へと順にたどり、最終的にニュートラルリソースを使用します。たとえば `fr-CA` が要求された場合は、`fr-CA`、`fr`、ニュートラルファイルの順に検索します。デフォルトカルチャのリソースファイルすら存在しない場合は、`MissingManifestResourceException` または `MissingSatelliteAssemblyException` の例外をスローします。Linux と macOS では、カルチャフォルダ名が大文字・小文字の区別も含めて `CultureInfo.Name` と完全に一致している必要があります ([Microsoft: Package and deploy resources](https://learn.microsoft.com/en-us/dotnet/core/extensions/package-and-deploy-resources)) 。

フォールバックを利用すれば、同じ言語を使う複数のリージョンを一度の翻訳でまとめてカバーできます。Microsoft は、`de-DE`、`de-AT`、`de-CH` のユーザー向けに単一の `de` ファイルを用意し、地域ごとのファイルには差異のある文字列だけを含める方法を推奨しています。ただしその反面、翻訳が欠けていても例外はスローされません。ユーザーにはニュートラル言語が表示されるだけで、ビルド時にも何の警告も出ません。 ([ロケールコードとは？](/kb/locale-codes)を参照してください。)

## ASP.NET Core、Windows Forms、WPF で .resx を使用する

### ASP.NET Core

ローカライゼーションを登録し、サポートするカルチャを選択したうえで、ミドルウェアを追加します ([Microsoft: Select language and culture](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/localization/select-language-culture)) 。

```csharp title="Program.cs"
builder.Services.AddLocalization(options => options.ResourcesPath = "Resources");

builder.Services.Configure<RequestLocalizationOptions>(options =>
{
    var supportedCultures = new[] { "en-US", "fr" };
    options.SetDefaultCulture(supportedCultures[0])
        .AddSupportedCultures(supportedCultures)
        .AddSupportedUICultures(supportedCultures);
});

var app = builder.Build();

// クエリ文字列、クッキー、Accept-Language の順にカルチャを決定します。
app.UseRequestLocalization();
```

次に `IStringLocalizer<T>` を注入し、名前で文字列を検索します。書式引数は名前の後に渡します: `localizer["ItemsInCart", count]`。リソースファイルの名前は、クラスの完全な型名からアセンブリ名を除いたものになります。たとえば `Controllers.HomeController` は、`Resources` フォルダー内の `Controllers.HomeController.fr.resx`(または `Resources/Controllers` 内の `HomeController.fr.resx`)を読み込みます。また、空の `SharedResource` マーカークラスを用意すると、アプリ全体で共有する文字列をまとめられます。`SupportedUICultures` は読み込む .resx ファイルを決め、`SupportedCultures` は日付と数値のフォーマットを決めます([Microsoft: Provide localized resources](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/localization/provide-resources))。

`IStringLocalizer` は翻訳が存在しない場合にキーそのものを返します。そのため Microsoft は、ニュートラルな .resx を一切使わないワークフローも紹介しています。この場合、`localizer["About Title"]` は英語で &quot;About Title&quot; と表示されます([Microsoft: Make content localizable](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/localization/make-content-localizable))。表示するだけならこれで問題ありませんが、翻訳者やツールが読み取るためのソースファイルが存在しないことになります。ファイルから翻訳を生成したい場合は、名前付きキーと、英語テキストを値に持つニュートラルな .resx を組み合わせてください。これは Microsoft が同じく紹介している従来の方法です。

### Windows Forms と WPF

Windows Forms では、フォームの **Localizable** プロパティを `true` に設定し、**Language** プロパティでカルチャを選択します。この状態でデザイナー上のテキストを変更すると、Visual Studio は `Form1.es-ES.resx` のようなカルチャ別ファイルにその内容を書き込みます ([Microsoft: Localizing a hybrid application](https://learn.microsoft.com/en-us/dotnet/desktop/wpf/advanced/walkthrough-localizing-a-hybrid-application)) 。デザイナーが生成するファイルには、`>>` で始まる名前など、テキスト以外のエントリも含まれます。WPF アプリでは `ResourceManager` を使って .resx の文字列を読み込めます。Microsoft の XAML ローカライゼーションのチュートリアルでは LocBaml ツールが使われていますが、Microsoft 自身はこれを「本番環境向けのアプリケーションではない」サンプルとしています ([Microsoft: Localize a WPF app](https://learn.microsoft.com/en-us/dotnet/desktop/wpf/advanced/how-to-localize-an-application)) 。

### Visual Studio で編集する

Visual Studio 2022 バージョン 17.11 以降では、Resource Explorer で各 .resx ファイルのカルチャを並べて確認できます。.resx ファイルを右クリックして **Open With &gt; Resource Explorer** を選択します (または **Ctrl+Alt+R** を押します) 。翻訳が欠けている場合 (「No value」) や、プレースホルダーがニュートラルカルチャと一致しない場合 (例: `Hello, {name}!` と `Hola, {nombre}!`) には警告が表示されます ([Microsoft: Manage application resources](https://learn.microsoft.com/en-us/visualstudio/ide/managing-application-resources-dotnet)) 。

## .resx ファイルの翻訳で壊れやすい箇所

* **プレースホルダー。** .NET の複合書式指定項目は `{index[,width][:formatString]}` の形式で、`{0}`、`{1,-10}`、`{0:N2}` などがあります。翻訳で順序を入れ替えたり、同じ項目を2回使ったりするのは問題ありません。ただし、引数の範囲外を指す書式指定項目があると実行時に `FormatException` がスローされ、項目が抜け落ちると値が警告なしに失われます。リテラルの波かっこは `{{` と `}}` と記述します ([Microsoft: Composite formatting](https://learn.microsoft.com/en-us/dotnet/standard/base-types/composite-formatting)) 。
* **名前。** `name` 属性を翻訳してしまうと参照で何も見つからず、その文字列はニュートラル言語にフォールバックします。
* **XML。** `&` や `<` を含む値は、`&amp;` や `&lt;` とエスケープされた状態を保つ必要があります。そうしないとファイルがコンパイルできません。
* **アクセスキー。** Windows Forms では、`&File` と書くと F に下線が付きます。翻訳でも、適切な文字の前に `&` をちょうど1つだけ置く必要があります。
* **コメント。** コメントは翻訳者向けの文脈情報であり、翻訳対象のテキストではありません。Microsoft の Windows App SDK ガイドにも、翻訳者がコメントを翻訳する必要はないと記載されています ([Microsoft: Localize strings](https://learn.microsoft.com/en-us/windows/apps/windows-app-sdk/mrtcore/localize-strings)) 。
* **ずれ。** 開発者がニュートラルファイルに名前を追加したら、すべてのカルチャファイルにも同じ名前が必要です。フォールバックによって欠落が表面化しないため、リリース前には毎回、値の不足がないか確認してください。

## .resx ファイルを翻訳する方法

| 方法                              | 名前と文字列以外のリソースの保持                 | プレースホルダーのチェック                                     | カルチャ間の同期                                                                                 | 適したケース                             |
| ------------------------------- | -------------------------------- | ------------------------------------------------- | ---------------------------------------------------------------------------------------- | ---------------------------------- |
| Visual Studio のResource Explorerで手作業 | はい                               | 不一致を警告                                            | カルチャごとに不足している値を表示                                                                        | チーム内に話せる人がいる言語が 1〜2 つの場合           |
| 翻訳者または翻訳管理システム (TMS)            | はい (TMS が .resx を解析できる場合)        | TMS の QAチェック次第                                    | TMS のリポジトリ同期で対応                                                                          | プロの翻訳者やベンダーが作業を担当する場合              |
| 機械翻訳 API や LLM をスクリプトで呼び出す      | スクリプトが XML を解析して値のみを送信する場合に限る    | 自分で実装する                                           | 再実行して差分を確認                                                                               | スクリプトとその検証を自分で管理する場合               |
| ファイルをチャットアシスタントに貼り付ける           | 保証なし                             | なし                                                | 手動                                                                                       | 1 行ずつ確認する単発のファイルの場合                |
| General Translation CLI         | 文字列値のみを翻訳し、名前、コメント、文字列以外のリソースは保持 | プレースホルダーを変更・欠落させた翻訳は除外され、そのエントリは .NET のフォールバックで表示 | 変更のないエントリは既存の翻訳を再利用。リリースごとに [`gt translate`](/docs/cli/reference/commands/translate) を実行 | リソースファイルがリポジトリで管理され、リリースごとに変更される場合 |

チームメンバーがレビューできる言語が 1〜2 つなら、Resource Explorerを使いましょう。プロの翻訳者がコードベースの外で作業する場合は、[TMS](/kb/what-is-a-translation-management-system) が適しています。.resx ファイルがリリースごとに変更され、翻訳済みファイルをコードと一緒にコミットしたい場合は、General Translation を選んでください ([General Translation と TMS の比較](/kb/general-translation-vs-tms)を参照) 。

## General Translation で .resx ファイルを翻訳する方法

General Translation の CLI である `gt` は、`resx` ファイルキーを使って .resx ファイルを翻訳できます。同じスキーマの `.resw` ファイルにも対応しています (`gt` 2.23.1 以降) 。ニュートラルファイルはファイル名にカルチャを含まないため、`include` でそのファイルを指定し、同じ場所にある翻訳済みファイルを除外したうえで、`transform` を使って拡張子の前にカルチャを付加します。

```json title="gt.config.json"
{
  "defaultLocale": "en",
  "locales": ["fr", "es-MX"],
  "files": {
    "resx": {
      "include": ["Resources/*.resx"],
      "exclude": ["Resources/*.[locales].resx"],
      "transform": {
        "match": "\\.resx$",
        "replace": ".{locale}.resx"
      }
    }
  }
}
```

`Resources` フォルダーでは、この設定により `Controllers.HomeController.resx` が読み込まれ、ASP.NET Core のドット区切りの名前を維持したまま `Controllers.HomeController.fr.resx` と `Controllers.HomeController.es-MX.resx` が書き出されます。すでに提供しているカルチャはすべて `locales` に列挙してください。`[locales]` による除外でスキップされるのは設定済みロケールの翻訳済みファイルだけです。そのため、リストにない `Resources.de.resx` は翻訳元ファイルとして読み込まれてしまいます。言語ごとのフォルダーに `.resw` ファイルを配置する UWP および WinUI プロジェクトでは、`transform` を指定せずに `"include": ["Strings/[locale]/Resources.resw"]` を使用してください。

.NET リポジトリであっても、CLI の実行には Node.js 20 以降が必要です。[CLI クイックスタート](/docs/cli/quickstart)の手順に従ってインストールし、[`npx gt login`](/docs/cli/reference/commands/login) でサインインしてから、`GT_PROJECT_ID` を設定してください ([CLI の認証情報](/docs/cli/guides/configuring#credentials)) 。既存の翻訳があるアプリでは、まず [`npx gt upload`](/docs/cli/reference/commands/upload) で翻訳をインポートします。次に、[`npx gt translate`](/docs/cli/reference/commands/translate) を実行します。CI では、**Files &gt; Write** と **Translation queue &gt; Enabled** の権限を持つプロジェクトの APIキーを `GT_API_KEY` として保存してください。

翻訳済みファイルは、翻訳元の文字列値だけを置き換えたコピーです。そのため、名前、エントリの順序、スキーマおよび `<resheader>` ブロック、コメント、文字列以外のリソースは元のまま維持されます。`mimetype` を持つエントリ、型が `System.String` 以外のエントリ、`>>` で始まるデザイナー名のエントリ、値が空のエントリは翻訳対象として送信されません。各 `<comment>` は文脈として送信され、コメント内の `{Locked}` などの Microsoft のローカライゼーション指示も反映されます。`{0}`、`{0:N2}`、`{1,-10}`、`{count}` などのプレースホルダーや二重の波括弧はそのまま保持され、単一の `&` によるアクセスキーは適切な文字の前に配置されます。また、ダウンロードしたファイルには翻訳元と同じエンコーディングとバイトオーダーマークが維持されます。 ([.resx リファレンス](/docs/cli/reference/formats/resx-files)を参照してください。) 

翻訳は[ダッシュボード](/docs/platform/dashboard/guides/reviewing-translations)または Visual Studio でレビューできます。ローカルでファイルを編集した場合は、[`npx gt save-local`](/docs/cli/reference/commands/save-local) を実行しておくと、以降の実行でも編集内容が保持されます。[コンテキストグループ](/docs/platform/dashboard/guides/defining-context-for-translations)を使えば、Web アプリの [JSON ファイル](/kb/translate-json-files)と同じ用語集とカスタムプロンプトを .NET リソースにも適用できるため、製品名などの訳語を両者で統一できます。

## よくある質問

### .resx と .resw の違いは何ですか？

スキーマは同じです。UWP アプリや WinUI アプリでは、ファイル名にカルチャを含めるのではなく、`Strings/en-US/Resources.resw` や `Strings/de-DE/Resources.resw` のように言語ごとのフォルダーに `.resw` ファイルを配置します ([Microsoft: Localize strings](https://learn.microsoft.com/en-us/windows/apps/windows-app-sdk/mrtcore/localize-strings)) 。

### fr がある場合、fr-CA 用のファイルも別途必要ですか？

いいえ。`fr-CA` のリクエストで見つからない名前は `fr` にフォールバックするため、`fr-CA` ファイルには `fr` と異なる文字列だけを含めれば十分です。

### フランス語ファイルを追加したのに、ASP.NET Core アプリが英語のまま表示されるのはなぜですか？

`fr` が `SupportedUICultures` に含まれているか、ファイル名がクラスの型名と一致しているかを確認してください。また、Linux や macOS では、ビルド出力内のカルチャフォルダー (`fr` など) の名前が、大文字・小文字の区別も含めて `CultureInfo.Name` と完全に一致している必要があります。

## 要点

* 各翻訳は、`Resources.fr.resx` のようにファイル名にカルチャを含む、同じ階層の .resx ファイルです。翻訳するのは値だけで、`name` 属性は絶対に翻訳しないでください。
* .NET は `fr-CA` → `fr` → ニュートラルリソースの順にフォールバックするため、翻訳が欠けていてもエラーにはならず、ニュートラル言語で表示されます。
* 書式指定項目のインデックスが渡された引数の数を超えると、`FormatException` の例外がスローされます。すべての翻訳で `{0}` 形式のプレースホルダーを確認してください。
* Visual Studio 2022 17.11 の Resource Explorer では、カルチャ間での値の欠落やプレースホルダーの不一致を検出できます。
* General Translation の CLI は、`resx` キー (2.23.1 以降) を使って .resx と .resw を翻訳します。名前、コメント、文字列以外のリソースはそのまま保持され、プレースホルダーを壊す翻訳は出力から除外されます。

## Related questions

- [i18n の JSON ファイルを翻訳するには？](https://generaltranslation.com/ja/kb/translate-json-files.mdx): JSON ロケールファイルでは、文字列の値だけを翻訳します。複数形以外のキー、{{name}} などのプレースホルダー、タグは変更せずに残しますが、複数形のキーは言語によって異なる点に注意が必要です。たとえばポーランド語では inbox_few と inbox_many が必要になります。ファイル形式に対応したツールや API を使い、レビューの前に出力をパースして検証してください。
- [POファイルとPOTファイルはどのように翻訳すればよいですか？](https://generaltranslation.com/ja/kb/translate-po-files.mdx): Plural-Formsヘッダーが求める各複数形を含め、すべてのmsgstrを埋めます。msgid、msgctxt、プレースホルダーは変更しないでください。msgfmt --checkを実行すると、ヘッダー、複数形の数、および書式フラグ付きエントリのプレースホルダーを検査できます。空のmsgstrがないかは別途確認してください。General TranslationのCLIは、POTテンプレートから言語ごとに翻訳済みのPOファイルを書き出します。
- [翻訳管理システム（TMS）とは？](https://generaltranslation.com/ja/kb/what-is-a-translation-management-system.mdx): 翻訳管理システム（TMS）とは、ソースコンテンツとその翻訳を保管し、翻訳メモリ、用語集、レビュー、機械翻訳、外部連携といった翻訳ワークフローを運用するソフトウェアです。翻訳メモリは、完全一致またはあいまい一致によって過去の翻訳を再利用します。代表的な例として Crowdin、Lokalise、Phrase、Smartling、Transifex があります。
- [General Translation と TMS（Crowdin、Lokalise、Phrase）の比較](https://generaltranslation.com/ja/kb/general-translation-vs-tms.mdx): 翻訳の生成、コードから導出した文脈、レビューをプロダクトのリリースと連動させたい開発チームには General Translation が適しています。既存のカタログとレンダリングライブラリをそのまま使うことも、翻訳キーを使わずにインライン JSX を記述することもできます。TMS は、言語ベンダー、CAT エディター、XLIFF でのやり取りを中心とした翻訳プログラムに適しており、そのインテグレーションを使えばファイル転送を自動化できます。
- [デプロイのたびに翻訳を最新の状態に保つにはどうすればよいですか？](https://generaltranslation.com/ja/kb/translations-in-ci.mdx): 本番環境のビルド前に、翻訳をパイプラインのステップとして毎回実行します。こうすることで、新しいテキストは追加されたデプロイと同時に翻訳済みの状態でリリースされます。General Translation の gt CLI では、CI シークレットとして保存したプロジェクトの APIキーとプロジェクトIDを使い、npx gt translate でこれを実現します。

## Previous and next questions

- Previous question: [翻訳をレビュー・編集するにはどうすればよいですか？](https://generaltranslation.com/ja/kb/review-translations.mdx)
- Next question: [AI翻訳で用語の一貫性を保つにはどうすればよいですか？](https://generaltranslation.com/ja/kb/ai-translation-glossary.mdx)

## Sitemap

See the [Knowledge Base sitemap](https://generaltranslation.com/ja/kb/sitemap.md) for every article.
