Apps SDK — Flutter
Translate your Flutter or Dart app's UI into 90 languages with one init
call and a TransableText widget. Pure Dart, zero runtime
dependencies. Translations are cached on disk for instant offline startup, and no public call ever
throws into your app — every failure falls back to the original text.
dart analyze-clean, passes 58/58 unit tests, and
a live check against the real API translated en → ru and
served the repeat call from cache. It is not battle-tested inside a shipped Flutter
app, has no web support (the transport uses dart:io),
and the public API may still change. Not recommended for a shipping app yet —
we'd love your feedback.
Install
- Download the package: transable-flutter-0.1.0-preview.1.zip
- Unzip it next to your app and depend on the local copy in your
pubspec.yaml(once the repo is public you can use a git or pub.dev dependency instead — seePUBLISH.md):
dependencies:
transable_sdk:
path: ../transable-flutter
Then run flutter pub get (or dart pub get in a pure-Dart CLI project). Supported targets: Flutter mobile/desktop and the Dart CLI — no web. Create an app project in the dashboard and copy your API key.
One-line start
Call Transable.init(...) exactly once at startup. It is idempotent and never throws — a missing or wrong key just leaves the UI in the source language. Pass a real, writable cacheDirectory so the offline cache persists across launches:
import 'package:path_provider/path_provider.dart';
import 'package:transable_sdk/transable_sdk.dart';
import 'package:transable_sdk/transable_widget.dart'; // TransableText
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
final support = await getApplicationSupportDirectory();
Transable.init('tk_live_yourKeyHere', TransableOptions(
appName: 'my-app',
cacheDirectory: support.path,
// defaultLanguage: 'de', // else the user's OS locale is detected
));
runApp(const MyApp());
}
Translate — the widget, or one call
The idiomatic Flutter path: wrap the strings you want translated. The widget re-renders when the language changes and when the background translation lands. The authored string is both the source text and the fallback shown until the translation arrives:
TransableText('Save changes')
Or call t() directly — synchronous and cache-first (returns the fallback and queues a background batch on a miss), plus an async index-aligned batch:
Text(Transable.t('greeting', 'Welcome back'))
final out = await Transable.translateBatch(['Save', 'Cancel'], language: 'de');
// index-aligned: ['Speichern', 'Abbrechen']
There is no automatic widget-tree scanning — you explicitly wrap what you want translated. That's a privacy boundary: the SDK never picks up text a user typed into a field. Rebuild your UI on Transable.onLanguageChanged / onTranslationsUpdated, and switch language with Transable.setLanguage('de').
Safe mode & offline cache
Safe mode is on by default and runs before any network I/O, so filtered text never leaves the machine: emails, URLs, file paths, GUIDs, version strings, log lines, and code-like identifiers (snake_case, PascalCase) are never sent — while ordinary UI words like "Save" and "Cancel" do translate. The SDK only ever translates strings you explicitly pass to t() / translateBatch() or author on a TransableText.
Every translation is written to disk at {cacheDirectory}/v1/{lang}.jsonl, per language, content-addressed (10 MB per-language cap), so the second launch is translated instantly, even offline. Always pass a real cacheDirectory — in a Flutter app use a path_provider directory.
It never crashes your app
One rule: no public entry point ever throws. Missing key, no network, HTTP 4xx/5xx, quota exhaustion, a malformed response, even a throwing logger — every failure degrades to the source-language text, with at most a message on your logger.
Questions or something broke? Contact us — include your Flutter/Dart version and the package version. Other platforms: Android, iOS / macOS, or any language via the REST API. Full platform list on Apps SDK.