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.
- ✅ 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
@
- Better Namespace support (use RootNamespace)
- Support for custom access modifiers (e.g., public, internal)
Add a project reference to your consuming project:
<ItemGroup>
<ProjectReferenceInclude="path\to\GoneDotNet.Localization.SourceGenerators.csproj"OutputItemType="Analyzer"ReferenceOutputAssembly="false" />
</ItemGroup>dotnet add package GoneDotNet.Localization.SourceGeneratorsIn your project file (.csproj), add the following to include .resx files for the source generator:
<ItemGroup>
<AdditionalFilesInclude="**/*.resx" />
</ItemGroup>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>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!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}}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.
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- .NET SDK 6.0 or later (for consuming projects)
- The source generator targets
netstandard2.0for broad compatibility
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
MIT License