JTigerNova.jtiger.lang
1.0.3
dotnet add package JTigerNova.jtiger.lang --version 1.0.3
NuGet\Install-Package JTigerNova.jtiger.lang -Version 1.0.3
<PackageReference Include="JTigerNova.jtiger.lang" Version="1.0.3" />
<PackageVersion Include="JTigerNova.jtiger.lang" Version="1.0.3" />
<PackageReference Include="JTigerNova.jtiger.lang" />
paket add JTigerNova.jtiger.lang --version 1.0.3
#r "nuget: JTigerNova.jtiger.lang, 1.0.3"
#:package JTigerNova.jtiger.lang@1.0.3
#addin nuget:?package=JTigerNova.jtiger.lang&version=1.0.3
#tool nuget:?package=JTigerNova.jtiger.lang&version=1.0.3
jtiger.lang
.NET Standard 2.0 library for looking up localized user-facing messages from a caller-supplied translation table.
Stateless. No I/O, no globals, no DI. The caller owns the message table; this library just resolves a key against it with a sensible fallback chain.
API
public static class Lang
{
public static string Get(
IReadOnlyDictionary<string, IReadOnlyDictionary<string, string>> msgs,
string key,
string locale = null,
Action<string> onMissingKey = null,
Action<string> onMissingFallback = null);
}
locale is optional. When omitted (or null/empty), the resolver skips the locale-specific lookups and falls straight through to English.
Message table shape
A two-level dictionary: key → locale → message.
var msgs = new Dictionary<string, IReadOnlyDictionary<string, string>>
{
["greeting.hello"] = new Dictionary<string, string>
{
["en"] = "Hello",
["es"] = "Hola",
["es-MX"] = "¿Qué onda?",
["fr"] = "Bonjour",
},
["greeting.bye"] = new Dictionary<string, string>
{
["en"] = "Bye",
// no es entry — falls back to English
},
};
Fallback chain
For each Get(msgs, key, locale) call, the resolver tries in order:
- Exact locale match.
- Language-only fallback - strips the first dash (
"es-ES"→"es"). - English -
byLocale["en"]. - The raw key - returned verbatim if nothing else matched.
Multi-segment tags like "zh-Hans-CN" only fall back one level (to "zh-Hans"), not two ("zh").
The locale string must be in BCP-47 dash form. Underscored variants like "es_ES" are not parsed and only match if the table registered that exact spelling.
Examples
Lang.Get(msgs, "greeting.hello", "es-MX"); // "¿Qué onda?"
Lang.Get(msgs, "greeting.hello", "es-AR"); // "Hola" (language fallback)
Lang.Get(msgs, "greeting.hello", "de"); // "Hello" (English fallback)
Lang.Get(msgs, "greeting.bye", "es"); // "Bye" (no es entry; falls back to en)
Lang.Get(msgs, "greeting.unknown", "en"); // "greeting.unknown" (raw key)
Lang.Get(msgs, "greeting.hello"); // "Hello" (locale omitted → English)
Missing-key callbacks
Two optional Action<string> callbacks signal the two ways a lookup can fail to find a real translation:
onMissingKey- fires whenkeyis not inmsgsat all. The caller probably forgot to register a message for a key the code path is using.onMissingFallback- fires whenkeyIS inmsgsbut its inner dictionary has no English entry, so even the safety-net path returned the raw key. The caller probably needs to add an English value as a baseline.
Lang.Get(
msgs, "greeting.unknown", "en",
onMissingKey: k => log.Warn($"unwired translation key: {k}"),
onMissingFallback: k => log.Warn($"key {k} has no English fallback"));
Either callback is invoked at most once per Get call. Exceptions thrown inside a callback are swallowed so a misbehaving logger cannot break the lookup.
Exceptions
| When | What |
|---|---|
msgs is null |
ArgumentNullException |
key is null |
ArgumentNullException |
| Anything else (missing key, missing locale, callback throws) | Returns the raw key and continues |
Threading
Lang.Get is pure with respect to its arguments. Concurrent calls are safe as long as the msgs dictionary you pass in is not being mutated concurrently - which is the same constraint IReadOnlyDictionary<,> already implies.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. 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 was computed. 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 was computed. 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. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 is compatible. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETFramework 4.8
- No dependencies.
-
.NETStandard 2.0
- No dependencies.
NuGet packages (2)
Showing the top 2 NuGet packages that depend on JTigerNova.jtiger.lang:
| Package | Downloads |
|---|---|
|
JTigerNova.Web.Lib.Service.JTigerNova
Library of standard web service functions and support |
|
|
JTigerNova.Web.Lib.Website.JTigerNova
Standard website operations |
GitHub repositories
This package is not used by any popular GitHub repositories.
v1.0.3:
- Lang.LocaleText: builds a per-key locale-text entry from (locale, text) tuples
v1.0.2:
- Lang.Get: stateless message lookup with fallback chain
- exact locale -> language-only (e.g. "es-ES" -> "es") -> English -> raw key
- optional locale parameter; omitting falls straight through to English
- optional onMissingKey callback for unwired keys
- optional onMissingFallback callback for keys with no English entry
- callback exceptions are swallowed so a faulty logger cannot break a lookup