Seventeen languages, done properly: how Googly Player handles translation, RTL and plurals

Endonyms, right-to-left layout, per-app locales on Android 13+, and the App Bundle setting that stops translations from vanishing on users' phones.

Binary Buddies · 5 min read · 0 views
A city at night, every window litApartment windows glow in many colours across a night skyline, a string of lights hangs over a balcony, and a phone playing music rests on the rail beside a pair of headphones.

A user switches an app to Arabic. The menus come back in Arabic, but the line that says how many videos they have puts the number on the wrong side of the label. Another user picks Hindi on a phone set to English, and the picker quietly keeps showing English. There is no crash and nothing in the logs. A third changes language and the notification for the music playing in the background stays in the old one.

None of these failures shows up in a demo on a developer's phone, because a developer's phone usually has every resource installed and runs in the language the app was written in. They show up for real users, on phones bought from a shop, in a language the team does not read. An in-app language picker that half works is worse than none: it promises a choice and then ignores it.

Googly Player is our Android app for videos, music and photos, and it ships in 17 languages through a picker of its own, separate from the system language. This is how we built that picker so that it holds up on a real device, and what each decision protects against.

Key takeaways

  • The language choice is applied to the whole app process, so services, notifications and dialogs follow it, not only the screens.
  • Language splits are turned off in the App Bundle; with them on, Play delivers only the system language and the picker silently falls back to English.
  • Arabic and Urdu get full right-to-left support, down to how their names sit in the picker.
  • Counts are formatted rather than glued together, and plurals use plural resources, because Arabic needs six forms and Russian four.
  • On Android 13 and later the choice is handed to the platform and also appears in system Settings.

Seventeen languages, chosen inside the app

Googly Player has a full in-app language picker that works independently of the language the phone itself is set to. A phone can stay in English for everything else while Googly Player runs in Bengali, or the other way round. The languages available are:

  • English, Hindi (हिन्दी), Spanish (Español), Arabic (العربية), French (Français), Bengali (বাংলা)
  • Portuguese (Português), Russian (Русский), Urdu (اردو), Indonesian (Bahasa Indonesia), German (Deutsch)
  • Japanese (日本語), Turkish (Türkçe), Vietnamese (Tiếng Việt), Korean (한국어), Italian (Italiano), Gujarati (ગુજરાતી)

That set mixes Latin, Devanagari, Bengali, Gujarati, Cyrillic, Arabic, Japanese and Korean scripts, and two right-to-left languages. Each of those brings its own way to break an Android app, which is why the list matters less than what we did to make every entry on it behave. The sections below take those problems one at a time.

17languages in the in-app picker
2right-to-left languages: Arabic, Urdu
6plural forms Arabic needs
4plural forms Russian needs

A picker that names each language in its own script

A language picker is used by exactly the person who cannot yet read the app. If it lists "Gujarati" in English, a Gujarati speaker whose app is currently in English has to know the English word for their own language to find it. So every entry in our picker leads with the language's endonym, its own name in its own script, as the primary label, with the English name underneath for everyone else.

Seventeen entries is long enough to scroll past, so the picker is searchable. It also opens with a Suggested section built from the device locale: the language the phone is already set to is the most likely candidate, and it sits at the top rather than somewhere in the middle of an alphabetical list.

How the language picker is organisedThe device locale feeds a Suggested section and a search query filters all seventeen languages. Each entry shows the endonym first with the English name below, and the Arabic entry is anchored to the right.Inside the language pickerDevice localeSearch querySuggested sectionFiltered list of 17DeutschGermanالعربيةArabicRTL anchored right
Two routes into the list, and every entry leads with the language's own name, with the English name underneath.

Right-to-left from the first screen

Arabic and Urdu read right to left, and Googly Player has full RTL support for both. That includes a detail most pickers miss: the language names inside the picker itself are anchored correctly. A list where العربية and اردو hang off the left edge like English words looks broken to the people it is meant for, and it is the very first screen they see in their language.

RTL also reaches into places that look like plain text. A label followed by a number is a layout decision as much as a translation, and in Arabic and Urdu the number belongs on the other side. We handle that with formatted strings rather than string concatenation, which comes up again below with the rest of the number handling, because it is the most common way an otherwise well-translated app reads wrong in a right-to-left language.

One setting that reaches services, notifications and dialogs

Changing the locale of an activity changes what that screen shows. It does not change the text a background service builds, and a media app does a great deal of work outside its screens. Googly Player plays audio in the background through a foreground service and posts a media notification for it. If the language choice stopped at the activities, that notification and any dialog raised outside them would stay in the previous language.

So the choice is applied process-wide through AppCompatDelegate.setApplicationLocales. That covers services, notifications and dialogs as well as activities, which means the whole app speaks one language at a time.

On Android 13 and later we go one step further and hand the choice to the platform. The selected language then also appears under Settings › Apps › Googly Player › Language, where Android itself manages it. A user can change it from there without opening the app, and the system's own view of the app's language agrees with ours.

How one language choice spreads through the appThe in-app picker calls setApplicationLocales, which applies the language to activities, services, notifications and dialogs, and on Android 13 and later also registers it in system Settings.One choice, applied everywhereIn-app language pickersetApplicationLocalesAndroid 13+ SettingsActivitiesServicesNotificationsDialogs
The choice is set once for the whole process, so the background notification follows it just as the screens do.

The failure that never crashes: App Bundle language splits

This is the bug we most want other Android teams to know about. An App Bundle lets Google Play split resources by language and install only the ones matching the phone's system language. For most apps that is a sensible saving. For an app with its own language picker it is a trap: a user on an English phone who chooses Japanese in the app has no Japanese resources installed, and Android falls back to the default strings.

The result is a picker that appears to work and renders everything in English. Nothing crashes, nothing is written to the logs, and on a development device with everything installed it never reproduces. We deliberately disable language splits in the App Bundle so that every translation ships in the base APK, which is what makes the picker honour any of the 17 choices on any phone.

App Bundle language splits on versus offWith language splits on, only system-language resources are delivered and the picker renders English with no crash and nothing logged. With splits disabled, every translation is in the base APK and the chosen language renders.What the App Bundle shipsLanguage splits onLanguage splits disabledOnly system language deliveredPicker renders English anywayNo crash, nothing in logsEvery translation in base APKPicker gets every languageChosen language renders
The left column is the silent failure; the right column is the build setting that prevents it.

Numbers and plurals that read correctly

Media apps are full of counts: how many videos, how many tracks, how many photos. The quick way to write one is to join a label and a number, "Total Videos: " + n. In Arabic and Urdu that puts the number on the wrong side of the label, because the code has fixed the order that only the translation should decide. We never concatenate counts. Every one is a format string, "Total Videos: %d", and each translation places the number where its language puts it.

Format strings fix the position of a number but not the grammar around it. English has a singular and a plural; Arabic needs six grammatical forms for a number and Russian needs four, and a single format string cannot express that. So every count with a noun attached uses Android plural resources, which let each translation supply as many forms as its language actually has. The result is a count that reads like it was written in the language, rather than translated around a number.

Formatting counts and plural formsA concatenated label puts the number on the wrong side in right-to-left languages, while a format string lets the translation place it. Arabic needs six plural forms and Russian four.Numbers in the right place"Total Videos: " + nNumber lands on wrong side"Total Videos: %d"Translation places the numberPlural forms per numberArabic6 formsRussian4 forms
Top: the order of label and number belongs to the translation. Bottom: why one format string per count is not enough.
Dusk over a long row of rooftopsA low sun glows on the horizon behind layered hills while a long row of houses lights up window by window and sparks drift upward.

Who it is for and what it needs

The language support is for anyone who wants Googly Player in a language other than the one their phone runs in, or who simply reads one of these 17 languages more comfortably than English: a household sharing a phone, a user who keeps the system in English for work, a reader of Arabic or Urdu who expects the app to run right to left properly. For engineers and technical buyers, it is a worked example of what a language picker needs beyond translated strings.

Googly Player runs on Android. The in-app picker is part of the app on every device it supports; the system-level entry under Settings › Apps › Googly Player › Language needs Android 13 or later, because that is where we hand the choice to the platform. Every translation ships in the base APK, so nothing extra downloads when a user switches language.

  1. Open the language picker

    Googly Player has its own picker, separate from the phone's language setting. Changing it affects only Googly Player.

  2. Pick from Suggested or search

    The Suggested section reflects the device locale. Otherwise, search the list; each language is shown by its own name, with the English name below it.

  3. Use it everywhere in the app

    The choice applies across the whole app, including background playback notifications and dialogs. Arabic and Urdu switch the app to right-to-left.

  4. On Android 13+, manage it from Settings

    The same choice appears under Settings › Apps › Googly Player › Language and can be changed there without opening the app.

Questions

Does changing Googly Player's language change my phone's language?

No. The in-app picker is independent of the system language and applies only to Googly Player. On Android 13 and later the choice is also visible in the app's own entry in system Settings, but it still applies to Googly Player alone.

Why does the picker show names like हिन्दी and Deutsch instead of Hindi and German?

Each language is listed first by its own name in its own script, so someone who reads it can find it even if the app is currently in a language they do not read. The English name appears underneath.

Will the notification for background music follow my language choice?

Yes. The language is applied process-wide through AppCompatDelegate.setApplicationLocales, which covers services, notifications and dialogs as well as the app's screens.

Do I need to download anything extra to use another language?

No. Language splits are disabled in the App Bundle, so every translation ships in the base APK. That is also what stops the picker from falling back to English on a phone set to a different system language.

How are counts handled in Arabic, Urdu and Russian?

Counts use format strings rather than joined text, so each translation decides where the number goes, and plural resources supply every grammatical form: six for Arabic and four for Russian.

  • #Android localization
  • #Android media app
  • #Android plural resources
  • #Googly Player
  • #in-app language picker

Comments

Add a comment
Sign in with Google to join the conversation