Skip to content

Repository files navigation

GoneDotNet.Localization.SourceGenerators

A Roslyn source generator that automatically generates strongly-typed C# classes from .resx resource files at compile time. This eliminates the need for the traditional ResXFileCodeGenerator custom tool and provides a modern, incremental source generation approach.

Features

  • Compile-time code generation - No runtime reflection overhead
  • Incremental generation - Only regenerates when .resx files change
  • Culture-specific file support - Automatically skips culture-specific files (e.g., Strings.fr.resx)
  • Strongly-typed access - Full IntelliSense and compile-time error checking
  • XML documentation - Generated properties include XML comments from .resx file comments
  • Special character handling - Properly escapes special characters in resource names and values
  • C# keyword handling - Automatically prefixes C# keywords with @

TODOs

  • Better Namespace support (use RootNamespace)
  • Support for custom access modifiers (e.g., public, internal)

Installation

Project Reference (for development)

Add a project reference to your consuming project:

<ItemGroup>
<ProjectReferenceInclude="path\to\GoneDotNet.Localization.SourceGenerators.csproj"OutputItemType="Analyzer"ReferenceOutputAssembly="false" />
</ItemGroup>

NuGet Package (when published)

dotnet add package GoneDotNet.Localization.SourceGenerators

Usage

1. Add your .resx files as AdditionalFiles

In your project file (.csproj), add the following to include .resx files for the source generator:

<ItemGroup>
<AdditionalFilesInclude="**/*.resx" />
</ItemGroup>

2. Create a .resx file

Create a resource file (e.g., Resources.resx) with your localized strings:

<?xml version="1.0" encoding="utf-8"?>
<root>
<dataname="Hello"xml:space="preserve">
<value>Hello World!</value>
<comment>A greeting message</comment>
</data>
<dataname="Goodbye"xml:space="preserve">
<value>Goodbye!</value>
</data>
<dataname="WelcomeUser"xml:space="preserve">
<value>Welcome, {0}!</value>
<comment>A welcome message with a placeholder for the user name</comment>
</data>
</root>

3. Use the generated class

The source generator automatically creates a strongly-typed class matching your .resx filename:

usingYourNamespace;// Access string resources directlyConsole.WriteLine(Resources.Hello);// Output: Hello World!Console.WriteLine(Resources.Goodbye);// Output: Goodbye!// Use format stringsConsole.WriteLine(string.Format(Resources.WelcomeUser,"John"));// Output: Welcome, John!

Generated Code

For a Resources.resx file, the generator creates a Resources.g.cs file similar to:

namespaceYourProjectNamespace{/// <summary>/// A strongly-typed resource class, for looking up localized strings, etc./// </summary>[GeneratedCode("GoneDotNet.Localization.SourceGenerators","1.0.0.0")]internalstaticclassResources{privatestaticResourceManager?resourceMan;privatestaticCultureInfo?resourceCulture;/// <summary>/// Returns the cached ResourceManager instance used by this class./// </summary>internalstaticResourceManagerResourceManager{get;}/// <summary>/// Overrides the current thread's CurrentUICulture property for all/// resource lookups using this strongly typed resource class./// </summary>internalstaticCultureInfo?Culture{get;set;}/// <summary>/// A greeting message/// </summary>internalstaticstringHello=>ResourceManager.GetString("Hello",resourceCulture)??string.Empty;// ... additional properties}}

Localization Support

To add translations, create culture-specific .resx files following the naming convention:

Resources.resx # Default/fallback resources
Resources.fr.resx # French translations
Resources.de.resx # German translations
Resources.es-MX.resx # Mexican Spanish translations

The source generator automatically detects and skips culture-specific files (they don't need separate generated classes). The .NET runtime handles loading the appropriate culture-specific resources automatically based on Thread.CurrentThread.CurrentUICulture.

Changing the Culture at Runtime

usingSystem.Globalization;// Set a specific culture for resource lookupsResources.Culture=newCultureInfo("fr-FR");Console.WriteLine(Resources.Hello);// Output: Bonjour le monde! (if defined in Resources.fr.resx)// Or change the thread's UI cultureThread.CurrentThread.CurrentUICulture=newCultureInfo("de-DE");Console.WriteLine(Resources.Hello);// Uses German translation

Requirements

  • .NET SDK 6.0 or later (for consuming projects)
  • The source generator targets netstandard2.0 for broad compatibility

Project Structure

GoneDotNet.Localization.SourceGenerators/
├── GoneDotNet.Localization.SourceGenerators/ # The source generator library
│ ├── ResxSourceGenerator.cs # Main generator implementation
│ └── GoneDotNet.Localization.SourceGenerators.csproj
├── GoneDotNet.Localization.SourceGenerators.Sample/ # Sample usage project
│ ├── Program.cs
│ ├── Resources.resx
│ └── Strings.resx
└── GoneDotNet.Localization.SourceGenerators.Tests/ # Unit tests
└── ResxSourceGeneratorTests.cs

License

MIT License

About

Replace the old dinosaur RESX tooling

Resources

Stars

6 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages