Databaseβbacked localization for .NET with multiβtenant support, EF Core integration, culture fallback, and export/import tooling.
Designed for:
- Multi-tenant systems
- EF Core
- Clean Architecture
- NuGet distribution
- Admin UI via a separate RCL (
Geaux.Localization.Admin)
- Database-backed translations (EF Core)
- Tenant-aware localization (
TenantId) - Culture fallback support
- Attribute-based model localization via
[Localized] - EF Core
SaveChangesinterceptor for automatic key creation - Seeding pipeline:
- Model attribute seeding
- Key and culture seeding
- Repair of missing
(Key Γ Culture)combinations
- Export/import services for language packs (JSON/CSV/ZIP)
- Fully self-contained core package (no ASP.NET framework reference)
dotnet add package Geaux.LocalizationAdmin UI (optional):
dotnet add package Geaux.Localization.Adminappsettings.json:
{
"Localization": {
"Provider": "SqlServer",
"ConnectionStringName": "LocalizationDb",
"DefaultCulture": "en-US",
"TenantId": "tenant-1"
}
}Configuration-based
builder.Services.AddGeauxLocalization(
builder.Configuration.GetSection("Localization"));Code-based
builder.Services.AddGeauxLocalization(options =>
{
options.Provider = "Sqlite";
options.ConnectionString = "Data Source=localization.db";
options.DefaultCulture = "en-US";
options.TenantId = "tenant-1";
});GeauxLocalizationDbContext is the core EF Core context.
Design-time connection string:
set GEAUX_LOCALIZATION_CONNECTION=Server=.;Database=LocalizationDb;Trusted_Connection=True;Apply migrations as usual:
dotnet ef database update --project src/Geaux.Localizationusing Geaux.Localization.Attributes;
public class Product
{
[Localized(
"Product.Name",
DisplayNameKey = "Product.Name.Display",
ErrorMessageKey = "Product.Name.Required")]
public string Name { get; set; } = string.Empty;
}At startup, you can scan and seed keys:
await app.Services.InitializeGeauxLocalizationDatabaseAsync();This uses:
-
LocalizationKeyScanner
-
ModelAttributeSeeder
-
CultureSeeder
-
KeySeeder
public class MyService
{
private readonly IStringLocalizer<MyService> _localizer;
public MyService(IStringLocalizer<MyService> localizer)
{
_localizer = localizer;
}
public string GetGreeting()
{
return _localizer["Hello"];
}
}Tenant behavior:
-
TenantId = null β global translation
-
TenantId != null β tenant-scoped translation
Global and tenant translations are stored and enforced separately.
The core library exposes:
-
LocalizationExportService
-
LocalizationImportService
The admin RCL (Geaux.Localization.Admin) wires these into:
-
JSON export/import
-
CSV export/import
-
ZIP export/import (all cultures)
See the Admin documentation in the GitHub wiki for routes and UI usage.
The test project includes coverage for:
-
Culture resolution
-
Tenant scoping
-
Seeding behavior
-
EF Core integration
-
Export/import behavior
Run tests:
dotnet test-
Repository: https://github.com/GeauxCajunIT/Geaux.Localization
-
Wiki: https://github.com/GeauxCajunIT/Geaux.Localization/wiki
Wiki includes:
-
Getting Started
-
Configuration
-
Admin UI
-
Export/Import
-
Seeding & Maintenance
-
Multi-tenant behavior
src/Geaux.Localization/
Attributes/
Config/
Contexts/
EFCore/
EntityConfiguration/
Interceptors/
Seeding/
Startup/
Extensions/
Interfaces/
Migrations/
Models/
Resources/
Scanning/
Services/
Engine/
ExportImport/
Maintenance/
Startup/
Admin UI lives in Geaux.Localization.Admin as a separate RCL.
Contributions are welcome!
-
Fork the repo
-
Create a feature branch
-
Add tests where appropriate
-
Open a pull request
See the CONTRIBUTING page for guidelines.
MIT