Generated keys: what qualifies, and what you get

The source generator ships inside both UI packages as an analyzer, together with the MSBuild wiring that feeds it. Nothing has to be configured for it to run.

Which files qualify

A .resx file produces a typed key class when all of these hold:

Requirement Why
It is the neutral file — AppStrings.resx, not AppStrings.de.resx The neutral file defines the key set; a satellite translates it
Its name has no dot before the extension A dot is how a culture is named, so My.Strings.resx cannot be told apart from a satellite of My.resx
A classic *.Designer.cs accessor sits in the same folder That file is where the generator reads the namespace and the ResourceManager property it must reference

The accessor is the one Visual Studio's and Rider's classic resx tooling writes — the PublicResXFileCodeGenerator or ResXFileCodeGenerator custom tool. The SDK's GenerateResxSource alternative writes its accessor into obj/, where it is build output rather than a file the generator can pair a .resx with, so a project using it gets no typed keys.

What becomes a key

Only string entries. An entry carrying a type or mimetype attribute — a binary resource, an image, a colour, an icon — is skipped, because its value is not a string a lookup could return.

Resource names that are not valid C# identifiers are sanitized into ones that are, and a collision that sanitizing would create is resolved by appending a number. The class is named after the file, with Keys appended, and lands in the same namespace as the resource accessor.

// <auto-generated/> - for Resources/AppStrings.resx
namespace YourApp.Resources;

public static partial class AppStringsKeys
{
    public static readonly ResourceKey Greeting = new("Greeting", AppStrings.ResourceManager);
    public static readonly ResourceKey WindowTitle = new("WindowTitle", AppStrings.ResourceManager);
    // …one ResourceKey per string entry, sorted by name.
}

Each ResourceKey carries both the key name and the ResourceManager it belongs to. That is what makes a typed lookup direct: it never searches, and two files may use the same key name without colliding.

The class is partial, so you can add members of your own to it in a file of your own.

Diagnostics

Id Meaning
RXLGEN001 An eligible .resx file is not well-formed XML. The diagnostic points at the file
RXLGEN002 An eligible .resx file has no recognizable classic accessor in its folder

RXLGEN002 is the one to expect when a project uses GenerateResxSource, or when the .Designer.cs file was deleted and the custom tool was never re-run.

The compiler floor

The generator is built against Roslyn 4.8 — the compiler in the .NET 8 SDK. A generator built against a newer Roslyn simply does not load in an older compiler: the build reports CS9057, skips generation, and then fails on the missing …Keys types. Building the generator against the floor is what keeps the packages usable on every SDK from .NET 8 upward, and CI proves it on every run by consuming the packed packages with nothing but the .NET 8 SDK installed.