Localization (l10n) — the adaptation of mobile app content to the language, region, and cultural characteristics of the target audience. Unlike internationalization (i18n), where the code is prepared for translation, localization is the actual process of translating strings, formatting dates, numbers and currencies, selecting images, and considering local norms. On iOS, translations are stored in Localizable.strings (.lproj folders for each language), on Android — in values-ru, values-de, and other resource directories. Learn more in the Android Localization Guide.
Key Takeaways
Localization (abbreviated as l10n — 10 letters between “l” and “n”) is the process of adapting an application to a specific language and region. If i18n is the architectural foundation, then l10n is the content. i18n makes translation possible, l10n carries it out. Localization includes: translating all interface texts, adapting date and number formats, replacing culturally sensitive images, adjusting legal texts (privacy policy, EULA), configuring payment systems for the region, and testing on target devices.
Business ROI — localization directly impacts conversion. According to CSA Research (2023), 76% of users prefer to purchase in apps in their native language, and 40% never buy in a foreign language. Localization into Japanese for a retail app increases conversion by an average of 150% (Google, 2022). Localized apps receive 2–3 times more organic installs in regional App Stores and Google Play thanks to regional ASO (keywords in the target language).
i18n vs l10n — two sides of the same process. i18n: extracting strings into resources, RTL support, number formatting. Done once by developers. l10n: translating strings, content adaptation, local testing. Done repeatedly by translators and QA for each locale. At IT Sectr, we allocate 20–30% of sprint time for localization for each new language — this includes translation, review, device testing, and bug fixing.
Localizable.strings — the main file for storing translations in iOS. Each locale has its own .lproj folder: en.lproj/Localizable.strings, ru.lproj/Localizable.strings, de.lproj/Localizable.strings. Format: “key” = “value”; (with semicolon). Apple uses Base Internationalization: Storyboard and XIB are created once (Base.lproj), and interface strings are exported to Localizable.strings for each language. This eliminates the need to create copies of XIB for each locale.
// en.lproj/Localizable.strings
// "settings.title" = "Settings";
// "profile.greeting" = "Hello, %@!";
// "items.count" = "%d item(s)";
// ru.lproj/Localizable.strings
// "settings.title" = "Settings";
// "profile.greeting" = "Hello, %@!";
// "items.count" = "%d item(s)";
// Loading string by key
navigationItem.title = NSLocalizedString(
"settings.title",
comment: "Settings screen title"
)
// String with parameter
let name = "Anna"
greetingLabel.text = String.localizedStringWithFormat(
NSLocalizedString("profile.greeting", comment: ""), name
)
// XLIFF import (Xcode → Editor → Import Localizations)
// Automatically updates .lproj files after translator's work
Base Internationalization — Apple’s approach where the interface (Storyboard, XIB) is created once in Base.lproj. When adding a language, Xcode exports strings from Base to an XLIFF file. The translator translates the XLIFF. After import, Xcode creates .lproj with translated strings. Advantage: no need to duplicate XIB for each language. Limitation: for RTL languages (Arabic, Hebrew), a separate XIB with mirrored layout may be required.
InfoPlist.strings — a file for localizing the app name (CFBundleDisplayName), camera/microphone permissions (NSCameraUsageDescription), and other values from Info.plist. Created in .lproj: ru.lproj/InfoPlist.strings. Format: CFBundleDisplayName = “My App”; NSCameraUsageDescription = “The app needs camera access to take photos”;. Without InfoPlist.strings localization, system dialogs will be in English.
Android resources for localization are organized through qualifiers in directory names. For Russian — res/values-ru/, for German — res/values-de/, for Brazilian Portuguese — res/values-pt-rBR/. Android supports over 160 locales. The system automatically selects resources based on the device language (Locale.getDefault()). If an exact locale is not found, resources from values/ (base locale, usually en) are used.
// res/values/strings.xml (base — English)
<string name="settings_title">Settings</string>
<string name="greeting">Hello, %s!</string>
// res/values-ru/strings.xml (Russian)
<string name="settings_title">Settings</string>
<string name="greeting">Hello, %s!</string>
// res/values-de/strings.xml (German)
<string name="settings_title">Einstellungen</string>
<string name="greeting">Hallo, %s!</string>
// Kotlin — single code for all languages
textView.text = getString(R.string.settings_title)
// String with parameter
val greeting = getString(R.string.greeting, userName)
// Localized images
// res/drawable-ru/flag.png — flag for Russian version
// res/drawable/flag.png — default flag
// Layout localization (for RTL languages)
// res/layout-ar/activity_main.xml — Arabic version
Localization beyond strings — Android allows localizing images (res/drawable-ru/), colors (res/values-ru/colors.xml), dimensions (res/values-ru/dimens.xml), animations, menus, and even entire layouts. For languages with different word lengths (German is 30–40% longer than English), use localized dimens.xml with increased button widths. For regions with different color symbolism (white is mourning in China), use localized colors.xml.
Testing — switch the device language to the target language via Settings → System → Language. Check: all strings are translated, dates are formatted correctly, numbers display with the proper separator, images match the region, the layout does not break with long strings. For automation, use Espresso with LocaleTestRule (Android Testing Library) — it allows running tests with different locales without manually switching the language.
Cultural specifics — localization is not limited to translating strings. Color symbolism varies: red is luck in China, danger in the US, mourning in South Africa. White is purity in Europe, mourning in China. Gesture icons: thumbs up is positive in the US, an insult in the Middle East. Images of people: in Arab countries, images of women in swimsuits are unacceptable. Religious symbols: cross, crescent, Star of David should only be used in appropriate context.
Legal requirements — each country has its own digital product laws. GDPR (EU) — mandatory consent for cookies and data processing. CCPA (California) — right to data deletion. Personal Data Law (Russia, 152-FZ) — data storage on Russian servers. LGPD (Brazil) — GDPR equivalent. Payments: in China, Alipay/WeChat Pay are needed, in India — UPI, in Brazil — Boleto and PIX. Configure the payment gateway for the region before launching localization.
| Aspect | USA | China | UAE | Germany |
|---|---|---|---|---|
| Payment System | Apple Pay, Cards | Alipay, WeChat Pay | Cards, Apple Pay | PayPal, Giropay |
| Brand Colors | Any | Red — luck | Green — Islam | Black/Yellow |
| Social Networks | Instagram, X | WeChat, Douyin | WhatsApp, X | WhatsApp, X |
| Date | MM/dd/yyyy | yyyy/MM/dd | dd/MM/yyyy | dd.MM.yyyy |
| Data Law | CCPA | PIPL | PDPL | GDPR |
Examples and content — adapt examples to the region. For German localization, use the metric system (kg, km), for American — imperial (lb, mi). Phone numbers, postal codes, addresses — all format differently. Currency examples: ¥1000 in Japan, $9.99 in the US, 999 ₽ in Russia. Images of food, clothing, and interiors should match regional standards. At IT Sectr, we recommend hiring local consultants to verify cultural adaptation.
Localization tools — professional platforms automate the process: Lokalise, Crowdin, POEditor, Smartling, Phrase. They integrate with the repository, automatically import new strings, track changes (Delta updates — only changed strings are translated), provide Translation Memory (TM — storage of previously translated phrases) and Glossary. Average professional translation cost: $0.08–0.15 per word (depending on language).
Process — (1) Developer adds i18n keys to code, pushes to repository. (2) CI/CD (GitHub Actions / GitLab CI) automatically sends new keys to the localization platform. (3) Translators receive notification, translate, and save. (4) Translated files automatically create a PR to the repository. (5) QA checks localization on devices. (6) Release. Cycle for one locale: 2–5 business days (depending on volume). For 10 locales: 5–15 days with parallel translator work.
Machine Translation + Human Review — the modern standard. Neural network translation (DeepL, Google Translate, GPT-4) provides 80–90% quality for popular language pairs. A human translator checks: terminology, context (words can have different meanings on different screens), cultural adaptation. At IT Sectr, we use a hybrid approach: ML translation + native speaker review. For critical strings (legal, payment) — only professional translation. Savings: up to 60% of cost while maintaining quality.
Frequently Asked Questions
Internationalization — preparing code for translation (extracting strings, RTL, formatting). Localization — the actual translation and cultural adaptation. i18n is done by the developer once, l10n — by translators for each language. i18n without l10n — the app is ready for translation but not translated. l10n without i18n — you need to rewrite code for each language.
In Localizable.strings files inside .lproj folders. For each language: en.lproj (English), ru.lproj (Russian), de.lproj (German). Format: “key” = “value”;. For plurals — Localizable.stringsdict. App settings (CFBundleDisplayName) — in InfoPlist.strings. Xcode manages .lproj through Base Internationalization.
values-ru — an Android resource directory for the Russian language. Contains strings.xml with translations. Similarly for other languages: values-de (German), values-fr (French). Android selects resources based on the system language. If values-ru is not found, it uses values/ (base language, usually English).
Always use the Locale API. iOS: DateFormatter.locale = Locale(identifier: locale). Android: DateFormat.getDateInstance(DateFormat.SHORT, locale). Russia: 31.12.2024. USA: 12/31/2024. Japan: 2024/12/31. Never set a fixed format — each country has its own standards. For date input, use UIDatePicker / DatePicker.
For global reach, 10–15 languages are enough: English, Spanish, French, German, Japanese, Chinese, Korean, Portuguese, Russian, Italian, Arabic. For regional — 1–2 languages. Each additional locale increases organic installs by 5–15% in the corresponding region. The App Store requires at least English localization.
Summary
We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.
Read also