DocsFlutter6 min read
Flutter
siyak_flutter keeps your source string in the widget tree and lets the server learn its translation. No key tables, no codegen, no Intl ceremony — and the first frame never waits on the network.
pubspec.yaml
dependencies:
flutter:
sdk: flutter
siyak_flutter:
path: ../vendor/siyak_flutter # the folder from the downloaded archive
# pub.dev hosting is announced later; until then the archive is the install path.lib/main.dart
import 'package:siyak_flutter/siyak_flutter.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
final siyak = Siyak.init(
apiKey: const String.fromEnvironment('SIYAK_API_KEY'),
endpoint: const String.fromEnvironment('SIYAK_ENDPOINT'),
target: 'ar-EG',
source: 'en',
context: 'home screen',
onLog: debugPrint,
);
unawaited(siyak.preload()); // one request, every approved string
runApp(MyApp(siyak: siyak));
}The rebuild pattern
A cached getter is useless if nothing repaints when the translation lands, so the client exposes two ValueNotifiers: translationRevision fires whenever a new string enters the cache, and lastError fires with the service's error code — or with null when it recovers.
class _HomeState extends State<Home> {
final siyak = Siyak.shared;
@override
void initState() {
super.initState();
siyak.translationRevision.addListener(_repaint);
}
void _repaint() => setState(() {});
@override
void dispose() {
siyak.translationRevision.removeListener(_repaint);
super.dispose();
}
@override
Widget build(BuildContext context) => Text(siyak.t('Settings'));
}Right-to-left
if (siyak.isRightToLeft) { // ar, fa, he, ur, ckb, … (region-insensitive)
// Flip the whole app, not one Text.
return Directionality(textDirection: TextDirection.rtl, child: ...);
}- isRtlTag("ar-EG") is true; the check is by primary subtag, so a region never breaks it.
- warmUp(listOfStrings) before a screen you know is heavy — it batches and resolves, so nothing paints twice in the source language.
- The cache persists through shared_preferences and is a 30-day LRU of 1000 entries by default; in a pure-Dart test with no platform registrar it degrades to memory instead of throwing.
- Errors are typed: QuotaExceededException, RateLimitedException, InvalidApiKeyException, OriginNotAllowedException, BackendUnavailableException, SiyakNetworkException. t() still never throws — they surface through lastError and onLog.
Running against a local server
flutter run --dart-define=SIYAK_ENDPOINT=http://10.0.2.2:8787 \
--dart-define=SIYAK_API_KEY=sk_test_…
// and pass allowInsecureEndpoint: true to Siyak.init — it refuses plain http
// by default, because a release build pointing at http:// is almost always a bug.