Реализация поддержки RTL-языков (арабский, иврит) в мобильном приложении

TRUETECH занимается разработкой, поддержкой и обслуживанием мобильных приложений iOS, Android, PWA. Имеем большой опыт и экспертизу для публикации мобильных приложений в популярные маркеты Google Play, App Store, Amazon, AppGallery и другие.
Разработка и поддержка любых видов мобильных приложений:
Информационные и развлекательные мобильные приложения
Новостные приложения, игры, справочники, онлайн-каталоги, погодные, фитнес и здоровье, туристические, образовательные, социальные сети и мессенджеры, квиз, блоги и подкасты, форумы, агрегаторы
Мобильные приложения электронной коммерции
Интернет-магазины, B2B-приложения, маркетплейсы, онлайн-обменники, кэшбэк-сервисы, биржи, дропшиппинг-платформы, программы лояльности, доставка еды и товаров, платежные системы
Мобильные приложения для управления бизнес-процессами
CRM-системы, ERP-системы, управление проектами, инструменты для команды продаж, учет финансов, управление производством, логистика и доставка, управление персоналом, системы мониторинга данных
Мобильные приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, платформы предоставления электронных услуг, платформы кешбека, видеохостинги, тематические порталы, платформы онлайн-бронирования и записи, платформы онлайн-торговли

Это лишь некоторые из типы мобильных приложений, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента.

Предлагаемые услуги
Показано 1 из 1 услугВсе 1735 услуг
Реализация поддержки RTL-языков (арабский, иврит) в мобильном приложении
Сложная
~3-5 рабочих дней
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_mobile-applications_feedme_467_0.webp
    Разработка мобильного приложения для компании FEEDME
    756
  • image_mobile-applications_xoomer_471_0.webp
    Разработка мобильного приложения для компании XOOMER
    624
  • image_mobile-applications_rhl_428_0.webp
    Разработка мобильного приложения для компании RHL
    1054
  • image_mobile-applications_zippy_411_0.webp
    Разработка мобильного приложения для компании ZIPPY
    947
  • image_mobile-applications_affhome_429_0.webp
    Разработка мобильного приложения для компании Affhome
    862
  • image_mobile-applications_flavors_409_0.webp
    Разработка мобильного приложения для компании FLAVORS
    445

Реализация поддержки RTL-языков (арабский, иврит) в мобильном приложении

Добавить арабский или иврит к уже работающему приложению — это не «поменять locale и выставить layoutDirection = rtl». Типичная картина после такой попытки: иконки «назад» смотрят вправо, но стрелка прогресс-бара так и идёт слева направо; текст в TextField выровнен правильно, но placeholder по-прежнему слева; анимации slide-in «приезжают» с неправильной стороны, а кастомный Canvas рисует графики зеркально только в режиме отладки на эмуляторе — на реальном устройстве нет.

Где реально ломается RTL

iOS — Auto Layout и SwiftUI

В UIKit поведение определяется semanticContentAttribute у UIView. По умолчанию .unspecified — система сама решает по locale. Проблема начинается с кастомных view: UIView.draw(_:), CALayer, Core Graphics — всё это игнорирует semanticContentAttribute и рисует в абсолютных координатах. Нужно явно применять CGAffineTransform(scaleX: -1, y: 1) или переписывать логику под userInterfaceLayoutDirection.

В SwiftUI HStack и padding(.leading) автоматически зеркалятся при layoutDirection == .rightToLeft. Но alignment: .leading в тексте при RTL — это уже правый край. Если вы явно указываете .trailing, всё переворачивается. Кастомные Shape через Path рисуются в абсолютных координатах — зеркалить придётся вручную через .environment(\.layoutDirection, .rightToLeft) в сочетании с transform.

Иконки из SF Symbols: часть из них имеет RTL-вариант (например, arrow.right → автоматически arrow.left при RTL). Но логотипы и брендовые иконки зеркалить нельзя — для них .semanticContentAttribute = .forceLeftToRight.

Android — LayoutDirection и Drawable

android:supportsRtl="true" в манифесте — обязательно, но недостаточно. start/end вместо left/right в XML-атрибутах (paddingStart, layout_marginEnd) — Lint поймает не всё, особенно в программно создаваемых LayoutParams.

VectorDrawable с autoMirrored="true" — правильный способ зеркалить иконки. Но BitmapDrawable и PNG из mipmap не зеркалятся автоматически. Нужно либо rotationY = 180f через код, либо отдельный ресурс в drawable-ldrtl-*.

В Jetpack Compose Modifier.padding(start = 16.dp) корректно зеркалится при RTL, а Modifier.offset(x = 16.dp) — нет. Разница неочевидна, пока не запустишь на арабской локали. Alignment.Start и Alignment.End работают правильно; Alignment.Left — нет.

Анимации. SlideInHorizontally в Compose принимает лямбду initialOffsetX: для LTR это -fullWidth, для RTL — +fullWidth. Без проверки LocalLayoutDirection.current анимация едет с неправильной стороны.

Как мы это реализуем

Аудит начинается с запуска приложения на арабской локали через adb shell setprop persist.sys.locale ar-AE (Android) и Settings → General → Language & Region (iOS Simulator) — это выявляет 80% проблем ещё до правок.

На iOS работаем с UIView.appearance(whenContainedInInstancesOf:) для системного наследования semanticContentAttribute, переписываем кастомные draw() под conditional flipping, проверяем все NSTextAlignment.natural vs .left в старых XIB-файлах (.natural зеркалится, .left — нет).

На Android проводим lint-аудит на hardcoded-left/right атрибуты, заменяем LayoutParams programmatically через MarginLayoutParamsCompat.setMarginStart/End, добавляем autoMirrored к векторным иконкам направления.

Flutter требует отдельного внимания: TextDirection.rtl прокидывается через Directionality widget. Но CustomPainter рисует в абсолютных координатах Canvas — зеркалирование через canvas.scale(-1, 1) с canvas.translate(-size.width, 0). Row с textDirection: TextDirection.rtl и стандартные виджеты Material работают корректно; проблемы — в кастомных компонентах и анимациях через AnimationController с hardcoded offset.

React NativeI18nManager.isRTL для условной логики, flexDirection: 'row' зеркалится при RTL автоматически на iOS, на Android — только с React Native 0.63+. Для старых версий нужен I18nManager.forceRTL(true) с перезапуском приложения.

Типичные ошибки, которые пропускают в ревью

  • Жёстко заданный textAlign: 'left' в кастомных компонентах вместо 'auto' или 'start'
  • transform: [{scaleX: -1}] применён к иконке без проверки I18nManager.isRTL — иконка зеркалится всегда
  • Числа в арабском тексте: ١٢٣ (eastern arabic numerals) vs 123 — зависит от контекста отображения, нужно явно задавать NSLocale / Locale
  • Бидиректциональный текст (арабский + английское название): NSAttributedString с явным NSWritingDirectionAttributeName иначе порядок слов ломается

Этапы работы

  1. Аудит — запуск на арабской/ивритской локали, скриншоты всех экранов, составление списка артефактов
  2. Классификация — layout issues, icon mirroring, text alignment, animation direction
  3. Правки — итеративно по компонентам, начиная с навигации и основных экранов
  4. Тестирование — на реальных устройствах (Samsung с One UI меняет поведение части компонентов относительно AOSP)
  5. RTL-скриншот-тесты — добавляем в CI, чтобы регрессии ловились автоматически

Полный RTL-аудит и реализация для приложения среднего масштаба: 3-5 дней. Стоимость зависит от количества экранов и платформ.