Ozcorps.Localization 9.1.1

dotnet add package Ozcorps.Localization --version 9.1.1
                    
NuGet\Install-Package Ozcorps.Localization -Version 9.1.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="Ozcorps.Localization" Version="9.1.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Ozcorps.Localization" Version="9.1.1" />
                    
Directory.Packages.props
<PackageReference Include="Ozcorps.Localization" />
                    
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 Ozcorps.Localization --version 9.1.1
                    
#r "nuget: Ozcorps.Localization, 9.1.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 Ozcorps.Localization@9.1.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=Ozcorps.Localization&version=9.1.1
                    
Install as a Cake Addin
#tool nuget:?package=Ozcorps.Localization&version=9.1.1
                    
Install as a Cake Tool

Ozcorps.Localization

NuGet License: MIT .NET

A lightweight, database-driven localization library for .NET 8. Manages multilingual translations stored in PostgreSQL, with built-in in-memory caching, platform-based word filtering, and full CRUD services for languages and translations.


Features

  • Database-driven translations (no JSON/RESX files needed)
  • Supports PostgreSQL (Npgsql)
  • In-memory caching with configurable expiration (default: 30 minutes)
  • Platform-based word filtering via PlatformId
  • Full CRUD services: ILanguageService, ILanguageWordService, ILanguageWordTypeService
  • Bulk operations for translations (AddRange, UpdateRange)
  • Translation versioning — every change is snapshotted, with full history and rollback
  • Simple DI setup with a single extension method call

Installation

dotnet add package Ozcorps.Localization

Database Setup

The library expects four tables: language, language_word, language_word_type, and language_word_revision (translation version history).

PostgreSQL example:

CREATE TABLE language (
    id          UUID PRIMARY KEY,
    key         VARCHAR(200),
    name        VARCHAR(300),
    is_active   BOOLEAN DEFAULT true,
    is_deleted  BOOLEAN DEFAULT false,
    created_at  TIMESTAMP WITHOUT TIME ZONE,
    created_by_id UUID,
    updated_at  TIMESTAMP WITHOUT TIME ZONE,
    updated_by_id UUID
);

CREATE TABLE language_word_type (
    id          UUID PRIMARY KEY,
    name        VARCHAR(300),
    is_active   BOOLEAN DEFAULT true,
    is_deleted  BOOLEAN DEFAULT false,
    created_at  TIMESTAMP WITHOUT TIME ZONE,
    created_by_id UUID,
    updated_at  TIMESTAMP WITHOUT TIME ZONE,
    updated_by_id UUID
);

CREATE TABLE language_word (
    id                   UUID PRIMARY KEY,
    language_id          UUID,
    language_word_type_id UUID,
    platform_id          BIGINT NOT NULL DEFAULT 1,
    key                  VARCHAR(200),
    value                VARCHAR(300),
    is_active            BOOLEAN DEFAULT true,
    is_deleted           BOOLEAN DEFAULT false,
    created_at           TIMESTAMP WITHOUT TIME ZONE,
    created_by_id        UUID,
    updated_at           TIMESTAMP WITHOUT TIME ZONE,
    updated_by_id        UUID
);

CREATE TABLE language_word_revision (
    id                    UUID PRIMARY KEY,
    language_word_id      UUID NOT NULL,
    revision_number       INTEGER NOT NULL,
    operation             VARCHAR(20) NOT NULL,   -- Insert | Update | Delete | Rollback
    language_id           UUID NOT NULL,
    language_word_type_id UUID NOT NULL,
    platform_id           BIGINT NOT NULL DEFAULT 1,
    key                   VARCHAR(200),
    value                 VARCHAR(300),
    is_active             BOOLEAN DEFAULT true,
    is_deleted            BOOLEAN DEFAULT false,
    changed_by_id         UUID NOT NULL,
    changed_at            TIMESTAMP WITHOUT TIME ZONE,
    CONSTRAINT fk_language_word_revision_word
        FOREIGN KEY (language_word_id) REFERENCES language_word (id),
    CONSTRAINT uq_language_word_revision_number
        UNIQUE (language_word_id, revision_number)
);

The full script (with IF NOT EXISTS guards) lives in docs/create-scripts.sql.

Sample data:

INSERT INTO language (id, key, name, is_active, is_deleted, created_at, created_by_id)
VALUES (gen_random_uuid(), 'tr', 'Türkçe', true, false, now(), gen_random_uuid());

INSERT INTO language (id, key, name, is_active, is_deleted, created_at, created_by_id)
VALUES (gen_random_uuid(), 'en', 'English', true, false, now(), gen_random_uuid());

Registration

builder.Services.AddLocalization("Host=localhost;Database=mydb;Username=user;Password=pass");

Accepts an optional shouldAddLanguageServices parameter (default: true). Set it to false if you only need LocalizationTool without the CRUD services.

// Only LocalizationTool, no CRUD services
builder.Services.AddLocalization(connectionString, shouldAddLanguageServices: false);

Usage

Inject LocalizationTool

public class ProductController : ControllerBase
{
    private readonly LocalizationTool _localization;

    public ProductController(LocalizationTool localization)
    {
        _localization = localization;
    }

    [HttpGet]
    public IActionResult Get([FromQuery] string lang = "tr")
    {
        var message = _localization.Get(lang, "welcome_message");
        return Ok(message);
    }
}

Get all words for a language (dictionary)

// Get all words
var words = _localization.GetWords("en");

// Get words filtered by platform
var words = _localization.GetWords("en", platformId: 2);

Clear the cache

_localization.Refresh();

CRUD Services

When shouldAddLanguageServices: true (default), three services are registered:

Interface Description
ILanguageService Manage languages (add, update, remove, paginate)
ILanguageWordService Manage translation entries (incl. bulk operations and versioning)
ILanguageWordTypeService Manage word type categories

Each service provides: Get, GetAll, Add, Update, Remove, Paginate, Any.

Bulk operations (ILanguageWordService)

Insert or update many translations in a single round-trip:

var added = _languageWordService.AddRange(dtos, userId);
var updated = _languageWordService.UpdateRange(dtos, userId);

Translation Versioning

Every change to a translation through ILanguageWordService is automatically snapshotted into the language_word_revision table. Each word keeps a sequential revision_number starting at 1, together with the operation that produced it (Insert, Update, Delete, Rollback), the full content snapshot, and who changed it.

// Full history of a word, oldest revision first
List<LanguageWordRevisionDto> history = _languageWordService.GetHistory(wordId);

// Restore a word's content to a previous revision.
// This is itself recorded as a new "Rollback" revision (non-destructive).
LanguageWordDto restored = _languageWordService.Rollback(wordId, revisionNumber: 1, userId);

Notes:

  • AddRange / UpdateRange also record revisions for every affected word.
  • Rollback restores only the content fields (Key, Value, LanguageId, LanguageWordTypeId, PlatformId); it does not resurrect a soft-deleted word.

Configuration Summary

Extension Method Database Cache CRUD Services
AddLocalization PostgreSQL IMemoryCache (30 min) Optional

License

MIT

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  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. 
Compatible target framework(s)
Included target framework(s) (in 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
9.1.1 47 6/19/2026
9.1.0 44 6/19/2026
9.0.1 203 4/13/2026
9.0.0 108 4/12/2026
8.0.0 2,624 12/3/2024
1.1.2 558 7/11/2024
1.1.1 158 7/10/2024
1.1.0 168 7/9/2024
1.0.0 185 7/4/2024

9.1.1: Fixed an "is not a property accessor" error thrown during model build (e.g. EnsureCreated) caused by an anonymous-type expression in the revision index; switched to the obfuscation-safe string-based HasIndex overload.