J18n.Analyzers 1.2.1

dotnet add package J18n.Analyzers --version 1.2.1
                    
NuGet\Install-Package J18n.Analyzers -Version 1.2.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="J18n.Analyzers" Version="1.2.1">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="J18n.Analyzers" Version="1.2.1" />
                    
Directory.Packages.props
<PackageReference Include="J18n.Analyzers">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add J18n.Analyzers --version 1.2.1
                    
#r "nuget: J18n.Analyzers, 1.2.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package J18n.Analyzers@1.2.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=J18n.Analyzers&version=1.2.1
                    
Install as a Cake Addin
#tool nuget:?package=J18n.Analyzers&version=1.2.1
                    
Install as a Cake Tool

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
  • Nested JSON support with automatic flattening using dot notation (e.g., "User.Profile.Name")
  • Array handling with indexed access (e.g., "Messages[0]", "Items[1].Name")
  • 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
  • Roslyn analyzers for compile-time validation and code fixes
  • Comprehensive XML documentation
  • Extensive test coverage

Installation

Package NuGet
J18n nuget
J18n.Analyzers nuget
J18n.SourceGenerators nuget

Install the main package via NuGet Package Manager:

dotnet add package J18n

Or via Package Manager Console:

Install-Package J18n

Optional: Roslyn Analyzers

For compile-time validation and code fixes, also install the analyzers package:

dotnet add package J18n.Analyzers

Or via Package Manager Console:

Install-Package J18n.Analyzers

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 support both flat key-value pairs and nested object structures. Nested objects are automatically flattened using dot notation for easy access.

{
  "WelcomeMessage": "Welcome to our app!",
  "User": {
    "Profile": {
      "Greeting": "Hello, {0}!",
      "Settings": {
        "Language": "English"
      }
    }
  },
  "GoodbyeMessage": "See you later!"
}

Accessing Nested Values

Nested values are accessed using dot notation:

var welcome = localizer["WelcomeMessage"];

// Nested object access
var greeting = localizer["User.Profile.Greeting", "John"];
var language = localizer["User.Profile.Settings.Language"];
var status = localizer["User.Account.Status"];

// Array access with indexes
var firstMessage = localizer["Messages[0]"];
var secondMessage = localizer["Messages[1]"];

Culture Fallback

The library follows standard .NET culture fallback patterns:

  1. Specific culture (e.g., en-US)
  2. Parent culture (e.g., en)
  3. English as final fallback
  4. 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

Source Generators (J18n.SourceGenerator)

The J18n.SourceGenerators package provides compile-time code generation for strongly-typed access to your JSON localization keys.

Features

  • Strongly-typed access: Generates classes with properties for each localization key
  • Compile-time safety: Eliminates runtime string key errors

Setup

  1. Install the source generator package:

    dotnet add package J18n.SourceGenerator
    
  2. Include your JSON localization files as AdditionalFiles in your project:

    <ItemGroup>
      <AdditionalFiles Include="Resources/**/*.json" />
    </ItemGroup>
    
  3. Use the generated strongly-typed classes:

    // Instead of: _localizer["WelcomeMessage"]
    // Use: _localizer[Messages.WelcomeMessage]
    var welcome = _localizer[Messages.WelcomeMessage];
    var greeting = _localizer[Messages.User.Profile.Greeting, "John"];
    

Roslyn Analyzers (J18n.Analyzers)

The J18n.Analyzers package provides compile-time validation and code fixes for your JSON localization keys.

Features

  • Missing Key Detection (LOC001): Identifies localization keys referenced in code but missing from JSON files
  • Unused Key Detection (LOC002): Finds keys defined in JSON files but never used in code
  • Partial Missing Keys (LOC003): Detects keys missing in some cultures but present in others
  • Duplicate Key Detection (LOC004): Identifies duplicate keys within the same JSON file
  • Code Fixes: Automatic suggestions for missing keys with nearest matches

Setup

  1. Install the analyzer package:

    dotnet add package J18n.Analyzers
    
  2. Include your JSON localization files as AdditionalFiles in your project:

    <ItemGroup>
      <AdditionalFiles Include="Resources/**/*.json" />
    </ItemGroup>
    

Diagnostic Rules

Rule Severity Description
LOC001 Error Referenced localization key not found in any culture
LOC002 Warning Localization key defined but never used
LOC003 Warning Key missing in some cultures but present in others
LOC004 Error Duplicate key definition in the same JSON file

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

  1. Fork the repository
  2. Create a feature branch
  3. Add tests for new functionality
  4. Ensure all tests pass
  5. 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.

There are no supported framework assets in this package.

Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.2.1 208 8/24/2025
1.2.0 132 8/24/2025
1.1.1 78 8/23/2025
1.1.0 75 8/23/2025