rerune 0.8.2 copy "rerune: ^0.8.2" to clipboard
rerune: ^0.8.2 copied to clipboard

OTA localization updates for Flutter apps with build_runner code generation.

rerune #

OTA localization updates for Flutter apps.

ReRune layers server-provided translations on top of your generated AppLocalizations values, without changing how you call localization getters in widgets.

Requirements #

  • Flutter >=3.22.0
  • Dart >=3.4.0

Install #

dependencies:
  rerune: ^0.8.2

dev_dependencies:
  # Optional: needed only if you use the build_runner path below.
  build_runner: ^2.4.13

1) Generate Flutter localizations #

flutter gen-l10n

2) Generate ReRune localization config #

Fast path (ReRune-only generation):

dart run rerune

Alternative (build_runner pipeline):

dart run build_runner build --delete-conflicting-outputs

Both commands generate identical *.rerune.g.dart artifacts. Parity is protected by dedicated drift-guard tests in CI.

With default Flutter l10n naming, ReRune generates:

  • lib/.../app_localizations.rerune.g.dart
  • reRuneAppLocalizationsConfig

No manual anchor class or annotation file is needed.

3) Wire ReRune.setup(...) in main() #

import 'package:flutter/widgets.dart';
import 'package:rerune/rerune.dart';

import 'l10n/gen/app_localizations.rerune.g.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await ReRune.setup(
    otaPublishId: 'your-ota-publish-id',
    localizations: reRuneAppLocalizationsConfig, // Generated by rerune/build_runner
    updatePolicy: const ReRuneUpdatePolicy(checkOnStart: true),
  );

  runApp(const MyApp());
}

4) Use ReRune delegates/locales in your app #

MaterialApp(
  localizationsDelegates: ReRune.localizationsDelegates,
  supportedLocales: ReRune.supportedLocales,
)

Runtime APIs #

  • Setup and load cached bundles: await ReRune.setup(...)
  • Check manually: await ReRune.checkForUpdates()
  • Listen to applied updates: ReRune.onFetchedTextsApplied.listen(...)
  • Rebuild subtree on any localization revision: ReRuneBuilder(builder: ...)
  • Listen to any localization revision: ReRune.localizationsRevisionListenable

Dashboard-Only Locale Additions #

ReRune can make newly added dashboard languages available without an app-store release. await ReRune.setup(...) loads cached manifest/ARB bundles before the first app frame, so a dashboard-only locale fetched during a previous run is available in ReRune.supportedLocales before MaterialApp resolves the device locale. If checkOnStart is enabled, the network refresh starts in the background after cached bundles are loaded; it does not block setup.

After a successful manifest/update fetch, ReRune.supportedLocales contains the app's compiled locales plus dashboard locales whose ARB bundle has been fetched or loaded from cache. The generated delegate uses the app's first compiled locale as the fallback base when Flutter's generated delegate cannot load a dashboard-only locale.

Startup Modes #

Use awaited setup when you want deterministic second-run locale support without waiting on the network:

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await ReRune.setup(
    otaPublishId: 'your-ota-publish-id',
    localizations: reRuneAppLocalizationsConfig,
  );

  runApp(const MyApp());
}

Use the builder when you also want the app to follow the device language immediately after a same-run background fetch:

ReRuneBuilder(
  builder: (_) => MaterialApp(
    localizationsDelegates: ReRune.localizationsDelegates,
    supportedLocales: ReRune.supportedLocales,
  ),
)

Limits:

  • Without ReRuneBuilder or another rebuild trigger, a locale fetched during the current run is picked up by MaterialApp on the next launch after await ReRune.setup(...) loads it from cache.
  • New localization keys or changed placeholder signatures still require running flutter gen-l10n and dart run rerune, then shipping an app update.
  • Platform/app-store language metadata and OS-level language listings are not changed by OTA localization.

Advanced And Custom Integrations #

Custom Flutter l10n class/file names #

If your app does not use app_localizations.dart / AppLocalizations, add a build.yaml in the app root:

targets:
  $default:
    builders:
      rerune|re_rune_localizations_overlay:
        generate_for:
          - lib/**/my_localizations.dart
        options:
          localizations_file_name: my_localizations.dart
          localizations_class_name: MyLocalizations

Then run:

flutter gen-l10n
dart run rerune

# or

dart run build_runner build --delete-conflicting-outputs

This generates my_localizations.rerune.g.dart and reRuneMyLocalizationsConfig.

Use it in startup:

import 'package:rerune/rerune.dart';

import 'l10n/gen/my_localizations.rerune.g.dart';

void main() {
  ReRune.setup(
    otaPublishId: 'your-ota-publish-id',
    localizations: reRuneMyLocalizationsConfig,
  );

  runApp(const MyApp());
}

Disable automatic startup fetch #

ReRune.setup(
  otaPublishId: 'your-ota-publish-id',
  localizations: reRuneAppLocalizationsConfig, // Generated by rerune/build_runner
  updatePolicy: const ReRuneUpdatePolicy(checkOnStart: false),
);

Schedule periodic refresh in hours or days #

ReRune.setup(
  otaPublishId: 'your-ota-publish-id',
  localizations: reRuneAppLocalizationsConfig,
  updatePolicy: const ReRuneUpdatePolicy(
    checkOnStart: true,
    periodicIntervalInHours: 2,
    periodicIntervalInDays: 3,
  ),
);

ReRuneUpdatePolicy only accepts whole-hour or whole-day periodic refresh intervals. If both fields are set, they are combined into a single refresh cadence. On web, if the combined interval exceeds the supported timer limit, ReRune clamps it to the maximum supported delay (24 days and 20 hours) instead of throwing.

Trigger updates from UI actions #

final result = await ReRune.checkForUpdates();
if (result.hasErrors) {
  // show error state
}

Provide your own cache store #

If you need custom storage behavior, implement ReRuneCacheStore and pass it to ReRune.setup(cacheStore: ...).

Troubleshooting #

  • Target of URI hasn't been generated: run flutter gen-l10n, then dart run rerune (or dart run build_runner build --delete-conflicting-outputs).
  • Undefined name reRune...Config: generated .rerune.g.dart file is missing, stale, or imported from a wrong path.
  • Changed l10n keys/signatures: rerun both generators.

License #

This package is proprietary software.

  • Copyright (c) 2026 BasalBit GmbH. All rights reserved.
  • Commercial license terms: https://rerune.io/terms
  • Issue tracker: https://rerune.io/issue-tracker
0
likes
0
points
1.03k
downloads

Publisher

unverified uploader

Weekly Downloads

OTA localization updates for Flutter apps with build_runner code generation.

Homepage
View/report issues

License

unknown (license)

Dependencies

analyzer, build, crypto, flutter, glob, http, intl, path_provider, shared_preferences, source_gen, yaml

More

Packages that depend on rerune