SuperAPI AI Directory

i18n-mobile

Frontend & websites

View repository

Updated 10-15 20:31

About this skill

Mobile i18n

UI strings come from platform resources (or RN i18n), not from literals in views. System locale + in-app override if the product has one. Web: i18n-frontend. API: i18n-backend. Visual: better-mobile-interface.

Non-negotiable rules

  • No new hardcoded UI string (Text("Salvar"), "Welcome \(name)" without LocalizedStringResource).
  • Native plurals (quantity, stringsdict / String Catalog, ICU in RN). Not if count == 1.
  • Dates, times, numbers, currency: platform formatters (DateFormatter, NumberFormatter, DateTimeFormatter, Intl in RN) with the active locale.
  • RTL: layoutDirection / trailing-leading. Test ar even if the MVP is LTR.
  • Locale fallback (e.g., pt-BR → pt → default). No raw key in the production UI.
  • Do not translate: IDs, tokens, logs, API names.

Android (Kotlin / Compose)

res/
  values/strings.xml
  values-pt-rBR/strings.xml
  values-ar/strings.xml
<plurals name="item_count">
    <item quantity="one">%d item</item>
    <item quantity="other">%d items</item>
</plurals>
  • Compose: stringResource(R.string.x), pluralStringResource. Not getString in ViewModel if you can pass UiText / resource id.
  • LocaleList / per-app language (AppCompatDelegate.setApplicationLocales) if the product allows a language ≠ the system one.
  • tools:locale in previews. Pseudolocale (en-XA) in debug.
  • Layout: start/end, not left/right. autoMirrored in directional drawables.

App: android-development. UI: jetpack-compose.

iOS (Swift / SwiftUI)

  • String Catalog (.xcstrings) in new code. LocalizedStringResource / String(localized:).
  • Text("key") only if the key is in the catalog — prefer Text(.saveAction) with LocalizedStringKey documented.
  • Plurals in the catalog (variations). Inflect / format with locale: .autoupdatingCurrent.
  • Locale.current / environment(\.locale). In-app override: environment(\.locale, …) + persistence.
  • Format: Text(date, format: Date.FormatStyle().locale(...)) — not DateFormatter with yyyy fixed for UI.
  • RTL: layoutDirection; Trailing/Leading. RTL screenshots in preview.

Language/UI: swift / swiftui-development. Widgets: strings in the extension (widgetkit) with the same catalog/App Group if shared.

React Native / Expo

  • expo-localization for device locale/RTL. Catalog: i18n-js / react-i18next / i18next — the one in the repo.
  • I18nManager.forceRTL aligned to the locale; reload if the platform requires it.
  • Do not mix native strings.xml and JS JSON for the same key without a bridge. Prefer one source (JS) for RN UI; native only in native modules.
  • Deep links and store listing are another pipeline (ASO) — do not forget InfoPlist / AndroidManifest translatable labels.

App: react-native-development.

Share locale with the backend

  • Send Accept-Language and/or X-Locale / field in the profile. The server does not guess from the IP.
  • Errors: prefer code stable and translate on the client (errors.not_found) — see i18n-backend.
  • Push/email: locale saved in the profile, not the device's at the time of the job.

Anti-patterns

  • Concatenating sentences ("Olá, " + name + "!")
  • String(format:) with order of %@ that breaks in another language
  • One if language == .portuguese in the View
  • DateFormatter with locale en_US_POSIX in UI (POSIX only for ISO parsing)
  • Forget RTL / quantity zero/few/many when the language requires it
  • Translate in the ViewModel for logging

Integration with other skills

  • Android: android-development / jetpack-compose
  • iOS: swiftui-development / widgetkit
  • RN: react-native-development
  • Web: i18n-frontend
  • API: i18n-backend
  • IAP copy: storekit / play-billing (Store texts stay in the Console; in-app paywall in the catalog)
  • Copy: website-copywriting

Completion criteria

  • New strings in resources/catalog; native plurals
  • Formatters with locale; no fixed “foreign” date in the UI
  • RTL verified or logical layout
  • User locale sent to the API when there is a server
  • Fallback without raw keys