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>
<ProjectReference Include="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>
<AdditionalFiles Include="**/*.resx" />
</ItemGroup>Create a resource file (e.g., Resources.resx) with your localized strings:
<?xml version="1.0" encoding="utf-8"?>
<root>
<data name="Hello" xml:space="preserve">
<value>Hello World!</value>
<comment>A greeting message</comment>
</data>
<data name="Goodbye" xml:space="preserve">
<value>Goodbye!</value>
</data>
<data name="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:
using YourNamespace;
// Access string resources directly
Console.WriteLine(Resources.Hello); // Output: Hello World!
Console.WriteLine(Resources.Goodbye); // Output: Goodbye!
// Use format strings
Console.WriteLine(string.Format(Resources.WelcomeUser, "John")); // Output: Welcome, John!For a Resources.resx file, the generator creates a Resources.g.cs file similar to:
namespace YourProjectNamespace
{
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
[GeneratedCode("GoneDotNet.Localization.SourceGenerators", "1.0.0.0")]
internal static class Resources
{
private static ResourceManager? resourceMan;
private static CultureInfo? resourceCulture;
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
internal static ResourceManager ResourceManager { get; }
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
internal static CultureInfo? Culture { get; set; }
/// <summary>
/// A greeting message
/// </summary>
internal static string Hello => 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.
using System.Globalization;
// Set a specific culture for resource lookups
Resources.Culture = new CultureInfo("fr-FR");
Console.WriteLine(Resources.Hello); // Output: Bonjour le monde! (if defined in Resources.fr.resx)
// Or change the thread's UI culture
Thread.CurrentThread.CurrentUICulture = new CultureInfo("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