Calinga.NET
2.2.0
dotnet add package Calinga.NET --version 2.2.0
NuGet\Install-Package Calinga.NET -Version 2.2.0
<PackageReference Include="Calinga.NET" Version="2.2.0" />
<PackageVersion Include="Calinga.NET" Version="2.2.0" />
<PackageReference Include="Calinga.NET" />
paket add Calinga.NET --version 2.2.0
#r "nuget: Calinga.NET, 2.2.0"
#:package Calinga.NET@2.2.0
#addin nuget:?package=Calinga.NET&version=2.2.0
#tool nuget:?package=Calinga.NET&version=2.2.0
Calinga.NET
Package to connect and use the calinga service in .NET applications
General usage
- Install the
Calinga.NETnuget package - Create and populate an instance of
CalingaServiceSettings - Instantiate
CalingaServicewith your settings from 2.
ASP.NET Core integration
- Install the
Calinga.NETnuget package - Extend your
appsettings.jsonwith:
"CalingaServiceSettings": {
"Organization": <YOUR_ORGANIZATION>,
"Team": <YOUR_TEAM>,
"Project": <YOUR_PROJECT>,
"ApiToken": <YOUR_TOKEN>,
"IsDevMode": false,
"IncludeDrafts": false,
"CacheDirectory": "CacheFiles", # Only needed for default caching implementation,
"MemoryCacheExpirationIntervalInSeconds": <YOUR_CACHE_EXPIRATION_INTERVAL_IN_SECONDS>, # Only needed for default caching implementation,
"DoNotWriteCacheFiles": false, # Only needed for default caching implementation
"UseCacheOnly": false, # Only needed for default caching implementation
"FallbackToReferenceLanguage": false
}
Organization: The name of your organization.Team: The name of your team.Project: The name of your project.ApiToken: The API token used for authentication.IsDevMode: Whentrue, the service returns each translation key as its own value instead of the translated text. Use during UI development to verify which translation key renders where. The keyedGetTranslationsAsync(language, keys)overload additionally validates the server response: if any requested key is missing on the server, the call throwsKeysNotFoundExceptionlisting the missing keys, so typos and unknown keys surface at integration time rather than as silent omissions at runtime.IncludeDrafts: A boolean indicating if draft translations should be included.CacheDirectory: The directory where cache files are stored. Only needed for the default caching implementation.MemoryCacheExpirationIntervalInSeconds: The expiration interval for the in-memory cache in seconds. Only needed for the default caching implementation.DoNotWriteCacheFiles: A boolean indicating if cache files should not be written to the filesystem. Only needed for the default caching implementation.UseCacheOnly: A boolean indicating if the system should only fetch translations from the cache and not from the internet. Only needed for the default caching implementation.FallbackToReferenceLanguage: A boolean indicating if the system should fallback to the reference language if an error occurs or the requested language could not be found.
- Add the following to your
Startup.ConfigureServicesmethod:
services.AddSingleton<ICalingaService>(ctx =>
{
var settings = new CalingaServiceSettings();
Configuration.GetSection(nameof(CalingaServiceSettings)).Bind(settings);
return new CalingaService(settings);
});
Custom Caching
Calinga uses out of the box in memory caching with a fallback to optional filesystem cache. You can override ICachingService with the implementation of your choice.
To enable the optional filesystem caching, the variable DoNotWriteCacheFiles in the configuration has to be set to true. When DoNotWriteCacheFiles is set to false, a copy of the entire language strings will be saved on disk at the CacheDirectory from the configuration, this copy will remain in use until ClearCache() is called.
When a translation for a string is called, Calinga.Net will check if the Key exists in its In-Memory cache, and that the In-memory cache has not yet expired, then return the translation value. If the In-memory cache was expired, it will continue to the following source, the cache stored in the filesystem and return the value. If the key was not found in the filesystem cache, Calinga.Net will send a request to Calinga API to get a new translation.
If the filesystem cache is used, you will have to manually update it by calling ClearCache() whenever it suits your use case, in order to discard the old json files and reload a fresh copy from the following Calinga API Call.
If the DoNotWriteCacheFiles was set to true, then once the cache expires, Calinga.Net will fetch the translations again from the Calinga API without looking in the local cache.
Custom HttpClient
If you need to set additional network options (proxy configuration, customized encryption, etc.) pass a pre-configured HttpClient to CalingaService.
Now the CalingaService is ready to be used in your application. More examples can be found here.
Language Tags
To fetch translations for languages with language tag you must provide the language and tag in the following format:
<language code>~<language tag>
e.g. de-AT~Intranet.
Calls to GetLanguagesAsync() will also return languages in this format.
Fetching a subset of keys
When you only need a few translation keys and do not want to pay the cost of downloading the full language dictionary, use the overload that accepts a collection of key names:
var keys = new[] { "dashboard.title", "dashboard.subtitle" };
var translations = await calingaService.GetTranslationsAsync("de", keys);
- Every keyed call POSTs to the Consumer API with a JSON body
{ "keyNames": [...] }and returns only the translations the server responded with. The cache is never consulted and never written for keyed calls, so the result is always server-fresh. - In normal mode, keys absent from the server response are silently omitted from the result (no exception).
- In DevMode (
IsDevMode = true), the server response is validated: if any requested key is missing, the call throwsKeysNotFoundException. The exception'sMissingKeysproperty exposes the missing keys, and the message lists them too, so devs can fix typos and unknown keys immediately. - Passing
keys: nullthrowsArgumentNullException. UseCacheOnly = trueis incompatible with the keyed overload — passing any key collection (including an empty one) whileUseCacheOnlyis set throwsInvalidOperationException, because keyed calls always require HTTP and cannot be served from the cache.- When
UseCacheOnlyis false, passing an empty collection returns an empty dictionary immediately — no HTTP call, no cache access.
Transport summary
| Call | HTTP method | Path | Cache read | Cache write |
|---|---|---|---|---|
GetTranslationsAsync(language) |
GET |
{ConsumerApiBaseUrl}/{org}/{team}/{project}/languages/{language} |
Yes | Full dictionary stored |
GetTranslationsAsync(language, keys) with non-empty keys (and UseCacheOnly = false) |
POST |
{ConsumerApiBaseUrl}/{org}/{team}/{project}/languages/{language} with body { "keyNames": [...] } |
No | Not stored |
GetTranslationsAsync(language, keys) with empty keys (and UseCacheOnly = false) |
none | — | No | — |
GetTranslationsAsync(language, keys) with any keys while UseCacheOnly = true |
— | — | — | Throws InvalidOperationException |
Both calls share the existing ConsumerApiBaseUrl setting — no additional URL configuration is required.
| 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 was computed. 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. |
-
.NETStandard 2.0
- Microsoft.Extensions.Caching.Abstractions (>= 10.0.8)
- Microsoft.Extensions.Caching.Memory (>= 10.0.8)
- System.Text.Json (>= 10.0.8)
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 |
|---|---|---|
| 2.2.0 | 402 | 7/30/2026 |
| 2.1.4 | 7,523 | 1/15/2026 |
| 2.1.3 | 12,184 | 7/17/2025 |
| 2.1.2 | 431 | 6/5/2025 |
| 2.1.1 | 4,098 | 3/10/2025 |
| 2.0.1 | 47,616 | 12/19/2022 |
| 2.0.0 | 820 | 11/14/2022 |
| 1.10.0 | 13,581 | 10/20/2021 |
| 1.9.2 | 12,517 | 3/24/2021 |
| 1.9.1 | 606 | 3/15/2021 |
| 1.9.0 | 604 | 3/5/2021 |
| 1.8.0 | 623 | 3/5/2021 |
| 1.7.0 | 604 | 2/23/2021 |
| 1.6.0 | 663 | 2/9/2021 |
| 1.5.0 | 600 | 2/3/2021 |
| 1.4.2 | 725 | 1/21/2021 |
| 1.4.1 | 663 | 1/21/2021 |
| 1.4.0 | 630 | 1/20/2021 |
| 1.3.0 | 638 | 10/28/2020 |
| 1.2.2 | 717 | 8/27/2020 |
## New Features
- Added `GetTranslationsAsync(string language, IEnumerable<string> keys)` to fetch a subset of translations for a given language without downloading the full dictionary.
- Every call requesting a specific list of keys issues a POST to the Consumer API (`POST {ConsumerApiBaseUrl}/{org}/{team}/{project}/languages/{language}`) with a JSON body `{ "keyNames": [...] }`. The cache is never consulted and never written for keyed calls, so the result is always server-fresh.
- Keys absent from the server response are silently omitted from the result in normal mode. In DevMode (`IsDevMode = true`), the keyed overload validates the server response and throws `KeysNotFoundException` if any requested key is missing, with the missing keys listed in both the message and the `MissingKeys` property.
- `UseCacheOnly = true` is incompatible with the keyed overload and throws `InvalidOperationException` for any key collection (including an empty one) — keyed requests always require HTTP and cannot be served from the cache.
- When `UseCacheOnly` is false, passing an empty key collection returns an empty dictionary immediately (no HTTP call, no cache access).
- When in "DevMode" and requesting a list of keys, a KeysNotFoundException gets thrown when keys were missing from the server response
## API contract decisions
- Filtering for a list of keys while having useCacheOnly enabled throws an InvalidOperationException
## Documentation
- Package now ships its README on the NuGet listing and links to the GitHub source repository
## Further Changes
- The dependency on Newtonsoft was removed and replaced by System.Text.Json
- Upgraded transitive dependencies `Microsoft.Extensions.Caching.Abstractions`, `Microsoft.Extensions.Caching.Memory` and `System.Text.Json` to 10.0.x (LTS). The library still targets `netstandard2.0`, so consumers do not need to change their target framework. .NET Framework consumers may need refreshed binding redirects for the additional transitive `System.*` packages; apps with `AutoGenerateBindingRedirects=true` are unaffected.
- `GetReferenceLanguage()` now throws `TranslationsNotAvailableException` (previously `LanguagesNotAvailableException`). The reference language exists to drive translation fallback, so a failure to determine it is reported as a translations failure. The original `LanguagesNotAvailableException` is preserved as the inner exception when the language list itself was unavailable.
- `GetTranslationsAsync(string language)` no longer leaks `LanguagesNotAvailableException` out of the reference-language fallback path — callers consistently see `TranslationsNotAvailableException`.
- Translations responses with a `null` JSON body no longer crash with `NullReferenceException`; the call now returns an empty dictionary.
- `Guard.IsNotNullOrWhiteSpace` (used to validate `language`/`key` arguments on every public API entry point) now correctly rejects whitespace-only strings — including tabs, newlines, and other Unicode whitespace — and is null-safe. Callers passing such values previously slipped past validation or hit a `NullReferenceException`; they now see `ArgumentNullException` immediately.