Prowl.Rosetta 1.0.1

There is a newer version of this package available.
See the version list below for details.
dotnet add package Prowl.Rosetta --version 1.0.1
                    
NuGet\Install-Package Prowl.Rosetta -Version 1.0.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="Prowl.Rosetta" Version="1.0.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Prowl.Rosetta" Version="1.0.1" />
                    
Directory.Packages.props
<PackageReference Include="Prowl.Rosetta" />
                    
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 Prowl.Rosetta --version 1.0.1
                    
#r "nuget: Prowl.Rosetta, 1.0.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 Prowl.Rosetta@1.0.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=Prowl.Rosetta&version=1.0.1
                    
Install as a Cake Addin
#tool nuget:?package=Prowl.Rosetta&version=1.0.1
                    
Install as a Cake Tool

Rosetta

Rosetta is a lightweight, backend-agnostic localization library for .NET. It works anywhere — Unity, custom engines, desktop apps, and games.


Installation

dotnet add package Prowl.Rosetta

Quick Start

// 1. Configure once at startup
Loc.Configure(cfg => cfg
    .SetFallbackLocale("en")
    .AddProvider(new JsonFileProvider("Localization/{locale}.json"))
    .SetLocale("fr")
);

// 2. Look up strings anywhere
string text = Loc.Get("ui.button.confirm");

That's it. Loc.Get is a static accessor so you can call it from anywhere without dependency injection.


Core API

Basic lookup

string text = Loc.Get("ui.button.confirm");
// → "Confirm"

Interpolation

Named placeholders — not positional {0} — so translators always have context.

string text = Loc.Get("player.killed", new { name = "Zara", count = 3 });
// → "Zara defeated 3 enemies"

Pluralization

Rosetta follows Unicode CLDR plural rules, so languages with complex plural forms (Russian, Arabic, Polish) work correctly out of the box.

string text = Loc.GetPlural("item.collected", count: 1);  // → "1 item"
string text = Loc.GetPlural("item.collected", count: 7);  // → "7 items"

// With interpolation
string text = Loc.GetPlural("enemy.remaining", count: 3, new { zone = "Northgate" });
// → "3 enemies remain in Northgate"

Gender

string text = Loc.GetGender("npc.greeting", gender: Gender.Female);
// → "She smiles at you."

Translation File Format

Rosetta uses flat JSON by default. Keys use dot notation. Pluralization and gender are expressed as nested objects.

{
  "ui.button.confirm": "Confirm",

  "player.killed": "{{name}} defeated {{count}} enemies",

  "item.collected": {
    "one":   "{{count}} item",
    "other": "{{count}} items"
  },

  "npc.greeting": {
    "male":   "He nods at you.",
    "female": "She smiles at you.",
    "other":  "They glance over."
  }
}

Providers

Providers are the source of truth for translations. They are tried in order, with later providers overriding earlier ones on key conflicts. This lets you ship bundled strings and override them from a remote backend.

Rosetta ships with the following built-in providers:

Provider Description
JsonFileProvider Loads .json files from disk. Path supports {locale} token.
EmbeddedResourceProvider Loads from embedded assembly resources. Good for libraries and engines.
InMemoryProvider Loads from a Dictionary<string, string>. Useful for testing.

Configuration examples

File-based:

Loc.Configure(cfg => cfg
    .SetFallbackLocale("en")
    .AddProvider(new JsonFileProvider("Localization/{locale}.json"))
    .SetLocale("fr")
);

Prowl Engine (embedded resources):

Loc.Configure(cfg => cfg
    .SetFallbackLocale("en")
    .AddProvider(new EmbeddedResourceProvider(Assembly.GetExecutingAssembly()))
    .SetLocale("en")
    .OnMissingKey(MissingKeyBehavior.ReturnKey) // never crash in editor
);

Hybrid — local fallback with remote overrides:

Loc.Configure(cfg => cfg
    .SetFallbackLocale("en")
    .AddProvider(new JsonFileProvider("Localization/{locale}.json")) // bundled baseline
    .AddProvider(new MyRemoteProvider())                             // remote overrides
);

Locale Switching

// Switch at runtime — reloads and fires LocaleChanged
Loc.SetLocale("ja");

// Subscribe to locale changes for UI refresh
Loc.LocaleChanged += (oldLocale, newLocale) => RefreshAllUI();

Scoped locale

Temporarily override the locale without changing the global setting — useful for previewing translations or localizing a specific NPC.

using (var scope = Loc.BeginScope("de"))
{
    string preview = Loc.Get("ui.title"); // German, inside the scope
}
// Global locale restored outside the using block

Missing Keys

Control what happens when a key is not found.

.OnMissingKey(MissingKeyBehavior.ReturnKey)       // returns "ui.button.confirm" — safe for editors
.OnMissingKey(MissingKeyBehavior.ReturnFallback)  // tries the fallback locale first
.OnMissingKey(MissingKeyBehavior.Throw)           // throws KeyNotFoundException — strict mode

You can also hook into missing key events to track untranslated strings:

Loc.MissingKey += (locale, key) =>
{
    Analytics.Track("missing_translation", new { locale, key });
};

Custom Providers

Implementing your own provider requires a single interface:

public class MyCustomProvider : ILocalizationProvider
{
    public IReadOnlyDictionary<string, string> Load(string locale)
    {
        // Return a flat key → value dictionary for this locale
        return FetchFromMyBackend(locale);
    }

    public bool SupportsLocale(string locale) =>
        _supportedLocales.Contains(locale);
}

Then register it like any built-in provider:

.AddProvider(new MyCustomProvider())

Reload

To force a reload of all cached translations — for example after a live content update:

Loc.Reload();

Design Philosophy

  • One static entry point. Loc.Get works from anywhere — no service locator, no constructor injection required.
  • Provider order is override order. Bundle your baseline translations and let later providers win on conflict.
  • Named placeholders only. {{name}} instead of {0} keeps translation files readable for non-developers.
  • CLDR pluralization. Plural rules are locale-aware from the start. You don't bolt this on later.
  • Never throws in production. The default missing key behaviour is ReturnFallback then ReturnKey. Your game keeps running.

Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 is compatible.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  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 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net6.0

    • No dependencies.
  • net7.0

    • No dependencies.
  • net8.0

    • No dependencies.
  • net9.0

    • No dependencies.

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.1.0 97 5/16/2026
1.0.1 90 5/16/2026
1.0.0 115 4/4/2026