dotnet-localization
Localizing .NET apps. .resx resources, IStringLocalizer, source generators, pluralization, RTL.
What this skill does
# dotnet-localization
Comprehensive .NET internationalization and localization: .resx resource files and satellite assemblies, modern alternatives (JSON resources, source generators for AOT), IStringLocalizer patterns, date/number/currency formatting with CultureInfo, RTL layout support, pluralization engines, and per-framework localization integration for Blazor, MAUI, Uno Platform, and WPF.
**Version assumptions:** .NET 8.0+ baseline. IStringLocalizer stable since .NET Core 1.0; localization APIs stable since .NET 5. .NET 9+ features explicitly marked.
**Scope boundary:** This skill owns all cross-cutting localization concerns: resource formats, IStringLocalizer, formatting, RTL, pluralization. UI framework subsections provide architectural overview and cross-reference the framework-specific skills for deep implementation patterns.
**Out of scope:** Deep Blazor component patterns -- see [skill:dotnet-blazor-components]. Deep MAUI development patterns -- see [skill:dotnet-maui-development]. Uno Platform project structure and Extensions ecosystem -- see [skill:dotnet-uno-platform]. WPF Host builder and MVVM patterns -- see [skill:dotnet-wpf-modern]. Source generator authoring (Roslyn API) -- see [skill:dotnet-csharp-source-generators].
Cross-references: [skill:dotnet-blazor-components] for Blazor component lifecycle, [skill:dotnet-maui-development] for MAUI app structure, [skill:dotnet-uno-platform] for Uno Extensions and x:Uid, [skill:dotnet-wpf-modern] for WPF on modern .NET.
---
## .resx Resource Files
### Overview
Resource files (`.resx`) are the standard .NET localization format. They compile into satellite assemblies resolved by `ResourceManager` with automatic culture fallback.
### Culture Fallback Chain
Resources resolve in order of specificity, falling back until a match is found:
```
sr-Cyrl-RS.resx -> sr-Cyrl.resx -> sr.resx -> Resources.resx (default/neutral)
```
The default `.resx` file (no culture suffix) is the single source of truth. Translation files must not contain keys absent from the default file.
### Project Setup
```xml
<!-- MyApp.csproj -->
<PropertyGroup>
<NeutralLanguage>en-US</NeutralLanguage>
</PropertyGroup>
<ItemGroup>
<!-- Default resources -->
<EmbeddedResource Include="Resources\Messages.resx" />
<!-- Culture-specific resources -->
<EmbeddedResource Include="Resources\Messages.fr-FR.resx" />
<EmbeddedResource Include="Resources\Messages.de-DE.resx" />
</ItemGroup>
```
### Resource File Structure
```xml
<!-- Resources/Messages.resx (default/neutral) -->
<?xml version="1.0" encoding="utf-8"?>
<root>
<data name="Welcome" xml:space="preserve">
<value>Welcome to the application</value>
<comment>Shown on the home page</comment>
</data>
<data name="ItemCount" xml:space="preserve">
<value>You have {0} item(s)</value>
<comment>{0} = number of items</comment>
</data>
</root>
```
### Accessing Resources
```csharp
// Via generated strongly-typed class (ResXFileCodeGenerator custom tool)
string welcome = Messages.Welcome;
// Via ResourceManager directly
var rm = new ResourceManager("MyApp.Resources.Messages",
typeof(Messages).Assembly);
string welcome = rm.GetString("Welcome", CultureInfo.CurrentUICulture);
```
---
## Modern Alternatives
### JSON-Based Resources
Lightweight alternative for projects already using JSON for configuration. Libraries provide `IStringLocalizer` implementations backed by JSON files.
```json
// Resources/en-US.json
{
"Welcome": "Welcome to the application",
"ItemCount": "You have {0} item(s)"
}
```
**Libraries:**
- `Senlin.Mo.Localization` -- JSON-backed `IStringLocalizer`
- `Embedded.Json.Localization` -- embedded JSON resources
JSON resources are popular in ASP.NET Core but lack the built-in tooling support (Visual Studio designer, satellite assembly compilation) of `.resx`.
### Source Generators for AOT Compatibility
Traditional `.resx` with `ResourceManager` uses reflection at runtime, which is problematic for Native AOT and trimming. Source generators eliminate runtime reflection by generating strongly-typed accessor classes at compile time.
**Recommended source generators:**
| Generator | Description | AOT-Safe |
|-----------|-------------|----------|
| ResXGenerator (ycanardeau) | Strongly-typed classes with `IStringLocalizer` support and DI registration | Yes |
| VocaDb.ResXFileCodeGenerator | Original strongly-typed `.resx` source generator | Yes |
| Built-in `ResXFileCodeGenerator` | Visual Studio custom tool (not a Roslyn source generator) | No -- generates static properties but still uses `ResourceManager` |
```xml
<!-- Using ResXGenerator -->
<ItemGroup>
<PackageReference Include="ResXGenerator" Version="1.*"
PrivateAssets="all" />
</ItemGroup>
```
```csharp
// Generated at compile time -- no runtime reflection
string welcome = Messages.Welcome;
// With DI registration (ResXGenerator)
services.AddResXLocalization();
```
**Recommendation:** Use `.resx` files as the resource format (broadest tooling support) with a source generator for AOT/trimming scenarios. Use JSON resources only for lightweight or config-heavy projects.
---
## IStringLocalizer Patterns
### Registration
```csharp
var builder = WebApplication.CreateBuilder(args);
// Register localization services
builder.Services.AddLocalization(options =>
options.ResourcesPath = "Resources");
var app = builder.Build();
// Configure request localization middleware
var supportedCultures = new[] { "en-US", "fr-FR", "de-DE", "ja-JP" };
app.UseRequestLocalization(options =>
{
options.SetDefaultCulture(supportedCultures[0])
.AddSupportedCultures(supportedCultures)
.AddSupportedUICultures(supportedCultures);
});
```
### IStringLocalizer<T>
The primary localization interface. Injectable via DI. Use everywhere: services, controllers, Blazor components, middleware.
```csharp
public class OrderService
{
private readonly IStringLocalizer<OrderService> _localizer;
public OrderService(IStringLocalizer<OrderService> localizer)
{
_localizer = localizer;
}
public string GetConfirmation(int orderId)
{
// Indexer returns LocalizedString with implicit string conversion
return _localizer["OrderConfirmed", orderId];
// Resolves: "Order {0} confirmed" with orderId substituted
}
public bool IsTranslated(string key)
{
LocalizedString result = _localizer[key];
return !result.ResourceNotFound;
}
}
```
### IViewLocalizer (MVC Razor Views Only)
Auto-resolves resource files matching the view path. Not supported in Blazor.
```cshtml
@* Views/Home/Index.cshtml *@
@inject IViewLocalizer Localizer
<h1>@Localizer["Welcome"]</h1>
<p>@Localizer["ItemCount", Model.Count]</p>
```
Resource file location: `Resources/Views/Home/Index.en-US.resx`
### IHtmlLocalizer (MVC Only)
HTML-aware variant that HTML-encodes format arguments but preserves HTML in the resource string itself. Not supported in Blazor.
```cshtml
@inject IHtmlLocalizer<SharedResource> HtmlLocalizer
@* Resource: "Read our <a href='/terms'>terms</a>, {0}" *@
@* {0} is HTML-encoded, the <a> tag is preserved *@
<p>@HtmlLocalizer["TermsNotice", Model.UserName]</p>
```
### When to Use Each
| Interface | Scope | HTML-Safe | Blazor | MVC |
|-----------|-------|-----------|--------|-----|
| `IStringLocalizer<T>` | Everywhere | No (plain text) | Yes | Yes |
| `IViewLocalizer` | View-local strings | No | **No** | Yes |
| `IHtmlLocalizer<T>` | HTML in resources | Yes | **No** | Yes |
### Namespace Resolution
If resource lookup fails, check namespace alignment. `IStringLocalizer<T>` resolves resources using the full type name of `T` relative to the `ResourcesPath`. Use `RootNamespaceAttribute` to fix namespace/assembly mismatches:
```csharp
[assembly: RootNamespace("MyApp")]
```
---
## Date, Number, and Currency Formatting
### CultureInfo
`CultureInfo` is the central class for cultRelated in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.