Ozcorps.Localization
9.1.0
See the version list below for details.
dotnet add package Ozcorps.Localization --version 9.1.0
NuGet\Install-Package Ozcorps.Localization -Version 9.1.0
<PackageReference Include="Ozcorps.Localization" Version="9.1.0" />
<PackageVersion Include="Ozcorps.Localization" Version="9.1.0" />
<PackageReference Include="Ozcorps.Localization" />
paket add Ozcorps.Localization --version 9.1.0
#r "nuget: Ozcorps.Localization, 9.1.0"
#:package Ozcorps.Localization@9.1.0
#addin nuget:?package=Ozcorps.Localization&version=9.1.0
#tool nuget:?package=Ozcorps.Localization&version=9.1.0
Ozcorps.Localization
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 EXISTSguards) lives indocs/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/UpdateRangealso 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 | Versions 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. |
-
net8.0
- Microsoft.Extensions.Caching.Memory (>= 8.0.1)
- Npgsql.EntityFrameworkCore.PostgreSQL (>= 8.0.11)
- Ozcorps.Generic (>= 9.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
9.1.0: Added bulk operations (AddRange, UpdateRange) and translation versioning with full revision history and rollback for language words.