Implementing Localization
1. Creating String Resources
| Resource Name | Value | Description |
|---|---|---|
| strings.xml | <string name="app_name">MyApp</string> |
Default string resource file |
| strings.xml (localized) | <string name="app_name">MiAplicación</string> |
Localized string resource file for Spanish |
Example: Define a localized string resource
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="welcome_message">Welcome to our app!</string>
<string name="user_greeting">Hello, %1$s!</string>
</resources>
Note: Use
%1$s for string placeholders and %d for integers in localized strings.Example: Using string resources in Kotlin
val welcomeMessage = getString(R.string.welcome_message)
val userGreeting = getString(R.string.user_greeting, userName)
2. Adding Language Qualifiers
| Qualifier | Language | Notes |
|---|---|---|
| values | en |
English (default) |
| values | es |
Spanish |
| values | fr |
French |
| values | de |
German |
| values | ja |
Japanese |
| values | ko |
Korean |
| values | pt |
Portuguese |
| values | ru |
Russian |
| values | zh |
Chinese (Simplified) |
| values | zh-rTW |
Chinese (Traditional) |
Example: Language Resource Directory Structure
values/
strings.xml
values-es/
strings.xml
values-fr/
strings.xml
values-ja/
strings.xml
values-zh/
strings.xml
3. Using Plurals for Quantities
| Resource | Description | Usage |
|---|---|---|
| plurals | Resource type for handling pluralized strings based on quantity | <plurals name="numberOfItems"> |
Example: Defining Plurals in XML
<?xml version="1.0" encoding="utf-8"?>
<resources>
<plurals name="numberOfItems">
<item quantity="zero">No items</item>
<item quantity="one">One item</item>
<item quantity="two">Two items</item>
<item quantity="few">{count} items</item>
<item quantity="many">Many items</item>
<item quantity="other">{count} items</item>
</plurals>
</resources>
Example: Using Plurals in Kotlin
val count = 5
val message = getString(R.plurals.numberOfItems, count, count)
// Result: "5 items"
Note: The
quantity attribute in <item> tags corresponds to Android's plural rules, which vary by language.4. Formatting Dates and Times
| Method | Description | Example |
|---|---|---|
| formatDate() | Formats a date using the specified pattern | |
| formatTime() | Formats a time using the specified pattern | |
| formatDateTime() | Formats a date and time using the specified pattern | |
Example: Formatting with Locale
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
import java.util.Locale
val dateTime = LocalDateTime.now()
val formatter = DateTimeFormatter.ofPattern("d MMM yyyy, HH:mm", Locale.FRENCH)
val formattedDate = dateTime.format(formatter)
Note: Use
Locale.getDefault() to get the current locale.Warning: Ensure that date/time patterns match the expected format for the target locale.
5. Formatting Numbers and Currency
| Feature | Description | Example |
|---|---|---|
| Number formatting | Formats numbers according to locale-specific rules. | |
| Currency formatting | Formats currency values with locale-specific symbols and rules. | |
Example: Formatting Numbers in Different Locales
val number = 1234567.89
val usFormatter = NumberFormat.getInstance(Locale.US)
val deFormatter = NumberFormat.getInstance(Locale.GERMANY)
val frFormatter = NumberFormat.getInstance(Locale.FRANCE)
println(usFormatter.format(number)) // 1,234,567.89
println(deFormatter.format(number)) // 1.234.567,89
println(frFormatter.format(number)) // 1 234 567,89
Example: Formatting Currency in Different Locales
val amount = 1234.56
val usFormatter = NumberFormat.getCurrencyInstance(Locale.US)
val deFormatter = NumberFormat.getCurrencyInstance(Locale.GERMANY)
val frFormatter = NumberFormat.getCurrencyInstance(Locale.FRANCE)
println(usFormatter.format(amount)) // $1,234.56
println(deFormatter.format(amount)) // 1.234,56 €
println(frFormatter.format(amount)) // 1 234,56 €
6. Using RTL Support
| Property | Description | Values |
|---|---|---|
| android:supportsRtl | Enables RTL layout support for the app | true or false |
| android:layoutDirection | Defines the layout direction for a view or layout | ltr, rtl, inherit |
| android:textDirection | Defines the text direction for a view or layout | ltr, rtl, inherit |
Example: Using Layout Direction in XML
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layoutDirection="rtl"
... >
Example: Setting Text Direction Programmatically
val textView = findViewById<TextView>(R.id.textView)
textView.setTextDirection(View.TEXT_DIRECTION_RTL)
Note: RTL support requires proper handling of layout and text direction in UI components to ensure correct rendering in right-to-left languages like Arabic or Hebrew.
7. Translating String Resources
| Resource | Type | Description |
|---|---|---|
| strings.xml | XML | Main resource file for string translations |
| strings.xml (localized) | XML | Translated versions in language-specific folders |
Example: Translating a String Resource
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="welcome_message">Welcome to our app!</string>
</resources>
Example: Translated String Resource (Spanish)
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="welcome_message">¡Bienvenido a nuestra aplicación!</string>
</resources>
Note: Android automatically selects the appropriate
strings.xml based on device language settings.
Localization Workflow
- Create base
strings.xmlinres/values/ - Create localized versions in
res/values-xx/wherexxis language code - Use
@string/welcome_messagein layouts to reference translated strings
8. Testing Different Locales
| Locale | Code | Notes |
|---|---|---|
| French (France) | fr-FR |
Default for France |
| German (Germany) | de-DE |
Default for Germany |
| Spanish (Spain) | es-ES |
Default for Spain |
| Japanese (Japan) | ja-JP |
Default for Japan |
Note: Use
Locale.setDefault() to change the app's default locale programmatically.
Warning: Ensure all string resources are properly localized before testing.
Workflow: Testing Locale Changes
- Set device/emulator locale to target language
- Rebuild and reinstall app
- Verify all UI elements adapt to new language
- Check for text overflow or layout issues
9. Handling Per-App Language Preferences
| Property | Value | Description |
|---|---|---|
| locale | Locale.getDefault() |
Current app locale used for resource lookup |
| resources.configuration.locale | Configuration.locale |
Current configuration locale for UI |
Example: Setting App Locale Programmatically
import android.content.res.Configuration
import java.util.Locale
fun setAppLocale(context: Context, languageCode: String) {
val locale = Locale(languageCode)
val config = Configuration(context.resources.configuration).apply {
setLocale(locale)
}
context.createConfigurationContext(config)
}
Note: Changes to locale require restarting the activity or using
recreate() to reflect in UI.
Key Points
- Use
Locale.setDefault()to change the default locale for the app - Update
Configuration.localeto reflect changes in UI and resources - App locale changes do not automatically update the UI; you must manually refresh or restart the activity
10. Using Grammatical Inflection API
| Property | Description | Example |
|---|---|---|
| pluralize() | Pluralizes a noun based on the grammatical context | val plural = "cat".pluralize() // "cats" |
| singularize() | Converts a plural noun to its singular form | val singular = "cats".singularize() // "cat" |
| ordinalize() | Converts a number to its ordinal form (e.g., 1st, 2nd) | val ordinal = 3.ordinalize() // "3rd" |
Example: Using pluralize in Android
import java.util.Locale
val locale = Locale.getDefault()
val pluralForm = "item".pluralize(locale) // "items" in English
Note: The
pluralize() function requires the androidx.core library or a third-party library like inflector.Warning: Grammatical inflection APIs may not support all languages or complex rules. Always test in target locales.