J18n 1.0.0
See the version list below for details.
dotnet add package J18n --version 1.0.0
NuGet\Install-Package J18n -Version 1.0.0
<PackageReference Include="J18n" Version="1.0.0" />
<PackageVersion Include="J18n" Version="1.0.0" />
<PackageReference Include="J18n" />
paket add J18n --version 1.0.0
#r "nuget: J18n, 1.0.0"
#:package J18n@1.0.0
#addin nuget:?package=J18n&version=1.0.0
#tool nuget:?package=J18n&version=1.0.0
J18n
A JSON-based localization library for .NET that provides a drop-in replacement for resx-based resources, fully compatible with IStringLocalizer<T>
and the Microsoft.Extensions.Localization ecosystem.
Features
- Drop-in replacement for resx resources using JSON files
- Full compatibility with
IStringLocalizer<T>
and Microsoft.Extensions.Localization - Culture hierarchy fallback (specific → parent → English)
- Parameterized string formatting using .NET composite format syntax
- Thread-safe operations with built-in caching for optimal performance
- Graceful fallback for missing keys (returns key name)
- Easy dependency injection integration
- Comprehensive XML documentation
- Extensive test coverage
Installation
Install the package via NuGet Package Manager:
dotnet add package J18n
Or via Package Manager Console:
Install-Package J18n
Quick Start
1. Set up JSON resource files
Create JSON files in your Resources directory following the naming convention {ResourceName}.{Culture}.json
:
Resources/
├── Messages.en.json
├── Messages.es.json
├── Messages.fr.json
└── Errors.en.json
Note: Unlike resx files, JSON resource files only need to be set as "Copy to Output Directory" in their build action. They do not need to be embedded resources.
Example Messages.en.json
:
{
"WelcomeMessage": "Welcome to our application!",
"HelloUser": "Hello, {0}!",
"ItemCount": "You have {0:N0} items",
"ValidationError": "The field {0} is required"
}
2. Register services
In your Program.cs
or Startup.cs
:
var builder = WebApplication.CreateBuilder(args);
// Simple registration with default options
builder.Services.AddJsonLocalization();
// Or with custom configuration
builder.Services.AddJsonLocalization(options =>
{
options.ResourcesRelativePath = "Localization/Resources";
});
var app = builder.Build();
3. Use in your application
public class HomeController : ControllerBase
{
private readonly IStringLocalizer<Messages> _localizer;
public HomeController(IStringLocalizer<Messages> localizer)
{
_localizer = localizer;
}
public IActionResult Index()
{
// Simple string
var welcome = _localizer["WelcomeMessage"];
// Parameterized string
var greeting = _localizer["HelloUser", User.Identity.Name];
// Formatted numbers
var itemCount = _localizer["ItemCount", 1234];
return View(new { welcome, greeting, itemCount });
}
}
Configuration Options
Default Configuration
services.AddJsonLocalization();
This uses:
- Resources directory:
Resources/
(relative to current directory) - Default fallback behavior
Custom Resource Path
services.AddJsonLocalization(options =>
{
options.ResourcesRelativePath = "Localization/Messages";
// or
options.ResourcesPath = "/absolute/path/to/resources";
});
Custom File Provider
var customFileProvider = new PhysicalFileProvider("/custom/path");
services.AddJsonLocalization(customFileProvider, "Resources");
Resource File Format
JSON resource files should contain key-value pairs where values can include .NET composite format placeholders:
{
"SimpleMessage": "Hello World",
"ParameterizedMessage": "Hello, {0}!",
"MultipleParameters": "User {0} has {1} items",
"FormattedNumber": "Price: {0:C}",
"FormattedDate": "Today is {0:yyyy-MM-dd}",
"SpecialCharacters": "Café, naïve, résumé",
"LongText": "This is a longer message that can span multiple lines and contain complex formatting."
}
Culture Fallback
The library follows standard .NET culture fallback patterns:
- Specific culture (e.g.,
en-US
) - Parent culture (e.g.,
en
) - English as final fallback
- Key name if no translation found
Example with CultureInfo.CurrentUICulture = new CultureInfo("es-MX")
:
Resources/
├── Messages.es-MX.json ← First choice
├── Messages.es.json ← Second choice
├── Messages.en.json ← Third choice
└── Messages.json ← Final fallback
Advanced Usage
Getting All Strings
var allStrings = localizer.GetAllStrings(includeParentCultures: true);
foreach (var localizedString in allStrings)
{
Console.WriteLine($"{localizedString.Name}: {localizedString.Value}");
}
Checking if Resource was Found
var localized = localizer["SomeKey"];
if (localized.ResourceNotFound)
{
// Handle missing translation
Console.WriteLine($"Missing translation for key: {localized.Name}");
}
Using with Dependency Injection
public class EmailService
{
private readonly IStringLocalizer<EmailService> _localizer;
public EmailService(IStringLocalizer<EmailService> localizer)
{
_localizer = localizer;
}
public async Task SendWelcomeEmailAsync(string email, string name)
{
var subject = _localizer["WelcomeEmailSubject"];
var body = _localizer["WelcomeEmailBody", name];
await SendEmailAsync(email, subject, body);
}
}
Performance Considerations
- Resources are cached after first load for optimal performance
- Thread-safe operations allow concurrent access
- Lazy loading - resources loaded only when first accessed
- Memory efficient - shares resources across localizer instances
Compatibility
- .NET 9.0 and later
- Microsoft.Extensions.Localization 9.0.8
- System.Text.Json for JSON parsing
- Full compatibility with existing
IStringLocalizer<T>
implementations
Contributing
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Ensure all tests pass
- Submit a pull request
Testing
Run the test suite:
dotnet test
The project includes comprehensive tests covering:
- Basic localization functionality
- Culture fallback scenarios
- Parameterized strings
- Error handling
- Dependency injection integration
License
This project is licensed under the GNU General Public License v3.0 - see the LICENSE file for details.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net9.0 is compatible. 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. |
-
net9.0
- Microsoft.Extensions.DependencyInjection (>= 9.0.8)
- Microsoft.Extensions.FileProviders.Physical (>= 9.0.8)
- Microsoft.Extensions.Localization (>= 9.0.8)
- System.Text.Json (>= 9.0.8)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.