agentsclimarketplace

Android localization

Skill almasumdev/awesome-kotlin-android-agent-skills/.github/skills/ui/android-localization

Curated agent skills, conventions, and workflows for building Kotlin Android apps with AI coding agents.

Install
npx -y skills add almasumdev/awesome-kotlin-android-agent-skills --skill android-localization

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Expert guidance on Android localization, res/values-*, string plurals, ICU MessageFormat, RTL layouts, and per-app locale (AppCompat 1.7 / Android 13+). Use this for any i18n / l10n task.

SKILL.md

4.7 KB, as published. Nobody here has run it

Android Localization & Internationalization

Instructions

1. Resource Directory Strategy

app/src/main/res/
├── values/            strings.xml (default, English)
├── values-es/         Spanish
├── values-pt-rBR/     Brazilian Portuguese (region-qualified)
├── values-ar/         Arabic (auto-RTL)
├── values-night/      dark theme overrides
└── values-w600dp/     tablet overrides

Rules:

  • Default values/strings.xml is English. Never leave English strings in region-specific folders.
  • Region qualifier format is -rXX (BCP-47 lowercase-then-r-then-uppercase region).
  • Never concatenate strings in code. Use placeholders and ICU.

2. Plurals with ICU MessageFormat

<!-- res/values/strings.xml -->
<string name="unread_count">{count, plural,
    =0 {No unread messages}
    one {# unread message}
    other {# unread messages}
}</string>

Load with getQuantityString replacement:

val formatted = MessageFormat.format(
    getString(R.string.unread_count),
    mapOf("count" to count),
)

Use android.icu.text.MessageFormat (API 24+, matches our minSdk = 24). It handles plural, select, and gender correctly in every locale. Do not use the legacy <plurals> XML tag for new strings — ICU is more flexible.

3. Interpolation in Compose

<string name="greeting">Hello, %1$s!</string>
Text(stringResource(R.string.greeting, user.name))

For ICU patterns pass through MessageFormat.format and wrap in a helper:

@Composable
fun icuStringResource(@StringRes id: Int, vararg args: Pair<String, Any>): String {
    val template = stringResource(id)
    return remember(id, args) { MessageFormat.format(template, args.toMap()) }
}

4. Right-to-Left (RTL) Support

In AndroidManifest.xml:

<application android:supportsRtl="true" ... >

In Compose:

  • Use start/end alignment (already default in Compose; Arrangement.Start flips automatically).
  • Mirror directional icons: Icon(Icons.AutoMirrored.Filled.ArrowBack, null) — note the AutoMirrored package.
  • Test with Developer Options → Force RTL layout direction and with Arabic (values-ar) locale.

5. Per-App Locale (Android 13+, AppCompat 1.7+)

// Set from Settings screen
AppCompatDelegate.setApplicationLocales(LocaleListCompat.forLanguageTags("pt-BR"))

// Read
val current = AppCompatDelegate.getApplicationLocales()[0]

Declare the supported set so the system can expose a per-app language picker:

<!-- res/xml/locales_config.xml -->
<locale-config xmlns:android="http://schemas.android.com/apk/res/android">
    <locale android:name="en"/>
    <locale android:name="es"/>
    <locale android:name="pt-BR"/>
    <locale android:name="ar"/>
</locale-config>
<application android:localeConfig="@xml/locales_config" ... >

For Android 12 and below, AppCompat stores the choice in a backing store and re-applies it at each Activity create.

6. Dates, Numbers, Currency

Never format these manually. Use java.text.NumberFormat, java.text.DateFormat, or kotlinx.datetime combined with the user's locale:

val money = NumberFormat.getCurrencyInstance(Locale.getDefault()).format(19.99)
val day   = DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM).withLocale(Locale.getDefault()).format(LocalDate.now())

7. Pseudolocales for Testing

Enable Developer Options → "Force pseudolocale", pick en-XA (accented) or ar-XB (RTL-bidi). This catches:

  • Hard-coded English.
  • Strings that overflow at +40% length.
  • Layouts that don't flip for RTL.

Also add to your debug build:

android.defaultConfig { /* ... */ }
android.buildTypes.debug { pseudoLocalesEnabled = true }

8. Translation Workflow

  • Keep strings.xml sorted alphabetically by key; use translatable="false" for non-translatable identifiers.
  • Use tools:ignore="MissingTranslation" only for intentionally untranslated keys (e.g., brand names).
  • Integrate with a TMS (Crowdin, Lokalise, Phrase) via their Gradle plugin so translators pull and push directly.

Checklist

  • supportsRtl="true" and a locales_config are declared in the manifest.
  • All strings come from resources; no hard-coded English in Kotlin or XML.
  • Plurals and selects use ICU MessageFormat.
  • Directional icons use Icons.AutoMirrored.*.
  • Dates/numbers/currency format with the current Locale.
  • pseudoLocalesEnabled = true in debug builds; screens tested at en-XA and ar-XB.
  • Per-app locale API is wired for Android 13+.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.