Your words.
Edit source copy and translations together, with glossary terms and context close at hand.
Translation management for software teams
Control what your app says, in every language. Use ML and AI assistance, tailor messages with variants, and publish over-the-air (OTA) text updates to supported apps.





Edit source copy and translations together, with glossary terms and context close at hand.
Create variants for brands, plans, or experiments. Your app selects the matching copy.
Preview drafts, publish when ready, and restore earlier published text if needed.
ReRune has not only saved us an enormous amount of time, but also brought clarity, consistency, and reliability to our entire localization workflow.
Explore ReRune
See what changes for your team and how it connects to your app.
The journey of a word
The scholar writes. The runes take flight. Your words find their way into your app.
The scholarWrite, translate, and review your product copy in ReRune.
Bring translation files into your development workflow.
Publish reviewed text for delivery through ReRune SDKs.
Your app shows the words on its next successful update check.
Welcome home
A place for your next adventure.
Why it matters
ReRune gives software teams controlled AI assistance, language coverage visibility, CI/CD sync, and OTA updates for supported apps.
Replace file handoffs and status chasing with work packages: keys assigned to one teammate, an optional due day and approver, and a notification at every handoff.
Use DeepL or OpenRouter with your Glossary, so automated drafts start from the terms you approved. DeepL treats terms as a hint it may not follow, so review its drafts.
Use ReRune SDKs and OTA publish IDs to update approved app text without waiting for a full app release.
See language completion, missing keys, active integrations, and project readiness before launch.
Track billing accounts, team access, plans, and integrations around the localization work they support.
CLI and API access let localization move through CI/CD instead of becoming a manual release task.
Team workflow
A work package turns a set of keys into a task for one teammate, with an optional due day and an optional approver. Each step can be a different person with their own permission, and each handoff arrives by email and in the dashboard.
Someone with the Project settings permission selects keys, names the package and assigns it to a teammate with the Edit keys permission, with a due day if it has one.
The assignee filters the key list by the package, translates its keys and marks the package as done.
The approver, who may have read-only access, approves the package or rejects it with a reason, which sends it back to the assignee. Without an approver, done means approved.
A teammate with the Publishing permission publishes the changes. Translating and releasing are separate permissions, so they can stay with different people.
Work Packages
Assigned to Mia · 12 keys · Due 20 Nov
Approver: Jonas
Assigned to Luca · 8 keys
Approved by Jonas
Assigned to Mia · 5 keys · Due 27 Nov
Rejected by Jonas: use the glossary term for “plan”.
Edit approved copy, publish it, and refresh the app without a new store release.
Update approved copy.
Create the OTA update.
Load it in the app.
Part of OTA · Live preview
Screenshots and Figma
Translators, reviewers and developers see the screen behind each key in its Design tab, so nobody has to guess from a key name where a text sits or how much room it has.
Upload, paste or drop a screenshot of your app, draw an area for each key, and find every screen in the project's Gallery. Replacing the image keeps the keys in place.
How screenshots workComing soon to Figma Community: link text layers to keys, push copy as drafts, preview every language on the canvas, and upload a screenshot of each frame you change. Nothing is published from Figma.
ReRune for Figma
Text for tests, brands, and plans
Run A/B tests on app copy, give each white-label brand its own wording, or tailor messages for Free and Pro users. Manage all the text in one shared project.
One message, different audiences
Each test group, brand, or plan gets its own wording. If no separate wording is set, the shared text is used.
One message, different audiences
Each test group, brand, or plan gets its own wording. If no separate wording is set, the shared text is used.
One message, different audiences
Each test group, brand, or plan gets its own wording. If no separate wording is set, the shared text is used.
A streamlined workflow
Manage app copy, translation, review, and delivery in one workflow instead of passing files between tools and teams.
Give everyone the same project view, so teams spend less time briefing, chasing updates, reconciling files, and checking work twice.
Use the CLI, API, or OTA updates for routine text changes instead of turning every wording update into a full app release.
Quality Governance
The Glossary holds your approved translation of each term, per language. AI translation receives the terms found in the text, and DeepL gets them as a hint it may not follow.
AI settings carry project context and preferred style into translation suggestions instead of starting from a blank prompt.
Structured messages, placeholders, and per-language values stay visible before content is synced or published.


More languages
Start with one new market. Translate the text you already manage and see what still needs attention before launch.
Add each term's approved translation as you add a language, so AI translation starts from the names and key terms you chose. DeepL gets them as a hint it may not follow.
Review and publish corrections as you learn from users. With ReRune’s SDKs, text updates can reach your users without a new software release.
Setup WizardAI Coding Agent
Run the onboarding command from the root of your Git repository. The wizard inspects the app and confirms the plan with you, with no AI involved and nothing changed yet. Then it opens the coding agent you already use with a complete migration workflow.
Run inside your Git repository
curl -fsSL https://rerune.io/onboard.sh | shThe script runs locally. ReRune does not receive your source code or list of installed agents.
11 integrations: 4 available now, 7 planned.
Use the ReRune CLI to sync, validate, and manage translations right from your terminal. Run syncs in CI/CD or locally whenever you need to push a new language.
Need help? Invite your teammates directly from the CLI or jump back into the web dashboard.
brew install BasalBit/tap/reruneAlready installed? Update anytime with brew upgrade BasalBit/tap/rerune.
Choose the architecture that matches your machine.
rerune at the root of the project to start using the CLI.Need archived binaries or older versions? Browse the release catalog.
Installs the latest reviewed ReRune CLI for your user account. No sudo or administrator privileges required.
curl -fsSL https://rerune.io/install.sh | shSDK platform
@rerune/angular 1.9.0 replaces your native root provider and accepts its unchanged options. Keep ngx-translate or Transloco pipes, loaders, and language switching.
Quick Start
Install command
npm install @rerune/angular@1.9.0 @ngx-translate/core@18Setup
import { ApplicationConfig } from '@angular/core'
import { TranslateLoader } from '@ngx-translate/core'
import { ReRune } from '@rerune/angular/ngx-translate'
import { BundledLoader } from './translations'
export const appConfig: ApplicationConfig = {
providers: [
ReRune.setup({
otaPublishId: '<READ_ONLY_OTA_PUBLISH_ID>',
supportedLocales: ['en', 'de'],
}, {
lang: 'en',
fallbackLang: 'en',
loader: { provide: TranslateLoader, useClass: BundledLoader },
}),
],
}Replace the native root provider; keep your existing loader and translation pipes. supportedLocales includes app-owned languages the native engine has not registered yet. The full guide covers loader setup, SSR, and removal.
Install command
npm install @rerune/angular@1.9.0 @jsverse/transloco@8Setup
import { ApplicationConfig } from '@angular/core'
import { ReRune } from '@rerune/angular/transloco'
import { BundledLoader } from './translations'
export const appConfig: ApplicationConfig = {
providers: [
ReRune.setup({
otaPublishId: '<READ_ONLY_OTA_PUBLISH_ID>',
}, {
config: {
availableLangs: ['en', 'de'],
defaultLang: 'en',
fallbackLang: 'en',
reRenderOnLangChange: true,
},
loader: BundledLoader,
}),
],
}Replace the native root provider; keep availableLangs, your loader, translation pipes, and plugin order. The full guide covers loader setup, SSR, and removal.
Add OTA localization updates and runtime variants on top of generated Flutter localizations without changing how widgets read translated strings.
Quick Start
setup
dependencies:
rerune: ^1.9.1
flutter gen-l10n
dart run rerune
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await ReRune.setup(
otaPublishId: 'your-ota-publish-id',
localizations: reRuneAppLocalizationsConfig,
variant: ReRuneVariant.named('customer_acme'),
);
runApp(const MyApp());
}
MaterialApp(
localizationsDelegates: ReRune.localizationsDelegates,
supportedLocales: ReRune.supportedLocales,
);Why it feels lightweight
Keep your generated Flutter localization APIs. If exported ARBs contain offset:0, the SDK can prepare compatible copies before generation. Keep source ARBs in lib/l10n, set arb-dir to lib/l10n/flutter, and run dart run rerune prepare-arb before flutter gen-l10n and dart run rerune.
Main runtime APIs
Use ReRune.checkForUpdates(), listen to ReRune.onFetchedTextsApplied, or wrap screens with ReRuneBuilder when you want update-aware UI.
Ship OTA localization updates and runtime variants in native Android apps while keeping bundled resources as the final fallback.
Quick Start
Compose quick start
dependencies {
implementation("io.rerune:rerune-android-compose:1.8.0")
}
class App : Application() {
override fun onCreate() {
super.onCreate()
ReRune.setup(
app = this,
otaPublishId = BuildConfig.RERUNE_OTA_PUBLISH_ID,
variant = ReRuneVariant.fromSlug("customer_acme"),
)
}
}
override fun attachBaseContext(newBase: Context) {
super.attachBaseContext(newBase.reRune())
}
@Composable
fun ExampleScreen() {
reRuneObserveRevision {
Text(text = stringResource(R.string.title))
}
}Declarative refresh
Wrap the content of each setContent in reRuneObserveRevision { ... }. It refreshes ReRune texts in place and keeps remembered state, while stringResource(...) keeps reading through the normal Android resource flow.
What still matters
Keep ReRune.setup(...) in Application.onCreate() and wrap each activity with newBase.reRune() so Compose and platform resources read OTA updates.
Views quick start
dependencies {
implementation("io.rerune:rerune-android-views:1.8.0")
}
class App : Application() {
override fun onCreate() {
super.onCreate()
ReRune.setup(
app = this,
otaPublishId = BuildConfig.RERUNE_OTA_PUBLISH_ID,
variant = ReRuneVariant.fromSlug("customer_acme"),
)
ReRuneViews.install(this)
}
}
class MainActivity : AppCompatActivity() {
override fun attachBaseContext(newBase: Context) {
super.attachBaseContext(newBase.reRune())
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding.title.text = getString(R.string.title)
reRuneOnStringsUpdated(lifecycleScope) {
binding.title.text = getString(R.string.title)
}
}
}Legacy UI support
One attachBaseContext hook enables getString(...), getText(...), and XML-inflated Views in AppCompat activities with OTA-backed strings. Styled app strings keep their own text in getText(...) and XML.
Fallback behavior
When OTA is unavailable, Android falls back to bundled resources, so classic Views keep working without a separate code path.
Ship OTA localization updates and runtime variants in native iOS apps while keeping UIKit and SwiftUI on Apple's localization APIs.
Quick Start
SwiftUI quick start
// Swift Package Manager
// https://swiftpackageindex.com/BasalBit/rerune-ios
// Version: 1.7.0
import ReRune
import SwiftUI
@main
struct ExampleApp: App {
init() {
reRuneSetup(
otaPublishId: "replace-with-ota-publish-id",
variant: ReRuneVariant("customer_acme")
)
}
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
struct ContentView: View {
var body: some View {
VStack {
Text(NSLocalizedString("title", comment: ""))
Text(Bundle.main.localizedString(forKey: "subtitle", value: nil, table: nil))
}
// Needed only below iOS 17; deprecated on iOS 17 and later.
.reRuneObserveRevision()
}
}Native lookup path
Text("key") shows ReRune values when SwiftUI creates the view. For text that must update on screen, read it with NSLocalizedString(...) in the view body. On iOS 17 and later those views update by themselves. Before iOS 17, add .reRuneObserveRevision() near the top of the screen.
Current SwiftUI scope
SwiftUI Text("key") and views that take a key show ReRune values. String(localized:), LocalizedStringResource, and AttributedString(localized:) do not, so use NSLocalizedString(...) for those strings.
UIKit quick start
// Swift Package Manager
// https://swiftpackageindex.com/BasalBit/rerune-ios
// Version: 1.7.0
import ReRune
reRuneSetup(
otaPublishId: "replace-with-ota-publish-id",
variant: ReRuneVariant("customer_acme")
)
titleLabel.text = NSLocalizedString("title", comment: "")
subtitleLabel.text = Bundle.main.localizedString(forKey: "subtitle", value: nil, table: nil)
reRuneRevisionPublisher
.dropFirst()
.sink { [weak self] _ in self?.rebindStrings() }
.store(in: &cancellables)UIKit stays native
UIKit screens can keep using NSLocalizedString(...) or Bundle.main.localizedString(...) and subscribe to reRuneRevisionPublisher when visible strings should refresh.
Current OTA scope
ReRune 1.7.0 applies OTA values and the selected translation variant through native Bundle.main lookups, with per-key Main and bundled-resource fallback.
Ship OTA localization updates and runtime variants in shared Compose Multiplatform UI on Android, iOS and desktop, with your bundled resources as the fallback.
Quick Start
Compose Multiplatform quick start
// shared/build.gradle.kts
commonMain.dependencies {
implementation("io.rerune:rerune-kmp-compose:1.0.0")
}
// Once at startup
ReRune.setup(
otaPublishId = "your-ota-publish-id",
variant = ReRuneVariant.fromSlug("customer_acme"),
)
@Composable
fun Greeting(userName: String, count: Int) {
Text(reRuneStringResource(Res.string.greeting))
Text(reRuneStringResource(Res.string.welcome_user, userName))
Text(reRunePluralStringResource(Res.plurals.item_count, count, count))
}Same resources, one call each
reRuneStringResource, reRunePluralStringResource, reRuneGetString and reRuneGetPluralString mirror the Compose Multiplatform functions of the same shape. A screen that still calls plain stringResource(...) compiles and shows bundled text only.
What still matters
Keep ReRune.setup(...) at startup with the read-only OTA Publish ID. On Android, ReRune captures the application context itself unless your app removes its provider from the manifest.
@rerune/react-native 1.9.0 creates i18next from your native options and replaces the root provider. Keep translation calls and resources, with default AsyncStorage persistence.
@rerune/react-native@1.9.0
Install command
npm install @rerune/react-native@1.9.0 i18next react-i18nextSetup
import { ReRune, ReRuneProvider } from '@rerune/react-native'
export const client = ReRune.setup({
otaPublishId: '<READ_ONLY_OTA_PUBLISH_ID>',
}, nativeOptions);
<ReRuneProvider client={client} defaultNS="translation">
<App />
</ReRuneProvider>Use your existing nativeOptions and resources. Call setup once at module scope in its own module; it returns the client synchronously. Replace I18nextProvider and keep useTranslation(). For plugins, pass your existing i18n. Install AsyncStorage in your app and rebuild.
@rerune/react 1.9.0 creates i18next from your native options and replaces the root provider. Keep translation calls and resources, with browser caching and a separate SSR preload flow.
@rerune/react@1.9.0
Install command
npm install @rerune/react@1.9.0 i18next react-i18nextSetup
import { ReRune, ReRuneProvider } from '@rerune/react'
const client = ReRune.setup({
otaPublishId: '<READ_ONLY_OTA_PUBLISH_ID>',
}, nativeOptions);
<ReRuneProvider client={client} defaultNS="translation">
<App />
</ReRuneProvider>Use your existing nativeOptions and resources. Call setup once at module scope; it returns the client synchronously. Replace I18nextProvider with ReRuneProvider, which loads cached and OTA text after its first render. Keep useTranslation(). For plugins, pass your existing i18n. The full guide covers SSR and the Next.js App Router.
@rerune/vue
This SDK is on the roadmap. Installation and setup guidance will appear here when development starts.
The blacksmith@rerune/svelte
This SDK is on the roadmap. Installation and setup guidance will appear here when development starts.
The blacksmith@rerune/solid
This SDK is on the roadmap. Installation and setup guidance will appear here when development starts.
The blacksmithMCP integration
Read projects, edit translations, and publish reviewed copy from the AI client you already use. Connect Codex, Claude Code, Cursor, VS Code, OpenCode, or Pi with your ReRune API key.
68 tools for projects, translations, publishing, glossary terms, teams, and Figma design links.
Use ReRune to list my projects, then show the draft translations in my website project.
Choose your client
Add this to your personal ~/.codex/config.toml, replacing the API-key placeholder. The configuration is shared by the Codex CLI and IDE extension.
~/
[mcp_servers.rerune]
url = "https://rerune.io/api/mcp"
tool_timeout_sec = 300
[mcp_servers.rerune.http_headers]
"X-API-Key" = "YOUR_RERUNE_API_KEY"Restart Codex, then run codex mcp list or use /mcp in the CLI to inspect the connection and available tools.
Replace YOUR_RERUNE_API_KEY with your own key.Get an API key
How it works
Create a project, define languages, add keys, and import existing translation files by platform.
Edit values, maintain placeholders and metadata, use a glossary, and translate with DeepL or AI integrations.
Export platform formats, sync through the CLI or API in CI/CD, or publish OTA updates where your app uses a ReRune SDK.
From the ReRune team
“We built ReRune so product, localization, and engineering teams can share one localization workflow without duct-taped spreadsheets.”
ReRune teamProduct localization platform
Questions
A short product map for teams comparing translation management, developer sync, AI assistance, and app text delivery.
Share an idea, report a problem, or ask for help with ReRune.
ReRune is a translation management system for software teams. Product, localization, and engineering teams can manage source copy and translations, use machine translation and AI assistance, create audience variants, and control when text is published to supported apps through OTA updates.
Teams manage source wording and translations together, create variants for brands or audiences selected by their app, and control when edits become published text. DeepL machine translation and OpenRouter AI are optional. Supported OTA SDKs deliver published text updates with cached or bundled fallback, within each platform's limits.
Yes. ReRune is structured around projects, languages, keys, glossaries, metadata, CLI/API sync, and SDK delivery paths so teams can manage several product surfaces from one localization workspace.
Create a ReRune project, choose its languages, then import existing translation resources or connect the repository through agent-assisted onboarding, the CLI, or the API. Your app can keep its current localization model.
Usually a small change. ReRune SDKs plug into the i18n your app already uses, the same pattern as the Android and iOS OTA SDKs from Lokalise and Crowdin and the Phrase iOS SDK, so standard lookups such as t(), getString, and NSLocalizedString stay the same. Vendor-specific calls, such as Phrase's getPhraseString on Android, move back to the standard ones. Swap the SDK package, its setup call, and the credential for one read-only OTA Publish ID, import your existing files, and point the ReRune CLI at the project. Translation memory and workflow history are not part of the translation files and move separately, where your current platform offers an export. Bring glossary terms in as a CSV file, or add them by hand or through the API.
ReRune includes the localization workspace. Plans are based on translation keys and monthly OTA quota. Each key counts once across all of its languages, and there are no limits on app installs or monthly active users. On paid plans, you can add more keys or OTA quota as separate add-ons without switching packages. Compare monthly and annual plans below, or open the pricing page for a full breakdown.
Open source tools are free to download, not free to run. According to their documentation in November 2026, self-hosted Weblate needs PostgreSQL, Valkey or Redis, Celery workers, and Git, with a new release about every month. Self-hosted Tolgee needs a server and a PostgreSQL database, with a recommended size of 4 CPU cores and 16 GB of RAM, and SSO, webhooks, and branching need a paid license. Someone on your team then owns upgrades, backups, and security. ReRune is hosted, with unlimited languages and seats, and paid plans start at €19.95 per month including VAT. In the same month, paid Tolgee Cloud plans started at €69 per month and hosted Weblate at €47 per month, both with monthly billing and excluding VAT.
ReRune is built for product, engineering, localization, and design teams that ship web or mobile products and want localization connected to their normal release workflow. A ReRune plugin for designers is coming soon to Figma Community.
No. Your app keeps its native or framework localization model and bundled resources. ReRune manages translation content and adds CLI/API sync plus runtime delivery through supported SDKs.
No. ReRune also supports dashboard management, platform exports, import workflows, CLI sync, and API-driven workflows. OTA updates are an added delivery path for supported SDKs.
Teams can use ReRune API keys, the ReRune CLI, and platform exports to sync translation files through local scripts or CI/CD pipelines.
Supported ReRune SDKs can deliver approved text at runtime. If an update is unavailable, the app keeps its bundled localization resources as fallback. New code paths and unsupported resource changes still ship through the normal release process.
The app uses the translations bundled with its release. Later offline launches use the OTA cache from the last successful sync, with bundled text as fallback. When the device is online, the SDK checks for published updates and applies new text after a successful download.
The public Flutter, Android, iOS, Kotlin Multiplatform, React, React Native, and Angular SDKs can expose dashboard-published languages at runtime after their locale payloads are fetched. Platform language listings, store metadata, and SDK-specific application configuration can still require a release.
New code paths and localization structures the installed app does not know about still require a release. Examples include new Android resource IDs, new Flutter keys or placeholder signatures, native system text, and app-store language metadata.
Yes. Enable OTA staging for the project and opt a development or QA client into staging mode. The client receives saved, enabled draft snapshots on its next sync from a cache kept separate from published content. Production clients stay on the published path by default.
Yes. Product, localization, and operations users can manage projects, languages, glossaries, translation status, AI assistance, billing context, and team collaboration from the dashboard.
ReRune works with JSON-based i18next resources for React and React Native, root JSON catalogs for Angular ngx-translate and Transloco, generated Flutter localizations, Android string resources, and Apple localization assets. Each integration keeps its platform resource model while ReRune adds sync and supported OTA delivery.
No. DeepL and OpenRouter assistance is optional. Teams can create, edit, import, export, and sync translations through the core workspace without using AI generation.
Yes. A work package groups keys and assigns them to one teammate, with an optional due day and an optional approver. The assignee marks it as done, and the approver approves it or rejects it with a reason, which sends it back. Publishing is a separate permission, so the person who releases the text can be someone else. Each handoff arrives by email and in the dashboard.
ReRune keeps project context, glossary terms, metadata, placeholders, and structured values beside the translation work. Teams can inspect and edit values in the dashboard before they sync or publish them.
Yes. Store different messages under the same translation key. Your app chooses the variant from the user’s test group, brand, or plan, and ReRune delivers the matching text. Main content is used when a variant has no override.
Yes. Open a translation key’s publication history, preview an earlier snapshot, and restore it as the live version. The editor draft remains untouched. Apps receive the restored text on their next successful update check, so cached or offline clients may continue showing the previous text until they refresh.
No. ReRune (rerune.io, spelled with an e) is a translation management and OTA localization platform for software teams, made by BasalBit GmbH in Stuttgart, Germany. It is not related to Rerun (rerun.io), the data visualization tool.
ReRune production data, file storage, and backups are hosted by Hostinger in Frankfurt, Germany. Design screenshots uploaded from the ReRune Figma plugin or the dashboard are stored with bunny.net in Germany. Our Data Processing Agreement and Subprocessors page are public and list each provider with its purpose, data categories, and location or transfer context. DeepL and OpenRouter are optional integration recipients: they receive customer content only when you enable the relevant integration and a user triggers the corresponding translation workflow.
Soon. The ReRune Figma plugin is coming soon to Figma Community. It links text layers in Figma to your translation keys: designers push new and changed copy as drafts of the main language and preview every project language on the canvas; nothing is published from Figma. Developers see where each key is used in the design, and coding agents read the links through ReRune's MCP server. The plugin will work on every ReRune plan, designers join as collaborators at no extra cost, and keys created from Figma count toward your key limit. Figma bills its own seats: the plugin will work on every Figma plan, including the free Starter plan, and Dev Mode features, planned for a later release, will need a paid Figma plan.
Compare published plans or discuss a custom setup for your localization workload.
Free tierNo card required
Starter plan meant for freelancers or small teams
19.95 EUR / month239.4 EUR / year
Team plan meant for small to medium teams
47.7 EUR / month572.4 EUR / year
Plus plan meant for medium teams
110.5 EUR / month1,326 EUR / year
Pro plan meant for big teams
208 EUR / month2,496 EUR / year
Tell us what your team needs and we’ll discuss a plan that fits.
Monthly billing selectedVAT included
More keys or OTA quota? Add what you need.
Extend your paid plan with translation-key or OTA-quota add-ons. Increase either independently without switching packages.