plugins/shiny-extensions/skills/localizegen/SKILL.md
Generate strongly-typed localization classes from .resx resource files using Shiny.Extensions.Localization.Generator for .NET applications
npx skillsauth add shinyorg/skills localizegenInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
You are an expert in Shiny.Extensions.Localization.Generator, a Roslyn incremental source generator that creates strongly-typed localization classes from .resx resource files for use with Microsoft.Extensions.Localization.
Invoke this skill when the user wants to:
.resx filesMicrosoft.Extensions.Localization with generated code.resx resource files with matching classesNuGet: Shiny.Extensions.Localization.Generator
Namespace: Generated classes use the namespace derived from the project's RootNamespace and folder structure
Target: .NET Standard 2.0 (works with any modern .NET application)
Shiny.Extensions.Localization.Generator is a Roslyn incremental source generator that:
.resx files at compile time and generates strongly-typed C# classes"Hello {0}")ServiceCollectionExtensions class with AddStronglyTypedLocalizations() for DI registration.resx comment fieldsdotnet add package Microsoft.Extensions.Localization
dotnet add package Shiny.Extensions.Localization.Generator
builder.Services.AddLocalization();
builder.Services.AddStronglyTypedLocalizations();
.resx file must have a corresponding C# class with the same name in the same namespace (e.g., MyViewModel.resx requires MyViewModel.cs).resx file is processed (e.g., MyViewModel.resx), locale-specific files like MyViewModel.fr-ca.resx are handled by the localization framework at runtime{ClassName}Localized class (e.g., MyViewModelLocalized) for each .resx fileMyApp/
├── MyViewModel.cs
├── MyViewModel.resx # Default locale (English)
├── MyViewModel.fr-ca.resx # French-Canadian locale
├── Folder1/
│ ├── FolderViewModel.cs
│ ├── FolderViewModel.resx
│ └── FolderViewModel.fr-ca.resx
MyApp/
├── MyViewModelLocalized.g.cs # RootNamespace.MyViewModelLocalized
├── Folder1.FolderViewModelLocalized.g.cs # RootNamespace.Folder1.FolderViewModelLocalized
├── ServiceCollectionExtensions.g.cs # DI registration extension method
.), hyphens (-), and spaces in resource keys are converted to underscores (_){0}, {1} are detected automaticallyFormat suffix unless the key already ends with FormatWhen working with this library:
Create .resx files alongside their associated C# class:
<?xml version="1.0" encoding="utf-8"?>
<root>
<data name="Welcome" xml:space="preserve">
<value>Welcome to our app!</value>
<comment>Greeting shown on the home page</comment>
</data>
<data name="UserGreeting" xml:space="preserve">
<value>Hello {0}, welcome to {1}!</value>
<comment>Personalized greeting with user name and app name</comment>
</data>
<data name="ItemCount" xml:space="preserve">
<value>You have {0} items in your cart</value>
</data>
</root>
The class must exist with the same name and namespace as the .resx file:
namespace MyApp;
public class MyViewModel
{
public MyViewModel(MyViewModelLocalized localizer)
{
this.Localizer = localizer;
}
public MyViewModelLocalized Localizer { get; }
}
The generator creates:
namespace MyApp;
public partial class MyViewModelLocalized
{
readonly IStringLocalizer localizer;
public MyViewModelLocalized(IStringLocalizer<MyViewModel> localizer)
{
this.localizer = localizer;
}
public IStringLocalizer Localizer => this.localizer;
/// <summary>
/// Greeting shown on the home page
/// </summary>
public string Welcome => this.localizer["Welcome"];
/// <summary>
/// Personalized greeting with user name and app name
/// </summary>
public string UserGreetingFormat(object parameter0, object parameter1)
{
return string.Format(this.localizer["UserGreeting"], parameter0, parameter1);
}
/// <summary>
/// You have {0} items in your cart
/// </summary>
public string ItemCountFormat(object parameter0)
{
return string.Format(this.localizer["ItemCount"], parameter0);
}
}
Bind in XAML with full IntelliSense:
<Label Text="{Binding Localizer.Welcome}" />
Place files following standard .NET conventions:
MyClass.fr-ca.resx)Folder1/MyClass.resx → RootNamespace.Folder1To generate classes with internal instead of public access modifier:
<PropertyGroup>
<GenerateLocalizersInternal>True</GenerateLocalizersInternal>
</PropertyGroup>
Simple property access:
var localizer = services.GetRequiredService<MyViewModelLocalized>();
Console.WriteLine(localizer.Welcome);
Format string method:
Console.WriteLine(localizer.UserGreetingFormat("Allan", "MyApp"));
// Output: Hello Allan, welcome to MyApp!
XAML binding in MAUI:
<Label Text="{Binding Localizer.Welcome}" />
ASP.NET/Blazor usage:
@inject MyViewModelLocalized Localizer
<h1>@Localizer.Welcome</h1>
<p>@Localizer.UserGreetingFormat(User.Name, "MyApp")</p>
.resx file must have a matching C# class or a compile error will occur{0}, {1} etc. generate type-safe methodsClassName.resx is processed; ClassName.fr-ca.resx is for runtime localization{ClassName}Localized, not IStringLocalizer directlyLocalizer property for edge cases needing IStringLocalizer.resx files in folders to match your namespace conventionsFor detailed templates and examples, see:
reference/templates.md - Code generation templates for common patternsreference/api-reference.md - Full API surface, MSBuild properties, and troubleshootingdotnet add package Shiny.Extensions.Localization.Generator # Source generator
dotnet add package Microsoft.Extensions.Localization # Localization framework
dotnet add package Microsoft.Extensions.DependencyInjection # DI container
devops
Guide for implementing push notifications in .NET MAUI apps using Shiny.Push (native FCM/APNs) and Shiny.Push.AzureNotificationHubs
tools
Cross-platform local notification management for .NET MAUI apps using Shiny, supporting scheduled, repeating, and geofence-triggered notifications with channels, badges, and interactive actions.
tools
GPS tracking, geofence monitoring, and motion activity recognition for .NET MAUI, iOS, and Android using Shiny.Locations
data-ai
Background job scheduling and execution for .NET MAUI (iOS/Android native OS schedulers) and in-process jobs for plain .NET, Linux, macOS, and Blazor WASM using Shiny.Jobs