Глобализација: шта је то, 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), сортирање по правилима локале (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 од првог комита. Сваки стринг у коду треба да прође кроз функцију омотач (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. године. Саветоваћемо вас и предложити најбоље решење.

Разговарајте о пројекту

Прочитајте такође