Глобализация: какво е, i18n и многоезичност в приложенията

Автор: IT Sectr Публикувано: 2026-02-26 Време за четене: 8 мин

Глобализация (глобализация, също интернационализация, i18n) — процес на подготовка на мобилно приложение за работа с няколко езика и регионални формати без промяна на изходния код. Включва изнасяне на текстови ресурси от кода, поддръжка на различни формати за дати, числа и валути, отчитане на посоката на текста (LTR/RTL) и адаптиране на оформлението за различни езици. В iOS се използват NSLocalizedString и Localizable.strings, в Android — strings.xml в директории values-{lang}. Повече в документацията на Apple за интернационализация.

Основни

  • Глобализация (i18n) — подготовка на кода на приложението за няколко езика и региона
  • NSLocalizedString — Swift макрос за извличане на преведени низове от Localizable.strings
  • strings.xml — XML файл на Android, където се съхраняват текстови ресурси за всеки език
  • RTL — поддръжка на езици с писмо отдясно наляво (арабски, иврит, урду)
  • Формати — датите, числата и валутите трябва да се форматират чрез Locale-зависими API

Какво е глобализация (i18n) и защо е необходима?

Глобализация (съкратено i18n — 18 букви между «i» и «n») — архитектурна подготовка на приложението за работа с произволен език и регион. Ключовото правило на i18n: нито един текстов низ не трябва да бъде твърдо кодиран (hardcoded) в изходния код. Вместо това низовете се изнасят в ресурсни файлове, а кодът осъществява достъп до тях чрез ключове. При добавяне на нов език е достатъчно да се добави файл с превод — кодът остава непроменен. Това отличава i18n от локализацията (l10n), където се превеждат самите низове.

Бизнес аргумент — глобализацията увеличава пазара. Според Common Sense Advisory (2023) повече от 70% от потребителите предпочитат да пазаруват в приложения на родния си език. Локализацията на 10 езика увеличава потенциалната аудитория с 80%. Без i18n всяко разширяване към нов език изисква промени в кода, което забавя навлизането на пазара и увеличава разходите 5–10 пъти. Правилната i18n архитектура позволява поддръжка на 40+ езика с минимални разходи.

Компоненти на i18n включват: изнасяне на низове (String externalization), множествени форми (pluralization за 1/2/5+), форматиране на дати и числа (DateFormatter/SimpleDateFormat), поддръжка на RTL езици (Right-to-Left), сортиране по правилата на locale (Collator), регионални символи (разделители на хиляди, десетични знаци). В IT Sectr вграждаме i18n на етапа на архитектурата, а не добавяме по-късно — това спестява до 60% време при последваща локализация.

Интернационализация в iOS: NSLocalizedString и XLIFF

NSLocalizedString — основният Swift макрос за работа с преводи. Формат: NSLocalizedString(«key», comment: «описание за преводача»). Макросът автоматично замества низа от Localizable.strings за текущата локала на устройството (NSLocale.preferredLanguages). Ако преводът за ключ не бъде намерен, се връща самият ключ или стойността в development language (обикновено en). Apple препоръчва използването на смислени ключове, а не английски низове като ключове.

swift
// Localizable.strings (en)
// "welcome_title" = "Добре дошли!";
// Localizable.strings (ru)
// "welcome_title" = "Добре дошли!";

// Swift код — единен за всички езици
titleLabel.text = NSLocalizedString(
    "welcome_title",
    comment: "Заглавие на екрана за добре дошли"
)

// Множествени форми чрез Localizable.stringsdict
// 
// <dict>
//     <key>items_count</key>
//     <dict>
//         <key>NSStringLocalizedFormatKey</key>
//         <string>%#@items@</string>
//         <key>items</key>
//         <dict>
//             <key>one</key>
//             <string>%d продукт</string>
//             <key>few</key>
//             <string>%d продукта</string>
//             <key>many</key>
//             <string>%d продукта</string>
//         </dict>
//     </dict>
// </dict>

// Използване на множествени форми
let items = 5
let label = String.localizedStringWithFormat(
    NSLocalizedString("items_count", comment: ""), items
)

XLIFF — формат за обмен на преводи между разработчици и преводачи. Xcode експортира XLIFF файл (Editor → Export for Localization), който съдържа всички низове за превод. Преводачът работи с XLIFF в CAT инструменти (Trados, memoQ, Smartcat). След превод XLIFF се импортира обратно в Xcode (Editor → Import Localizations). XLIFF автоматично актуализира всички .lproj директории. Това е стандартният работен процес за локализация на iOS приложения в продукция.

SwiftUI и i18n

SwiftUI работи с NSLocalizedString чрез инициализатора Text. Текстът в SwiftUI е автоматично интернационализиран: Text(«welcome_title») търси превод в Localizable.strings точно както NSLocalizedString. За множествени форми използвайте Text(«%d items», count: items). SwiftUI поддържа форматиране на дати чрез Text(date, style: .date) — автоматично използва Locale.current. Apple препоръчва SwiftUI за нови проекти, тъй като интернационализацията в него е по-прозрачна.

Интернационализация в Android: strings.xml и RTL

Android i18n се основава на ресурсната система. Низовете се изнасят в res/values/strings.xml за езика по подразбиране (обикновено английски). За всеки език се създава отделна директория: res/values-ru/strings.xml (руски), res/values-de/strings.xml (немски), res/values-fr/strings.xml (френски). Android автоматично избира низове въз основа на системния език на устройството (Locale.getDefault()). Ако няма точна локала, се използва базовата версия (values/strings.xml).

kotlin
// res/values/strings.xml (английски, по подразбиране)
<resources>
    <string name="welcome_title">Welcome!</string>
    <string name="items_count">%d item(s)</string>
</resources>

// res/values-ru/strings.xml (руски)
<resources>
    <string name="welcome_title">Добре дошли!</string>
    <plurals name="items_count">
        <item quantity="one">%d продукт</item>
        <item quantity="few">%d продукта</item>
        <item quantity="many">%d продукта</item>
    </plurals>
</resources>

// Kotlin код
textView.text = getString(R.string.welcome_title)

// Множествени форми
val items = 5
textView.text = resources.getQuantityString(
    R.plurals.items_count, items, items
)

// RTL поддръжка в кода
textView.textDirection = View.TEXT_DIRECTION_LOCALE
// Manifest: supportsRtl="true"

RTL (Right-to-Left) — поддръжка на езици, при които текстът се чете отдясно наляво (арабски, иврит, урду, персийски). Android поддържа RTL чрез атрибутите android:layoutDirection и android:textDirection. В манифеста задайте android:supportsRtl="true" — и Android автоматично отразява оформлението. NavDrawer, иконите за назад/напред, подравняването на текста трябва да работят и в двете посоки. В кода използвайте View.LAYOUT_DIRECTION_LOCALE и Gravity.START/END вместо LEFT/RIGHT.

Локализирани ресурси

Android Resource Qualifiers позволяват локализация не само на низове, но и на изображения (res/drawable-ru/), оформления (res/layout-ru/), анимации, цветове. За арабски и иврит са необходими отделни оформления с огледално разположение на елементите — използвайте res/layout-ar/ (арабски). Android също поддържа регионални варианти: values-rUS, values-rGB, values-de-DE. Qualifiers се комбинират: values-ldrtl-ru — руски за RTL дисплеи.

Регионални формати: дати, числа, валути в iOS и Android

Дата и час — един от ключовите аспекти на i18n. Различните региони използват различни формати: Русия — ДД.ММ.ГГГГ, САЩ — ММ/ДД/ГГГГ, Япония — ГГГГ.ММ.ДД. Използването на фиксиран формат (yyyy-MM-dd) за показване на потребителя е грешка. В iOS използвайте DateFormatter с Locale(identifier: locale), в Android — DateFormat.getDateInstance(DateFormat.SHORT, locale). За гласови асистенти и AI търсене датите трябва да бъдат в ISO 8601 във вътрешно представяне.

Числа и валути — в различните региони различни разделители: 1,234.56 (САЩ) vs 1.234,56 (Русия), 1 234,56 (Франция). iOS: NumberFormatter с .locale = locale. Android: DecimalFormat с DecimalFormatSymbols(locale). За валути: формат ¥1,234 (Япония) vs $1,234.56 (САЩ) vs 1 234,56 ₽ (Русия). Никога не конкатенирайте валута и число ръчно — използвайте NumberFormatter.currencyCode и .currencySymbol.

РегионДатаЧислоВалута
Русия31.12.20241 234,561 234,56 ₽
САЩ12/31/20241,234.56$1,234.56
Германия31.12.20241.234,561.234,56 €
Япония2024/12/311,234¥1,234
Саудитска Арабия31/12/20241,234.561,234.56 SAR

Сортиране (Collation) — азбучното сортиране се различава в различните езици. В испански «ch» идва след «c». В шведски «ä» е в края на азбуката. В немски «ß» се сортира като «ss». iOS: LocalizedComparison (String.localizedCompare). Android: Collator.getInstance(locale). Никога не използвайте compareTo() за низове, показвани на потребителя — той използва Unicode Code Point order, който не отчита регионални правила.

Най-добри практики за интернационализация на мобилни приложения

Архитектурни принципи — започнете i18n от първия commit. Всеки низ в кода трябва да премине през обвиваща функция (tr("key")), която не съществува до настройването на i18n — това ще принуди разработчика веднага да изнесе низовете. Не използвайте английски низове като ключове — при промяна на формулировката на английски ще трябва да актуализирате всички преводи. Използвайте смислени ключове: «profile.title», «settings.language.label».

Псевдолокализация — техника за тестване на i18n преди реалния превод. Заменете всяка латинска буква с диакритични символи (á, é, ñ, ü) за проверка на кодирането, добавете префикс [XXX] за проверка на отрязването на низове. Xcode: схеми за стартиране — псевдоезик «Double-Length Pseudolanguage». Android: Developer Options — Force RTL layout direction, System font scale до 200%. Псевдолокализацията открива 80% от проблемите с i18n без участие на преводач.

IT Sectr контролен списък за i18n — преди пускане проверяваме: (1) няма hardcoded низове в кода (изключение: логове), (2) множествените форми работят коректно за всички езици, (3) датите/числата се форматират чрез Locale API, (4) оформлението се показва правилно на RTL езици, (5) низовете не се отрязват при максимално мащабиране, (6) псевдолокализацията не е открила грешки, (7) всички езици, обявени в магазините, имат пълен набор от преводи.

Често задавани въпроси

По какво i18n се различава от l10n?

i18n (интернационализация) — подготовка на кода: изнасяне на низове, поддръжка на RTL, форматиране. Прави се от разработчика веднъж. l10n (локализация) — превеждане на низове на конкретен език. Прави се от преводача многократно за всяка локализация. i18n — архитектура, l10n — съдържание. Без i18n локализацията по принцип е невъзможна.

Как работи NSLocalizedString в Swift?

NSLocalizedString — макрос, който търси стойност по ключ в Localizable.strings за текущата локала на устройството. Ако преводът бъде намерен — връща го. Ако не — връща ключа. Формат: NSLocalizedString(«key», comment: «описание»). За форматиране с параметри използвайте String.localizedStringWithFormat().

Как са организирани strings.xml в Android?

strings.xml — файл с преводи в директория res/values/{lang}/. Базова версия в values/strings.xml, преводи — в values-ru/strings.xml. Кодът осъществява достъп чрез getString(R.string.key). Android сам избира необходимия файл на база системния език. За множествени форми се използва ресурс <plurals> с уточнения zero/one/few/many/other.

Какво е RTL в контекста на i18n?

RTL (Right-to-Left) — посока на писане за арабски, иврит, урду, персийски. Android: supportsRtl="true" в манифеста, android:layoutDirection, Gravity.START/END. iOS: UISemanticContentAttribute.forceLeftToRight за принудителен RTL. Оформлението трябва да се отразява огледално: меню отдясно, текст — отдясно наляво, икони за навигация — обърнати.

Кои езици са задължителни за публикуване?

За глобално публикуване минимален набор: английски, испански, френски, немски, японски, китайски, корейски, португалски, руски, италиански. App Store изисква поне английска локализация. Всяка допълнителна локализация увеличава потенциалната аудитория. За локалния пазар са достатъчни 1–2 езика.

Резюме

  • Глобализация (i18n) — архитектурна подготовка на приложението за множество езици и региони
  • NSLocalizedString — Swift макрос за превеждане на низове чрез Localizable.strings + XLIFF експорт
  • strings.xml — Android ресурс с преводи в директории values-{lang}
  • RTL — задължителна поддръжка за арабски, иврит, урду и персийски
  • Формати — датите и числата се форматират стриктно чрез Locale API, не ръчно
  • Множествени форми — iOS: stringsdict, Android: <plurals> с шест количествени форми
  • Псевдолокализация — техника за тестване на i18n преди превод (открива 80% от проблемите)

Ще разработим мобилно приложение под ключ

IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.

Обсъдете проекта

Прочетете също