Apps SDK — WPF

Make your WPF app multilingual with one line of code. The SDK translates your UI live, caches translations on disk for instant offline startup, and never breaks your app — every failure falls back to the original text.

Preview. Transable.Sdk.Wpf is an early preview (0.1.0-preview.2): the public API may change between preview releases without notice. Not recommended for production yet — we'd love your feedback.

Not using WPF? Cross-platform desktop apps use the Avalonia SDK, and any other language or framework can integrate through the REST API directly.

Quick start

  1. Create an app project in the dashboard and copy your API key.
  2. Install the SDK package (the SDK is in preview, so --prerelease is required):
dotnet add package Transable.Sdk.Wpf --prerelease

The package lives on NuGet: Transable.Sdk.Wpf (the WPF adapter) pulls in Transable.Sdk, the UI-framework-agnostic core.

  1. Add one line to your App.xaml.cs:
using Transable.Sdk.Wpf;

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        TransableWpf.Init("tk_live_yourKeyHere");
        base.OnStartup(e);
    }
}

That's the whole integration. On startup the SDK detects the user's OS language, discovers your windows (a sweep of Application.Current.Windows plus a class handler on Window.Loaded, so new windows are picked up automatically) and translates static UI text: TextBlock.Text, string Content / Header values (buttons, menu items, group boxes, tab headers), Window.Title, and ToolTip strings. _File-style access keys are preserved.

Modes

The default is Magic mode: everything that is safe to translate gets translated, and you only mark what should stay untouched. Other modes are available through TransableOptions:

  • Magic (default) — automatic translation of static UI text.
  • Manual — you call Transable.T("key", "Fallback text") for each string.
  • SemiAuto — only windows and containers you explicitly mark with tr:Transable.Scope="True" are translated.
  • ApiOnly — use the translation client and cache without any UI scanning.
  • WebView — reserved for hybrid apps; not available yet.
TransableWpf.Init("tk_live_yourKeyHere", new TransableOptions
{
    Mode = TransableMode.Manual,     // Magic is the default
    DefaultLanguage = "de",          // null = detect from the OS
});

Marking text: Ignore, Key, Force

Attached properties control translation per element (and per logical subtree). Add the namespace once:

<Window xmlns:tr="https://transable.to/sdk/wpf">

  <!-- Never translate this element or its children -->
  <TextBlock Text="Build v2.4.1-beta" tr:Transable.Ignore="True" />

  <!-- Stable key: the fallback text can change without re-keying -->
  <TextBlock Text="Welcome back!" tr:Transable.Key="home.greeting" />

  <!-- Translate even if Safe mode would normally skip it -->
  <TextBlock Text="RC1" tr:Transable.Force="True" />

</Window>

The value set closest to the element wins: a local Force="True" on a descendant overrides an inherited Ignore="True" and vice versa; when both are set on the same element, Force wins. The scanner honors values set locally (a XAML attribute or SetValue from code) — values coming from styles are not picked up as subtree markers.

Language selector

The SDK ships a ready-made selector control fed by your project's enabled languages (native names and flags included). Place it anywhere in your layout:

<tr:TransableLanguageSelector />

Or switch languages programmatically:

Transable.Sdk.Transable.SetLanguage("de");
var current = Transable.Sdk.Transable.CurrentLanguage;
Transable.Sdk.Transable.LanguageChanged += (_, e) => Console.WriteLine($"Now in {e.NewLanguage}");

(In code the core entry point is qualified as Transable.Sdk.Transable because the WPF namespace also contains a Transable class — the attached properties above.) The user's choice is persisted and restored on the next launch.

Safe mode

Safe mode is on by default. It filters out strings that should never be sent for translation, before anything leaves the user's machine:

  • user input — TextBox.Text is never read or sent anywhere, not even with Transable.Force (WPF has no built-in watermark, so input controls have nothing to translate);
  • emails, URLs, file paths, GUIDs, and version numbers;
  • pure numbers, punctuation, and strings without letters;
  • log-like lines (leading timestamps) and code-like identifiers such as PascalCaseNames — while single words like "Save" or "Cancel" still translate normally.

An honest limitation: in MVVM apps, Magic mode translates the static "chrome" of your interface — text set in XAML or from code. Properties with an active binding are skipped on purpose: it keeps translations from fighting your ViewModel and guarantees bound user data (names, emails, documents) never reaches the translation server. The same applies to values coming from styles, templates, or triggers (only plain local values are ever rewritten) and to ItemsSource-generated items — rows of lists, grids, and combo boxes are data, not chrome. For bound content, use Transable.T("key", "Fallback") in your ViewModel.

Offline cache

Every translation is cached on disk (per language, under %LocalAppData%/Transable/cache). The second launch of your app is translated instantly from the local cache — even fully offline. The cache is content-addressed: when you change a string, only that string is retranslated.

Limits and error behavior

The SDK is built around one rule: it never crashes, never throws into your code, and never blocks your UI thread. Whatever happens, users see the original text. It is also unconditionally inert in the XAML designer.

  • Network errors, timeouts, or server failures — the original text stays, translation retries quietly in the background.
  • Rate limits (HTTP 429) — the SDK honors Retry-After and pauses; queued texts are not lost.
  • Monthly quota exhausted — network translation pauses until the next day; cached translations keep working.
  • Invalid or revoked key — translation is disabled for the session with a single warning through the optional logger.

Rate limits are per API key across your whole install base. If your app has many simultaneous first-time users, consider the Advanced plan.

Troubleshooting

  • Nothing is translated: check that the API key is correct and active on the project page, and that the target language is enabled for your project.
  • The setup page never shows "Connected": run the app once with the TransableWpf.Init line in place; corporate proxies or firewalls may block https://transable.to.
  • A string that should stay untouched gets translated: mark it with tr:Transable.Ignore="True".
  • Bound text is not translated: that's Safe mode by design — see Safe mode and use Transable.T() for ViewModel strings.

Still stuck? Contact support — include your project name and the SDK version.