GoLocalise

Android engineering guide

Android localization with Kotlin, Compose, and OTA updates

Android apps traditionally package localized resource XML with the APK or App Bundle. OTA localization adds reviewed, versioned copy that refreshes after installation while Android resources remain the reliable offline baseline.

How Android resource localization works

Android packages default strings in res/values/strings.xml and locale-specific resources in directories such as values-ar. The resource system chooses the best match for the device configuration, while Views and Jetpack Compose read values through generated resource identifiers.

These resources are compiled into the application. They are fast, type-visible, and available offline, but changing them normally means building and distributing another APK or App Bundle. Keep resources for essential fallback copy even when remotely delivered translations are enabled.

Where OTA localization fits

OTA localization is useful for copy corrections, reviewed translation updates, and languages already supported by the application's UI. A client fetches a versioned artifact outside the composition or view lookup path, stores it locally, and resolves later calls from memory.

It does not add Android layouts, change navigation, or guarantee that a screen supports a new writing direction. Those remain application engineering responsibilities. See the Arabic and RTL engineering guide before enabling an RTL locale.

Add the GoLocalise Android SDK

The SDK is published on Maven Central for Android API 26+. Ensure mavenCentral() is present in dependency repositories, then add the verified coordinate.

build.gradle.kts
dependencies {
    implementation("me.golocalise:golocalise-android:1.0.0")
}

Configure cache and Android-resource fallback

Map localization keys explicitly to resource IDs so references remain visible to Android's resource shrinker. Initialization and refresh are suspend functions; translation() itself performs no network or disk I/O.

Kotlin
val client = GoLocaliseClient(
  GoLocaliseConfiguration(
    baseUrl = URL("https://api.golocalise.me"),
    token = "gl_sdk_REPLACE_ME",
    projectId = "PROJECT_ID",
    environment = "production",
    locale = "en",
    cache = FileCacheAdapter(File(context.cacheDir, "golocalise")),
    bundled = AndroidResourcesBundledTranslations(
      context.resources,
      mapOf("common.welcome" to R.string.common_welcome),
    ),
  ),
)

lifecycleScope.launch { client.initialize() }

val title = client.translation(
  "welcome",
  namespace = "common",
  fallback = "Welcome",
)

Offline behavior and safe releases

The Kotlin SDK loads persistent cache before refreshing. It validates project and environment scope, release order, artifact origin, size, and SHA-256, then writes cache atomically. If a request or validation fails, the last-known-good OTA content and mapped Android resources remain available.

Production content should move through review and environment promotion. GoLocalise releases are immutable, and rollback creates a new release rather than modifying history. The OTA architecture guide explains the full lifecycle.

Android localization implementation checklist

  • Bundle critical default and target-locale resources.
  • Keep format placeholders compatible across every translation.
  • Initialize from cache outside the synchronous UI lookup path.
  • Test process restart, airplane mode, timeouts, and invalid artifacts.
  • Test Compose screens with long text, font scaling, plurals, and RTL.
  • Ship only public read-only SDK credentials in the app.

Implement with GoLocalise

Connect a project to a production-ready SDK.

Publish a reviewed release, create a read-only SDK credential, and keep bundled translations as the final fallback.