Language support in android

Локализация Android-приложений: о чем умалчивает документация

Локализация Android-приложений — намного более сложная задача, чем должна была бы быть. Описание в документации недостаточное: чтобы разобраться в происходящем «под капотом», нужно искать информацию во внешних источниках (на StackOverflow и в блогах) и тренироваться на базовых приложениях типа «Hello World».

В этой статье я разберу некоторые трудности процесса локализации, с которыми я столкнулся в своих приложениях. Решения, которые я буду приводить, не описаны в документации, поэтому я постараюсь быть максимально точным. (Примечание: термины «локаль» и «язык» в статье используются как синонимы.)

Многобукаф? Нажмите Ctrl-F и введите «вывод №».

Введение

В статье говорится о некоторых трудностях локализации, которые не рассматриваются в официальных ресурсах, — то есть, это не руководство по локализации «для чайников».

Перед чтением полезно будет изучить основы локализации Android-приложений (если вы еще не знакомы с этой темой) — прочтите следующие документы:

Проблема № 1. Приложение отображается не на том языке

Разберемся, что происходит в этом случае «под капотом». Допустим, языковые настройки телефона следующие:

Если перевести этот список в псевдокод, получим:

(Примечание. Язык по умолчанию для приложения определяется самим приложением. В одном случае это может быть польский, в другом — немецкий, и так далее, — это язык, файл которого размещен по пути values/strings.xml . К сожалению, указать системе Android язык по умолчанию для конкретного приложения нельзя — и мы с этой особенностью еще столкнемся позже.)

В основе этого списка лежит вроде бы простая логика. Однако в некоторых случаях приложение использует не тот язык, который должно было бы, и переключается на свою локаль по умолчанию, когда вы этого не ожидаете.

Чтобы увидеть, как это происходит, установите языковые настройки так, как показано на скриншоте выше, а затем создайте в Android Studio новое приложение из шаблона «Empty Activity». Откройте res/values/strings.xml и для строки app_name (название приложения) задайте значение «App In Default Language» («Приложение на языке по умолчанию»).

Запустите приложение и проверьте, чтобы оно работало. Название приложения появится слева вверху экрана.

Теперь добавим еще два файла values.xml :

Приложение можно снова запускать, но перед этим подумайте: какое значение app_name будет отображаться?

Разумно предположить, что это будет название на французском: испанский — предпочитаемый язык пользователя, но для этой локали файла strings.xml нет, поэтому система выберет следующий предпочитаемый язык — то есть, французский, для которого файл strings.xml у нас есть. Верно же?

А теперь запустите приложение:

Какого… Как так? Почему не на французском? У нас проблемы с логикой?

Нет. С нашей логикой всё в порядке. Дело в другом.

При создании проекта в Android Studio с ним идут кое-какие библиотеки по умолчанию. Взгляните на файл app/build.gradle :

В этих библиотеках содержатся файлы ресурсов для многих локалей — в том числе в них могут быть файлы values-es/strings.xml . Поэтому в скомпилированном и упакованном приложении у вас наверняка найдутся файлы strings.xml на испанском.

В итоге Android будет считать, что в приложении есть испанская локаль, и попытается найти app_name на испанском. Но мы эту переменную не определили, поэтому приложение берет ее в strings.xml по умолчанию и, соответственно, отображает строку «App In Default Language».

Читайте также:  Как раздать vpn с андроида

Такая ситуация называется загрязнением ресурсов: Android наступает на свои же грабли. Подробнее — здесь и здесь.

Чтобы обойти эту проблему, нужно объявить поддерживаемые языки в файле app/build.gradle .

Таким образом мы удаляет все ресурсы, за исключением французской и английской локали: это позволяет не только избежать загрязнения ресурсов, но и снизить размер APK-файла.

Измените файл app/build.gradle так, как показано выше, и перезапустите приложение:

Отлично. А если удалить французский язык из списка поддерживаемых?

Работает как ожидалось… за исключением одного случая.

«Один случай»

Давайте кое-что немного поменяем. Приведем список предпочитаемых языков к такому виду:

Теперь удалим папку resources/values-en из проекта и добавим новый файл values-es/strings.xml :

Итак, теперь у нас есть файл по умолчанию strings.xml (по-прежнему со строкой «App In Default Language»), его французская и испанская версии.

Удалим английский из списка поддерживаемых языков и добавим испанский:

Прежде чем запускать приложение, подумайте: на каком языке оно будет отображаться?

Если следовать той же логике, что и раньше, это должен быть испанский.

А теперь запустите приложение:

Черт побери… опять?! Мы же только что всё исправили! Или нет?

Поэкспериментировав несколько часов с таким поведением, я пришел к следующему заключению: где-то в кодовой базе Android предполагается, что ресурсы по умолчанию — на английском языке.

Это, на мой взгляд, неверно, но что уж поделаешь.

Выше я говорил, что resConfig удаляет ресурсы всех локалей, кроме объявленных… но я соврал: ресурсы по умолчанию resConfig НЕ УДАЛЯЕТ.

Итак, что у нас есть? В настройках пользователя английский указан как предпочитаемый язык. В пакете нашего приложения есть кое-какие строковые файлы по умолчанию (ведь они не были удалены), Android считает, что они на английском, и поэтому решает использовать файлы ресурсов по умолчанию.

Вывод № 1. Обязательно объявляйте языки, поддерживаемые в приложении, — с помощью resConfigs .

Вывод № 2. Если нужно, чтобы приложение поддерживало английский язык, файлы ресурсов по умолчанию должны быть на английском: Android рассчитывает на такое положение дел, поэтому так у вас будет меньше головной боли.

(Если вам английский в приложении не нужен, пропустите второй вывод.)

Проблема № 2. Как узнать текущую локаль приложения?

Казалось бы, найти ответ на такой вопрос должно быть легко, но, к сожалению, это не так: погуглив, вы увидите, что на StackOverflow об этом спрашивали, и не раз.

Причем там есть несколько вводящих в заблуждение ответов, например:

О каждом из этих методов я расскажу подробнее. Но прежде проясним кое-что очевидное, что путают советчики на StackOverflow:

Язык устройства != язык приложения

Первое — это язык, выбранный пользователем в настройках устройства. Второе — это язык, который Android решил использовать для конкретного приложения.

Узнать значение для языка устройства легко:

Итак, с языком устройства мы разобрались — перейдем к языку приложения. К сожалению, официального способа узнать локаль приложения во время выполнения, гарантированно не наткнувшись на ошибку, не существует.

Еще раз: не существует официального способа надежным образом узнать язык приложения во время выполнения.

Почему? Рассмотрим два случая:

Случай 1. Android нашел соответствующий файл «strings.xml» и использует его.

Случай 2. Android не нашел соответствующий файл «strings.xml» и использует файл по умолчанию.

В первом случае следующий код всегда будет возвращать правильное значение:

[[[[ НАЧАЛО БОЛЬШОГО ПРИМЕЧАНИЯ. Ребята на StackOverflow предлагают использовать Locale.getDefault() . Чем это отличается от только что описанного способа?

Я рекомендую почитать документацию по классу Locale. Если вкратце, то Locale.getDefault() используется для целей самой JVM: некоторые операции зависят от локали (например, выбор формата дат), и если не указать для них язык, JVM будет использовать значение, получаемое методом Locale.getDefault() .

Но самое главное отличие в том, что Locale.getDefault() определяется во время запуска приложения, и единственный способ изменить это значение — вызвать Locale.setDefault(новаяЛокаль) самостоятельно. Другими словами, если пользователь изменит настройки языка по умолчанию во время работы приложения, то Locale.getDefault() всё равно будет возвращать значение, определенное во время запуска.

А вот метод getResources().getConfiguration().getLocales().get(0) всегда будет давать актуальное значение (если вы его не кешировали, конечно).

Читайте также:  Mafia city для андроида

КОНЕЦ БОЛЬШОГО ПРИМЕЧАНИЯ ]]]]

Ладно. Это был первый случай. А что насчет второго?

К сожалению, для случая 2 получить текущую локаль приложения нельзя. Нет официального способа узнать, какой файл strings.xml используется системой Android: локализованный или по умолчанию. Если применить способ для случая 1, мы просто получим локаль устройства.

Еще раз: если у вас случай 2, то метод getResources().getConfiguration().getLocales.get(0) вернет вам локаль устройства, а не приложения.

Однако для решения этой задачи есть обходной путь: нужно добавить в каждый из файлов strings.xml специальную строку (допустим, это будет current_locale ). В испанской версии strings.xml будет current_locale = ‘es’ , в итальянской — current_locale = ‘it’ , в файле по умолчанию — current_locale = ‘en’ (смотрите второй вывод статьи). Теперь достаточно будет в коде приложения вызвать следующий метод: getString(R.strings.current_locale)

Вывод № 3. Получение текущей локали устройства: Resources.getSystem().getConfiguration().getLocales().get(0) . Если уровень API равен 23 или ниже: Resources.getSystem().getConfiguration().locale .

Вывод № 4. Не существует надежного официального способа получить текущую локаль стандартными методами. Но есть обходной путь — см. чуть выше.

Проблема № 3. Как получить список предпочитаемых языков устройства?

В руководствах по Android сказано, что для этого есть новый API — LocaleList (для Android API с уровня 24). Теоретически, при вызове LocaleList.getDefault() вы должны получить список предпочитаемых языков пользователя, заданный в настройках, и он не должен зависеть от приложения — по крайней мере, так говорится в руководствах…

Я поэкспериментировал с LocaleList.getDefault() и могу сказать, что этот метод не всегда возвращает список предпочитаемых языков точно как в настройках.

В каких случаях бывает несоответствие? Проиллюстрирую на примере: предположим, немецкий НЕ ВЫБРАН как предпочитаемый язык и ваше приложение его тоже не поддерживает. Сделаем так:

Каким-то образом в списке, возвращенном методом LocaleList.getDefault() , оказался немецкий… хотя ни телефон, ни приложение его не поддерживают. Смотрим документацию LocaleList.getDefault() :

«Результат обязательно включает в себя локаль по умолчанию, получаемую из Locale.getDefault(), но не обязательно в верхней части списка. Если локаль по умолчанию не вверху списка, это значит, что система установила в качестве ее одну из других предпочитаемых локалей пользователя, заключив, что основной вариант не поддерживается, но вторичный поддерживается.

Внимание: для API >= 24 список LocaleList по умолчанию изменится, если вызвать Locale.setDefault(). В этом методе это учитывается: проверяется вывод Locale.getDefault() и при необходимости пересчитывается список LocaleList по умолчанию.»

Чего-о-о? Я прочел это трижды и всё равно не понял.

Давайте лучше я сам расскажу, как получить список предпочитаемых локалей на устройстве — и это будет последний вывод статьи.

Вывод № 5. Получение списка предпочитаемых локалей устройства (заданных в настройках): Resources.getSystem().getConfiguration().getLocales() . Это применимо только в API уровня 24 и выше: раньше в качестве предпочитаемого пользователь мог выбрать только один язык.

Заключение

В документации (а также в кодовой базе) Android не учитываются многие варианты использования локализации, и это может быть неприятно, поскольку разработчикам приходится учитывать крайние случаи, и делается это не всегда удобным и логичным образом.

Надеюсь, в этой статье мне удалось объяснить, как Android работает с локализацией, и какой API лучше выбрать для конкретного случая.

О переводчике

Перевод статьи выполнен в Alconost.

Alconost занимается локализацией игр, приложений и сайтов на 70 языков. Переводчики-носители языка, лингвистическое тестирование, облачная платформа с API, непрерывная локализация, менеджеры проектов 24/7, любые форматы строковых ресурсов.

Мы также делаем рекламные и обучающие видеоролики — для сайтов, продающие, имиджевые, рекламные, обучающие, тизеры, эксплейнеры, трейлеры для Google Play и App Store.

Читайте также:  Animus stand alone android

Источник

Android Multiple Language Support Best Practices

Welcome, Buddy… In this tutorial, we demonstrate, How to Build multi-language support apps in the android application. As per android best practice, Application should be kept culture-specific resource. So that resource to be translated to the language based on current locale. In android term, it is called Internationalization and Localization

Localization is play very important role for app reach and user experience (especially GUI). Multi-language support increases your audience reach and provides a better user interface based on locale. Let’s make your Android app more usable and comfortable so more and more audience can use it

How do Internationalization and Localization work in android?

In, Android you can specify resources to the culture of the targeted audience. All content related resource is held in drawable and value folder in Android Project. In this tutorials as will give support of 3 languages Spanish, Hindi (hi_IN)and English(en_US)

Multi Language Supported App in Android (Sample App)

1. Let’s build a sample app in 4 step

1.1 Create a new Project with the following details

In Android Studio, Go to File Menu -> New Project -> Fill some essential details like application name and choose androidx -> Select target SDK -> Select BasicActivity template -> Finish

1.2 Add new resource file strings.xml for the Hindi language

Go to value res folder and right click on go to the value resource file. Select locale from available qualifier clicks the right arrow. Select language and specific region (the region is not mandatory). Check below figure

Similarly, create the file for Spanish and English locale. So you have to create three locale file for Hindi, English, and Spanish languages

Create a string entry for English locale

The same key should be in Hindi locale

Furthermore, have to for Spanish

The complete project hierarchy looks like this figure

3. Now build LocalManager.java utilities.

3.1. Define some specific constant and define all support locale in LocaleDef annotated interface
3.2. Save locale preference in PreferenceManager

Write getter and setter for prefs, It’s setter responsible for persisting data in SharedPreferences and getter are responsible for pulling data from SharedPreferences.

Now set locale and update the resource

Finally, the complete LocaleManager class looks like below

5. Locale Configuration

Few minor configurations have to need in every activity and application class. For that, I’m creating a base class named is BaseActivity. In this activity, I have written methods for activity title and updating the LocaleManager context.

6. Implement Locale Configuration in the Application class

Same things I have to in Application class. Let’s see below code, here we also settings locale on onConfigurationChanged and attachBaseContext.

Above all locale configuration is complete and LocaleManager utilities are ready to use. In conclusion, just call below method for change locale of the application

Implement localization in your android application

Now open the Activity class where you want to change the app language of the app. In application is we mostly written in SettingActivity. But in this android app tutorial we writing in MainActvitiy. Let’s open MainActvitiy and paste below code

Finally, run the project and change your language. You will get the output as shown in the video.

Conclusion

Thank’s for reading, In this tutorial, we have learned implementation Android Multi Language App Example. I hope it’s helpful for you, Help me by sharing this post with all your friends who learning android app development.

Keep in touch

If you have any queries, feel free to connect us.

Источник

Оцените статью