Senlinz.Localization
1.0.0
See the version list below for details.
dotnet add package Senlinz.Localization --version 1.0.0
NuGet\Install-Package Senlinz.Localization -Version 1.0.0
<PackageReference Include="Senlinz.Localization" Version="1.0.0" />
<PackageVersion Include="Senlinz.Localization" Version="1.0.0" />
<PackageReference Include="Senlinz.Localization" />
paket add Senlinz.Localization --version 1.0.0
#r "nuget: Senlinz.Localization, 1.0.0"
#:package Senlinz.Localization@1.0.0
#addin nuget:?package=Senlinz.Localization&version=1.0.0
#tool nuget:?package=Senlinz.Localization&version=1.0.0
Senlinz.Localization
English | Chinese
A JSON-driven localization source generator for .NET that generates strongly typed localization accessors, resource base classes, and enum-to-localization helpers.
Supports .NET 6 and newer consumer projects.
Features
- Generate
Laccessors froml.json. - Generate
LResourcebase classes for culture-specific resource implementations. - Resolve localized text through
LString,LStringResolver, andLResourceProvider. - Convert enum values to localization keys with
[LString]and[LStringKey]. - Publish
Senlinz.LocalizationandSenlinz.Localization.Abstractionsas separate NuGet packages with a shared embedded package icon.
Package selection
Senlinz.Localization
Use this package in consumer projects that need source generation from JSON.
dotnet add package Senlinz.Localization
Senlinz.Localization.Abstractions
Use this package only when you need the shared runtime contracts and helpers without the source generator.
dotnet add package Senlinz.Localization.Abstractions
Quick start
1. Create the localization file
Create l.json in your project root.
{
"hello": "Hello",
"sayHelloTo": "Hello {name}!",
"statusReady": "Ready",
"UserType_Teacher": "Teacher",
"UserType_Student": "Student"
}
2. Register the file in the project
<ItemGroup>
<AdditionalFiles Include="l.json" />
<None Update="l.json" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
AdditionalFileslets the source generator read the file during compilation.CopyToOutputDirectoryis useful when the application also wants to ship the JSON file.
3. Use generated members
After build, the generator creates strongly typed members from each JSON key.
Console.WriteLine(L.Hello);
Console.WriteLine(L.SayHelloTo("World"));
hellobecomesL.Hello.sayHelloTobecomesL.SayHelloTo(string name).
Localization file rules
Key format
- JSON keys are converted into generated C# member names.
- Keep keys stable because generated API names depend on them.
Placeholder parameters
Placeholders inside values become method parameters.
{
"welcomeUser": "Welcome {userName}",
"orderSummary": "Order {orderId} for {customerName}"
}
Generated usage:
var message1 = L.WelcomeUser("Alice");
var message2 = L.OrderSummary("SO-001", "Alice");
Escaping placeholders
- If you want to keep braces as literal text instead of generating a parameter, prefix the placeholder name with
$.
{
"templateTip": "Use {$name} as a placeholder in your template."
}
- The generated default text becomes
Use {name} as a placeholder in your template.
Custom file name
If you do not want to use l.json, set SenlinzLocalizationFile in your project file.
<PropertyGroup>
<SenlinzLocalizationFile>localization.json</SenlinzLocalizationFile>
</PropertyGroup>
<ItemGroup>
<AdditionalFiles Include="localization.json" />
<None Update="localization.json" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
Generated types
L
Lcontains strongly typed accessors for every key in the localization JSON.- Plain values generate properties, and values with placeholders generate methods.
LResource
LResourceis a generated abstract base class with one protected abstract member per localization key.- Implement one derived class per culture.
Example:
using Senlinz.Localization;
public sealed class EnResource : LResource
{
public override string Culture => "en";
protected override string Hello => "Hello";
protected override string SayHelloTo => "Hello {name}!";
protected override string StatusReady => "Ready";
}
public sealed class ZhResource : LResource
{
public override string Culture => "zh";
protected override string Hello => "你好";
protected override string SayHelloTo => "你好,{name}!";
protected override string StatusReady => "就绪";
}
LString
LStringcarries the localization key, fallback text, and runtime arguments.- You normally get
LStringvalues from generatedLmembers or from enum extensions.
Resolve localized values
Use LResourceProvider to hold resources and LStringResolver to resolve text for the current culture.
using Senlinz.Localization;
var currentCulture = "zh";
var provider = new LResourceProvider(new EnResource(), new ZhResource());
var resolver = new LStringResolver(() => currentCulture, provider.GetResource);
Console.WriteLine(resolver[L.Hello]);
Console.WriteLine(resolver[L.SayHelloTo("世界")]);
You can also call the extension method:
var text = resolver.Resolve(L.Hello);
Fallback behavior
- If no resource exists for the current culture, the default text from
l.jsonis used. - If a resource exists but does not contain a key, the default text is also used.
Enum localization
[LString]
Apply [LString] to an enum to generate a ToLString() extension method.
[LString]
public enum UserType
{
Teacher,
Student
}
- This generates
UserTypeExtensions.ToLString(this UserType value). - By default, the generated key pattern is
<EnumName>_<MemberName>.
For the enum above, the expected localization keys are typically:
{
"UserType_Teacher": "Teacher",
"UserType_Student": "Student"
}
[LStringKey]
Use [LStringKey] on enum members when you want to map to an existing localization key.
[LString]
public enum UserType
{
[LStringKey("teacher")]
Teacher,
[LStringKey("student")]
Student
}
[LStringKey] replaces only the enum member portion of the generated key. The enum prefix and separator are still kept.
Matching JSON:
{
"UserType_teacher": "Teacher",
"UserType_student": "Student"
}
If you pass the full key explicitly, it is used as-is and the prefix is not duplicated:
[LString]
public enum UserType
{
[LStringKey("UserType_Teacher")]
Teacher,
[LStringKey("UserType_Student")]
Student
}
Usage:
var text = UserType.Student.ToLString();
Console.WriteLine(resolver[text]);
Custom separator
LStringAttribute accepts an optional separator value.
[LString("_")]
public enum OrderStatus
{
Pending,
Completed
}
- Choose a separator that keeps the generated member name valid in C#, such as
_. - Use
[LStringKey]when you want to customize the enum member segment while keeping the enum prefix.
End-to-end example
l.json
{
"hello": "Hello",
"sayHelloTo": "Hello {name}!",
"UserType_Teacher": "Teacher",
"UserType_Student": "Student"
}
Enum
[LString]
public enum UserType
{
Teacher,
Student
}
Resources and resolver
using Senlinz.Localization;
var currentCulture = "zh";
var provider = new LResourceProvider(new ZhResource());
var resolver = new LStringResolver(() => currentCulture, provider.GetResource);
Console.WriteLine(resolver[L.Hello]);
Console.WriteLine(resolver[L.SayHelloTo("世界")]);
Console.WriteLine(resolver[UserType.Student.ToLString()]);
public sealed class ZhResource : LResource
{
public override string Culture => "zh";
protected override string Hello => "你好";
protected override string SayHelloTo => "你好,{name}!";
protected override string UserTypeTeacher => "老师";
protected override string UserTypeStudent => "学生";
}
Expected output:
你好
你好,世界!
学生
Release packages
- Every push and pull request runs the validation workflow to restore, build, test, and pack the solution, then uploads the generated package artifacts.
- Create and push a version tag such as
v1.0.0to trigger the publish workflow.
- Validate the solution.
dotnet test Senlinz.Localization.slnx --configuration Release - Pack locally if needed.
dotnet pack Senlinz.Localization.slnx --configuration Release --output artifacts - The
ValidateGitHub Actions workflow should pass before you cut a release tag. - Local and CI pack operations produce
.nupkgartifacts and any available.snupkgsymbol artifacts, embed the shared package icon, and the validation workflow uploads them for inspection. - The
Publish NuGet packagesworkflow uploads the generated release artifacts, then publishes the primary packages and any generated symbol packages when the tag build succeeds.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Stable release with bundled Senlinz.Localization.Abstractions support.