Приложение может вести себя по-разному в Сан-Паулу и в Берлине по причинам, которые никогда не всплывут на код-ревью. Бэкенд угадывает страну по IP-адресу. Телефон форматирует деньги по своей локали. Часы следуют часовому поясу. Play Store показывает каталог и цены страны аккаунта.
Чтобы протестировать мобильное приложение в разных странах, вы управляете каждым из этих сигналов отдельно, а потом проверяете, что делает приложение, когда они расходятся. В этом гайде показано, как задать каждый сигнал на Android, какие проверки форматирования и серверной логики ловят большинство ошибок рынка и как проверить страницы в магазине и цены для страны, в которой вас нет.
Четыре сигнала, которые означают «страну»
| Сигнал | Откуда берётся | Что меняет | Как задать в тесте |
|---|---|---|---|
| Сетевое местоположение | IP-адрес, с которого телефон выходит в сеть | гео-правила бэкенда, фича-флаги, узел CDN, запросы согласия, каталоги контента | телефон, который выходит в сеть из этой страны |
| Локаль устройства | язык системы или язык приложения на 13 и новее | язык, форматы чисел, дат и валют, правила множественного числа, направление текста | Настройки или cmd locale set-app-locales |
| Часовой пояс | настройки даты и времени | метки времени, «сегодня», ежедневные сбросы, запланированные уведомления | Настройки или cmd alarm set-timezone |
| Страна Play | платёжный профиль аккаунта Google | каталог Play Store, доступность приложения, валюта Play Billing | тестовый аккаунт, зарегистрированный в этой стране |
Приложения, которые читают TelephonyManager.getSimCountryIso(), добавляют пятый сигнал — страну SIM-карты. Его проверяйте на физическом телефоне с местной SIM.
Настоящие баги находятся в расхождениях
У реальных пользователей все четыре сигнала совпадают редко. У американского инженера в командировке в Германии телефон в en-US, американский аккаунт Play, немецкий IP-адрес, а после посадки ещё и берлинское время. Бразильская студентка в Лиссабоне читает на pt-BR с португальского адреса. Ошибки живут именно в этих зазорах:
- Бэкенд показывает цены в евро из-за IP, а Play Billing списывает доллары по аккаунту.
- Приложение выбирает язык по IP и игнорирует язык, который выбрал пользователь.
- «Сегодня» считается на сервере в UTC, поэтому ежедневная серия у человека в Сан-Паулу обнуляется в 9 вечера.
- Запрос согласия, привязанный к IP, снова появляется у пользователя, который уже ответил на него дома.
Решите, какой сигнал управляет какой функцией, запишите это и протестируйте хотя бы одну комбинацию с расхождением для каждого рынка.
Подготовьте телефон в нужной стране
Для сетевого сигнала нужен телефон, который действительно выходит в сеть из этой страны. Это могут быть физические телефоны в местном офисе или лаборатории, а может быть облачный телефон, размещённый в стране. В Clousd телефон выходит в сеть из выбранной вами страны, например из США, Великобритании, Германии, Бразилии, Индонезии и ещё 40 стран, с подходящими часовым поясом и языком. Список есть на странице регионов, а для отдельных рынков есть свои страницы, например Бразилия и Германия.
Прежде чем тестировать приложение, убедитесь, что сообщает телефон:
adb shell getprop persist.sys.timezone adb shell date adb shell cmd locale get-app-locales com.example.app
Для сетевой стороны откройте в браузере телефона страницу, которая показывает страну клиента, или смотрите логи своего бэкенда. Проверьте, что ваш провайдер геолокации возвращает для этого адреса, потому что базы данных расходятся, а значение имеет ответ, которым пользуется именно ваш бэкенд.
Проверки локали и форматирования
Большинство «страновых» ошибок — это ошибки форматирования. Пусть работу делает платформа, а вы проверяете, что ей это позволили:
- Валюта. Форматируйте через
NumberFormat.getCurrencyInstance(locale)и никогда не приклеивайте символ к числу вручную. Для 1234.56 локаль pt-BR даётR$ 1.234,56, а de-DE даёт1.234,56 €: символ переезжает, а разделители меняются местами. - Даты и время. Используйте
DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM)и первый день недели из локали. Проверьте и 12-часовой, и 24-часовой формат. - Множественное число. В индонезийском одна форма множественного числа, а в русском и польском их несколько. Используйте
getQuantityString, а не условия на число. - Длина текста. Немецкие строки бывают на 30 % длиннее английских. Ищите обрезанный текст на кнопках, вкладках и в диалогах.
- Справа налево. Арабский и иврит зеркалируют интерфейс. Используйте start и end, а не left и right.
Псевдолокали ловят большую часть этого ещё до появления переводов. Включите их в debug-сборке, а затем при включённых параметрах разработчика выберите English (XA) или Arabic (XB) в настройках языка:
android {
buildTypes {
getByName("debug") {
isPseudoLocalesEnabled = true
}
}
}На Android 13 и новее можно сменить язык одного приложения, не трогая язык системы:
adb shell cmd locale set-app-locales com.example.app --locales pt-BR adb shell cmd locale set-app-locales com.example.app --locales de-DE
Чтобы смена была видна, приложение должно поддерживать язык на уровне приложения через объявление localeConfig или AppCompat. Если нужно проверить часовой пояс, который не совпадает с сетью, как в случае путешественника выше, задайте его напрямую командой adb shell cmd alarm set-timezone America/Sao_Paulo.
Поведение на сервере
Всё, что ваши серверы решают по IP-адресу, нужно проверять из соответствующей страны:
- Фича-флаги и удалённую конфигурацию с таргетингом по стране.
- Варианты оформления заказа и способы оплаты, которые отличаются по рынкам.
- Запросы согласия и приватности: GDPR в ЕС и Великобритании, LGPD в Бразилии, законы штатов о приватности в США.
- Каталоги контента, возрастные рейтинги и юридические уведомления.
- Узел CDN и задержку, которую реально видят ваши пользователи.
В тестовых сборках пишите в лог страну, которую ваш бэкенд определил для каждого запроса. Когда тест падает, первый вопрос — в какой стране, по мнению сервера, находился телефон.
Страницы в магазине и цены в другой стране
Play Store следует за аккаунтом, а не за сетью. У каждого аккаунта Google есть страна Play, которая задаётся платёжным профилем, и пользователь может сменить её только раз в год. Телефон в Германии с американским аккаунтом всё равно видит американский магазин: американскую страницу, доступность и цены. Смена языка телефона меняет язык страницы, но не её страну.
Чтобы проверить, что видят пользователи на конкретном рынке:
- Текст и графика страницы. Собственные страницы в Play Console можно нацелить на отдельные страны, а у основной страницы есть перевод для каждого языка. Посмотрите превью каждой в Play Console.
- Доступность. Страны и регионы, выбранные в Play Console, определяют, где приложение можно установить. Подтвердите это с тестировщиком, чей аккаунт принадлежит этой стране, на внутреннем или закрытом тестовом треке.
- Цены. Play Billing возвращает цену, уже пересчитанную и отформатированную для покупателя, через
getFormattedPrice()в деталях предложения товара. Показывайте эту строку как есть, никогда не цену, которую вы посчитали сами, и проверяйте покупки с тестировщиками лицензий.
Шире о том, как ленты, цены и страницы в магазине меняются по рынкам, рассказывает статья о том, как увидеть свой контент из другой страны.
Чек-лист для каждой страны
- Приложение запускается на языке устройства или приложения, а не на том, который подсказывает IP.
- Цены, числа, даты и время в местных форматах.
- Длинные строки помещаются, а рынки с письмом справа налево правильно зеркалируются.
- Ежедневные сбросы, запланированные уведомления, «сегодня» и «вчера» следуют местному часовому поясу.
- Поведение сервера для страны: флаги, согласие, каталог, варианты оформления заказа.
- Хотя бы одно расхождение: чужая локаль в местной сети или местная локаль с чужим аккаунтом.
- Страница в магазине, доступность и цены Play Billing, проверенные с тестовым аккаунтом из этой страны.
- Скриншоты всех ключевых экранов по каждому рынку, сохранённые вместе с релизом для сравнения.
Прогоните чек-лист и на тех версиях Android, что есть у ваших пользователей; язык на уровне приложения и другие различия релизов разобраны в гайде о тестировании приложения на разных версиях Android.
С каких стран начать
Начните с рынков, которые приносят выручку или вот-вот начнут. Затем добавьте по одному рынку на каждое семейство форматов, которое ещё не покрыто: рынок с десятичной запятой вроде Германии или Бразилии, рынок с письмом справа налево и рынок с нелатинской письменностью. Если вы растёте в Юго-Восточной Азии, Индонезия добавляет большую аудиторию со своим языком и форматами чисел.


