Calinga.NET 2.2.0

dotnet add package Calinga.NET --version 2.2.0
                    
NuGet\Install-Package Calinga.NET -Version 2.2.0
                    
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="Calinga.NET" Version="2.2.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Calinga.NET" Version="2.2.0" />
                    
Directory.Packages.props
<PackageReference Include="Calinga.NET" />
                    
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 Calinga.NET --version 2.2.0
                    
#r "nuget: Calinga.NET, 2.2.0"
                    
#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 Calinga.NET@2.2.0
                    
#: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=Calinga.NET&version=2.2.0
                    
Install as a Cake Addin
#tool nuget:?package=Calinga.NET&version=2.2.0
                    
Install as a Cake Tool

Calinga.NET

NuGet

Package to connect and use the calinga service in .NET applications

General usage

  1. Install the Calinga.NET nuget package
  2. Create and populate an instance of CalingaServiceSettings
  3. Instantiate CalingaService with your settings from 2.

ASP.NET Core integration

  1. Install the Calinga.NET nuget package
  2. Extend your appsettings.json with:
      "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: When true, 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 keyed GetTranslationsAsync(language, keys) overload additionally validates the server response: if any requested key is missing on the server, the call throws KeysNotFoundException listing 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.
  1. Add the following to your Startup.ConfigureServices method:
    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 throws KeysNotFoundException. The exception's MissingKeys property exposes the missing keys, and the message lists them too, so devs can fix typos and unknown keys immediately.
  • Passing keys: null throws ArgumentNullException.
  • UseCacheOnly = true is incompatible with the keyed overload — passing any key collection (including an empty one) while UseCacheOnly is set throws InvalidOperationException, because keyed calls always require HTTP and cannot be served from the cache.
  • When UseCacheOnly is 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 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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
Loading failed

## 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.