Localization & RTL (Java)
Localization means translating an app's visible text so people in different regions see it in their own language. Android builds this in using the same resource-qualifier system already seen for night mode in the previous lesson — just applied to language instead of theme.
1. strings.xml Per Language
The default res/values/strings.xml holds your base-language text (typically English). A parallel folder named with a language code — res/values-hi/strings.xml for Hindi, res/values-es/ for Spanish, and so on — holds the same string names translated into that language. Android automatically loads whichever file matches the device's active language setting.
<!-- res/values/strings.xml (default / English) -->
<resources>
<string name="add_recipe_button">Add Recipe</string>
</resources>
<!-- res/values-hi/strings.xml (Hindi) -->
<resources>
<string name="add_recipe_button">नई रेसिपी जोड़ें</string>
</resources>
// Referencing it in RecipeBox — same code, any language
Button btnAddRecipe = findViewById(R.id.btnAddRecipe);
btnAddRecipe.setText(R.string.add_recipe_button);
- R.string.add_recipe_button is the same identifier in Java regardless of language — only the resolved text changes.
- If a device's language has no matching values-XX folder, Android silently falls back to the default values/strings.xml.
- This mirrors the exact qualifier pattern used for values-night in the previous lesson — Android's resource system reuses the same idea for language, theme, screen size, and more.
2. Formatted Strings with Placeholders
When a message needs to embed a dynamic value — like a count — resist the urge to build it with Java string concatenation. Word order and grammar vary by language, so a string built by gluing pieces together in Java (e.g. count + " recipes found") can produce grammatically broken sentences once translated, because some languages need the number in a different position, or need different word forms depending on the count. Defining the entire sentence as one translatable string, with a placeholder, solves this correctly.
<!-- res/values/strings.xml -->
<resources>
<string name="recipe_count">%1$d recipes found</string>
</resources>
// RecipeBox's search-results screen
int count = recipeList.size();
String message = getString(R.string.recipe_count, count);
tvResultsSummary.setText(message);
- %1$d marks where the first integer argument is inserted; getString(int, Object...) fills it in.
- A translator working on values-hi/strings.xml can freely reposition %1$d anywhere in the Hindi sentence — the placeholder mechanism doesn't force English word order onto other languages.
- Hardcoding count + " recipes found" in Java bakes English grammar into the app and cannot be fixed by a translator at all, since there's no string resource to translate.
3. Right-to-Left (RTL) Language Support
Languages like Arabic and Hebrew read right-to-left, which means an entire layout should mirror: content that starts on the left in English should start on the right in Arabic. Android handles this automatically — but only if layouts are written using direction-aware attributes instead of literal left/right ones.
<!-- Avoid: hardcodes a physical side, never mirrors -->
<TextView
android:paddingLeft="16dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<!-- Prefer: describes a logical side, mirrors automatically in RTL -->
<TextView
android:paddingStart="16dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
start means "the side text begins from" — the left in English, the right in Arabic — while end is the opposite. Using paddingStart/paddingEnd (and similarly layout_marginStart/layout_marginEnd) instead of paddingLeft/paddingRight lets Android flip RecipeBox's recipe cards, icons, and text alignment automatically the moment the device's language is RTL — no separate layout file needed.
The manifest must also opt in to RTL layout mirroring:
<!-- AndroidManifest.xml -->
<application
android:supportsRtl="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name">
...
</application>
4. Previewing Languages and RTL Without Switching Devices
Android Studio's Layout Editor includes a "Preview" panel that can render the same layout in multiple configured locales side by side, and a dedicated "Right-to-Left" preview mode that simulates RTL mirroring — all without changing the emulator or device's actual system language. This is the fastest way to catch a mistranslated string or a layout that didn't mirror correctly, long before testing on a real device set to Arabic or Hebrew.
Localization Flow
Troubleshooting
Translated text not showing up? → Confirm the string name in values-XX/strings.xml matches exactly — a typo silently falls back to the default language.
Layout not mirroring in RTL? → Check for leftover paddingLeft/paddingRight or layout_alignParentLeft-style attributes; these never mirror, only start/end variants do.
Placeholder shows the wrong grammar? → Let a native speaker review the translated string; the placeholder mechanism handles word order, but grammar (like pluralization) may still need language-specific string variants.