Страницы

Поиск по вопросам

Показаны сообщения с ярлыком locale. Показать все сообщения
Показаны сообщения с ярлыком locale. Показать все сообщения

среда, 26 февраля 2020 г.

Как победить искажение текста кирилицы в bash, запущенном в Docker-контейнере?

#docker #кириллица #locale


Настроил локаль для контейнера:

# Set the russian locale
RUN apt-get clean && apt-get update && apt-get install -y locales
RUN locale-gen ru_RU.UTF-8
ENV LANG ru_RU.UTF-8
ENV LANGUAGE ru_RU.UTF-8
ENV LC_ALL ru_RU.UTF-8


При этом русский текст в bash терминале все-равно работает неправильно: ввод начинается
с символа ":�", вставка текста на русском выгляди точно также (начало строки искажается
при вставке). Как бы справиться с этой проблемой?
    


Ответы

Ответ 1



Пример из рабочего Dockerfile, проверено и работает. FROM php:7.2-apache RUN apt-get update && apt-get install -y locales # Locale RUN sed -i -e \ 's/# ru_RU.UTF-8 UTF-8/ru_RU.UTF-8 UTF-8/' /etc/locale.gen \ && locale-gen ENV LANG ru_RU.UTF-8 ENV LANGUAGE ru_RU:ru ENV LC_LANG ru_RU.UTF-8 ENV LC_ALL ru_RU.UTF-8 # +Timezone (если надо на этапе сборки) ENV TZ Europe/Moscow RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

Ответ 2



вероятно, в образе, используемом вами, не сгенерирована такая локаль (ru_RU.UTF-8). посмотрите список командой locale -a (приведён пример вывода): $ docker run --rm -ti имя-образа locale -a C C.UTF-8 POSIX для нормальной работы с кириллицей вполне подойдёт имеющаяся локаль C.UTF-8: $ docker run --rm -ti -e LC_ALL=C.UTF-8 ubuntu:16.04 bash если же необходима именно русскоязычная локаль, то её надо сгенерировать. наиболее, пожалуй, универсальный способ — использовать скрипт locale-gen: $ locale-gen ru_RU.UTF-8 Generating locales (this might take a while)... ru_RU.UTF-8... done Generation complete. скрипт этот присутствует (в debian-основных дистрибутивах) в пакет locales, который в вашем образе, скорее всего, тоже отсутствует, и его надо установить. демо-пример для проверки: $ docker run --rm -ti -e LC_ALL=ru_RU.UTF-8 ubuntu:16.04 bash -c 'apt update && apt install -y locales && locale-gen ru_RU.UTF-8; bash'

вторник, 28 января 2020 г.

Не вызывается деструктор у класса

#cpp #locale


Доброго времени суток. Имеется класс, который изменяет кодировку консоли. Код:

#include "stdafx.h"
#include 
#include 

class edit_locale
{
    int old_cin;
    int old_cout;
public:
   edit_locale(int);
   ~edit_locale();
};

int main()
{
    edit_locale(1251);
    std::cout << "Иван" << std::endl;

   return 0;
}


edit_locale::edit_locale(int cp)
{
   this->old_cin = GetConsoleCP();
   this->old_cout = GetConsoleOutputCP();
   SetConsoleCP(cp);
   SetConsoleOutputCP(cp);
}

edit_locale::~edit_locale()
{
   SetConsoleCP(this->old_cin);
   SetConsoleOutputCP(this->old_cout);
}


Проблема заключается в следующем: функция SetConsole срабатывает только в конструкторе,
в main - функции изменений не происходит. И деструктор не вызывается. С чем это может
быть связано? Спасибо.
    


Ответы

Ответ 1



Проблема в строчке edit_locale(1251); Вы создаёте временный объект, который тут же, в этой же строчке уничтожается. Пишите так: edit_locale l(1251);

Ответ 2



Попробуйте создать объект :) int main() { edit_locale el(1251); std::cout << "Иван" << std::endl; return 0; } Без этого в main() создается (и тут же, до вывода строки) уничтожается временный объект. Чтоб было понятнее - #include class test { public: test() { std::cout << "ctor\n"; } ~test() { std::cout << "dtor\n"; } }; void f() { test(); std::cout << "in f\n"; } void g() { test t; std::cout << "in g\n"; } int main() { std::cout << "call f()\n"; f(); std::cout << "call g()\n"; g(); } Update Можно обойтись и временным объектом - если поступить так: #include #include class edit_locale { int old_cin; int old_cout; public: template edit_locale(int,T f); ~edit_locale(); }; int main() { edit_locale{1251,[](){ std::cout << "Иван" << std::endl; }}; return 0; } template edit_locale::edit_locale(int cp, T f) { this->old_cin = GetConsoleCP(); this->old_cout = GetConsoleOutputCP(); SetConsoleCP(cp); SetConsoleOutputCP(cp); f(); }; edit_locale::~edit_locale() { SetConsoleCP(this->old_cin); SetConsoleOutputCP(this->old_cout); } Кстати, мне всегда хотелось в C++ иметь возможность для всяких lock'ов и иже с ними писать не { lock lk; // что-то делаем } а lock{ // что-то делаем } Так, по-моему, выглядит понятнее. С лямбдами имеем определенный суррогат...

пятница, 27 декабря 2019 г.

Как правильно повернуть календарь?

#java #android #calendar #locale


Я не уверен, что мой подход правильный может есть другая идея?

Мне нужно имплементировать календарь в своем приложении с возможностью Range selection
по датам.

Я для этого решил одну из самых популярных библиотек применить

https://github.com/prolificinteractive/material-calendarview

так как знаю, что Calendar View не приспособлен для Range selection

И все работает отлично пока не нужно поменять язык приложения с Английского на Иврит
(так же как и Арабский слева направо)

Название месяцев меняется название дней недели тоже, но не меняется направление последовательности
(оно тоже должно быть не rtl - cправа налево , а ltr - слева направо)

Вот скрин на англ 



Вот как на иврите android:supportsRtl="false"



И тут тоже на иврите но android:supportsRtl="true" (не знаю почему но кроме того,
что поменялось направление стрелок больше ничего)



Я нашел такой баг фикс как раз об этом 

https://github.com/prolificinteractive/material-calendarview/pull/573

Это как раз то, что мне нужно, согласно этому фиксу направление должно меняться,
но в моем случае видно, что это не так.

Что я делаю не так или подскажите, как можно это решить по другому?
    


Ответы

Ответ 1



Вы можете использовать форк этого репозитория от того кто сделал этот коммит: https://github.com/anasanasanas/material-calendarview Придется использовать JitPack В принципе, все предельно просто описано и на странице: 1 Пропишите: allprojects { repositories { ... maven { url 'https://jitpack.io' } } } 2 Добавьте: dependencies { ... compile 'com.github.anasanasanas:material-calendarview:1.4.4' } Реультат:

пятница, 20 декабря 2019 г.

Android / Использовать plural-правила русского, когда на телефоне установлен другой язык

#android #локализация #locale


В приложении используется только русская локализация. Все строки лежат в values/strings.xml
В том числе вот такой plural:


    Остался %d день
    Осталось %d дня
    Осталось %d дней



Если на телефоне установить, например, английский язык, то правила множественного
числа для русского языка не применяются и используются те, что присущи установленному
языку. Конкретно в данном случае, не работает few, и для 2, 3, 4 подставляется выражение
из many: Осталось 2 дней

Возможно ли принудительно использовать требуемую локаль, для правил множественного
числа? Как, например, это сделано в String.format(Locale l, String format, Object... args)
    


Ответы

Ответ 1



Начиная с Api 17 вы можете получить ресурсы для конкретной локали: @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) public Resources getResourcesByLocale() { Configuration configuration = new Configuration(getResources().getConfiguration()); configuration.setLocale(new Locale("ru")); return createConfigurationContext(configuration).getResources(); } И соответственно потом из этих локализованных ресурсов вытаскивать plurals: for (int i = 1; i < 10; i++) { String daysLeft = getResourcesByLocale().getQuantityString(R.plurals.days_left, i, i); Log.i("Plurals", daysLeft); }

Ответ 2



Попробуйте установить локаль принудительно на русскую на уровне приложения как-то так: public class MyApplication extends Application { @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); newConfig.locale = new Locale("ru"); Locale.setDefault(new Locale("ru")); getBaseContext().getResources().updateConfiguration(newConfig, getBaseContext().getResources().getDisplayMetrics()); } @Override public void onCreate() { super.onCreate(); Locale.setDefault(new Locale("ru")); config.locale = new Locale("ru"); getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics()); } }

суббота, 14 декабря 2019 г.

Принцип локализации на Android

#android #locale


Как правильно локализовать приложение на андроид, чтобы можно было в настройках например
кликнуть на radiobutton или checkbox и устанавливался выбранный язык. Я себе это как
представляю, сделать, либо замещать весь текст в активити текстом другого языка при
выборе, либо создать новые активити с другими языками и уже при выборе другого языка
менять просто активити, либо еще какие-то есть мне не известные способы. Может кто-то
сможет посоветовать рабочий способ.
    


Ответы

Ответ 1



Если необходимо менять язык на лету, делайте следующее. 1) Создаете ресурсы в string.xml Change Language Hello Welcome, потом ресурсы для второго языка, например Французский values-fr/string.xml Changer de langue Bonjour Bienvenue, 2) Создаете класс помощник package devdeeds.com.changelanguage; import android.annotation.TargetApi; import android.content.Context; import android.content.SharedPreferences; import android.content.res.Configuration; import android.content.res.Resources; import android.os.Build; import android.preference.PreferenceManager; import java.util.Locale; public class LocaleHelper { private static final String SELECTED_LANGUAGE = "Locale.Helper.Selected.Language"; public static Context onAttach(Context context) { String lang = getPersistedData(context, Locale.getDefault().getLanguage()); return setLocale(context, lang); } public static Context onAttach(Context context, String defaultLanguage) { String lang = getPersistedData(context, defaultLanguage); return setLocale(context, lang); } public static String getLanguage(Context context) { return getPersistedData(context, Locale.getDefault().getLanguage()); } public static Context setLocale(Context context, String language) { persist(context, language); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { return updateResources(context, language); } return updateResourcesLegacy(context, language); } private static String getPersistedData(Context context, String defaultLanguage) { SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); return preferences.getString(SELECTED_LANGUAGE, defaultLanguage); } private static void persist(Context context, String language) { SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); SharedPreferences.Editor editor = preferences.edit(); editor.putString(SELECTED_LANGUAGE, language); editor.apply(); } @TargetApi(Build.VERSION_CODES.N) private static Context updateResources(Context context, String language) { Locale locale = new Locale(language); Locale.setDefault(locale); Configuration configuration = context.getResources().getConfiguration(); configuration.setLocale(locale); return context.createConfigurationContext(configuration); } @SuppressWarnings("deprecation") private static Context updateResourcesLegacy(Context context, String language) { Locale locale = new Locale(language); Locale.setDefault(locale); Resources resources = context.getResources(); Configuration configuration = resources.getConfiguration(); configuration.locale = locale; resources.updateConfiguration(configuration, resources.getDisplayMetrics()); return context; } } 3) Меняете язык public class MainActivity extends AppCompatActivity { private String mLanguageCode = "fr"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //меняем Английский на Французский по клику на кнопку findViewById(R.id.btnChangeLangView).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //Change Application level locale LocaleHelper.setLocale(MainActivity.this, mLanguageCode); //Пересоздаем Активити с новым языком. recreate(); } }); } } Если надо, можете запомнить выбранный язык в SharedPreference и в onCreate() сетить методом LocaleHelper.setLocale(MainActivity.this, mLanguageCode). первоисточник

воскресенье, 1 декабря 2019 г.

Laravel 5 : русифицировать дату

#laravel #locale


Всем привет,
В laravel 5.5  нужно русифицировать дату и нагуглил способ :

echo '
$a::' . print_r($a, true) . '
'; setlocale(LC_TIME, 'ru'); date_default_timezone_set('CET'); Carbon::setLocale('ru'); echo '
$format::'.print_r($format,true).'
'; $b = $a->format($format); echo '
$b::'.print_r($b,true).'
'; С выводом: $a::Carbon\Carbon Object ( [date] => 2017-11-24 16:32:50.000000 [timezone_type] => 3 [timezone] => CET ) $format::j F, Y g:i A$b::24 November, 2017 4:32 PM То есть русифиция не сработала... также строки setlocale(LC_TIME, 'ru'); date_default_timezone_set('CET'); Carbon::setLocale('ru'); Я вставлял в app/Providers/AppServiceProvider.php: public function boot() { setlocale(LC_TIME, 'ru'); date_default_timezone_set('CET'); Carbon::setLocale('ru'); С тем же результатом. А как правильно? Спасибо!


Ответы

Ответ 1



Если вам нужно локализация даты, которая выводится через метод format, используйте PHP функцию setLocale(): setlocale(LC_TIME, 'ru_RU.UTF-8'); Так же замените метод format на formatLocalized, и так же учтите что метод formatLocalized использует функцию strftime() которая использует другие параметры, так что методы format нужно будет переписать под новые, список параметров найдете в описании функции. Приведу пример того что написал выше: Но есть ещё один метод diffForHumans который выводит дату в следующем виде: Для её локализации необходимо задать локаль в самом Carbon через метод setLocale: Carbon::setLocale('ru'); Лучше вынести этот параметр в конфиг (точнее он там уже есть) и использовать его: Carbon::setLocale(config('app.locale')); Приведу пример: Вот так получается что для разных методов разные подходы, так устроена библиотека Carbon. Устанавливать всё это нужно в момент запуска ядра, для этого нужно добавить это в метод boot сервис провайдера, к примеру AppServiceProvider: public function boot() { setlocale(LC_TIME, 'ru_RU.UTF-8'); Carbon::setLocale(config('app.locale')); }

суббота, 13 июля 2019 г.

Универсальное решение проблем с кириллицей C++

Веду разработку на операционной системе macOS. Возникают кучи проблем с кириллицей (string или char*), например, при работе с функциями regex, ::tolower/::toupper и тд.
При запросе locale в терминале, имею следующее:
LANG="ru_RU.UTF-8" LC_COLLATE="ru_RU.UTF-8" LC_CTYPE="ru_RU.UTF-8" LC_MESSAGES="ru_RU.UTF-8" LC_MONETARY="ru_RU.UTF-8" LC_NUMERIC="ru_RU.UTF-8" LC_TIME="ru_RU.UTF-8" LC_ALL=
Использую C++11. Boost принципиально использовать не хочу и, желательно, чтобы решение могло быть перенесено в будущем на линкус (отсылка к непереносимому codecvt).
Собственно сам вопрос: как можно исправить проблему кириллицы во всей программе? Например, использовать грамотно locale.h (и как это - грамотно?) или что-нибудь еще.
UPD:
Вывод текста я осуществляю непосредственно в консоль. В консоль вывод происходит отлично, вот только преобразования через transform, используя параметры ::tolower, ::toupper успешно игнорируются. Используя codecvt я смог получить из string -> wstring, выполнил ::tolower и смог так же сделать wstring->string, однако, это явный "костыль" и использовать его всегда, когда мне надо что-то сделать с байтами строки - не выход.
Если я вывожу русский текст в ncurses, получается так: (Я какой-то текст) "Я какой-?~Bо ?~Bек?~A?~B"


Ответ

Очень понимаю ваше желание не использовать Boost(тоже такой принцип).
Что бы раз и навсегда забыть о проблемах с кодировкой лучше всего использовать utf8 и в STL есть его реализация wstring
wstring str = u8"кириллический текст";//u8 преобразует ansi символы в utf8.
Используя wstring о проблемах с локалью можно забыть.
Из плюсов это переносимость на всё что угодно, а из минусов это повышенное потребление памяти(не смертельно но всё же).
И, кстати говоря, считается правилом хорошего тона не использовать std::wcout и std::cout (равно как и пару std::wcin и std::cin) в пределах одного приложения(есть проблемы их совместного использования).

пятница, 12 июля 2019 г.

Вопрос про работу с кириллицей (UTF-8) в C++ | Linux

Вводная
Допустим есть файл сохранённый в UTF8. Читать я его могу исключительно std::ifstream (без std::wifstream).
После прочтения файла, я хочу иметь возможность итерироваться по utf-8 символам, и даже сравнивать их
for (size_t i = 0; i < utf8String.size(); i++) { if (utf8String[i] == 'ф') { //... } }
Как мне этого добиться? Вероятно для этого потребуется сконструировать строку, std::wstring, в linux она конструируется из wchar_t, которые занимают 4 байта.
Тогда вопрос в следующем: как сделать конструирование из std::string - которая хранит какой-то utf8 текст - строки std::wstring
Самый первый вариант который приходит в голову: wstring wstr(str.begin(), str.end()); К сожалению не подойдет.
Чтобы понять почему не подойдёт потребуется класс, который показывает битовое содержимое вот он (pastebin)
Если посмотреть на utf8 строку "добро", хранимую в string то например 'д' будет представлено так 11010000 10110100 всё верно.
А вот символ 'д' из наивно сконструированной строки занимает целых 2 элемента wchar_t 11010000 11111111 11111111 11111111 10110100 11111111 11111111 11111111 и вообще не похож на utf-8.
Я могу объяснить почему он стал таким, но не будем (вкратце это от того что wchar_t=char а char<0 для любых широких символов + порядок байт на машине)
Я нашел что string -> wstring можно сделать linux.org.ru Но в моём gcc нет такого хедера как #include
Решил сделать сам конструирование из string в wstring как-то так (pastebin)
Теперь вопрос ко знатокам, я не разу не работал плотно с локалью, поэтому к своему стыду не знаю всех тонкостей, воспринимаю работу с локалью так как описано здесь https://ru.cppreference.com/w/cpp/locale/locale
т.е. просто нужно вставить в код
locale::global(std::locale("") ); wcout.imbue(std::locale());
Понимаю что это даст не более чем какие-то "национальные преобразования" например даты, денежных форматов, дробных форматов. Но именно слова закодированные в utf8 никак не должны затрагиваться манипуляциями с локалями. Верно? Ведь для этого и существует utf8, чтобы однозначно представлять символы разных стран кодом. Код буквы 'Д' внезависимости от любых манипуляций с локакалью (или отсутствием этих манипуляций) есть 1101000010110100 Правильно?
Вроде бы да, но почему-то ручное преобразовние не работает. После работы этой ф-ии букве 'д' будет соответствовать код 11010000 10110100 00000000 00000000 Что вроде бы верно. Но если так сконструированную строку передать на wcout то оно выведет крокозябры и иероглифы.
Сайт https://sites.google.com/site/nathanlexwww/tools/utf8-convert тоже говорит что кодировка буквы 'д' верна.
Тогда нужно посмотреть что из себя представляет std::wstring wstr = L"добро"; Как выяснилось её внутреннее представление вообще не является utf8 (хотя сам исходник сохранен именно в этой кодировке)
символу 'д' там соответствует 00110100 00000100 00000000 00000000
А теперь ряд вопросов 1. Правильно ли я понимаю что никакие манипуляции со стандартными наборами локалей как такие:
locale::global(std::locale("") ); wcout.imbue(std::locale());
Не должны влиять на байтовое/битовое представление велечин которые будут присвоены таким образом
std::wstring = L"добро"
?
Debian 8, gcc - все стандартное, стандартная локаль ru_RU.UTF-8 в системе и консоли, исходный код сохранен в UTF-8. В какой кодировке в памяти программы будет сохранена строка std::wstring = L"добро" ? Есть ли возможность сделать так чтобы std::wstring = L"добро" сохранялась именно в utf8 а не в непонятный формат?
Мне почему-то сейчас думается что в g++ должна быть какая-то опция возможно для чтобы он работал с utf-8, а по дефолту он L"добро" во что-то другое преобразует.
правильно ли я конструирую wchar_t символы для x86-64? Есть ли какие-то легковесные библиотеки, которые, вкомпиляясь статически в проект не сильно его утяжелят, обеспечивают высокоуровневый и простой синтаксис наподобии такого же std::wstring = makeUTF8Str(const std::string&) - и без всяких непонятных манипуляций с актуализацией шаблонов wstring_convert и кучей других приседаний?
весь код по которому я пытаюсь понять utf-8 здесь
Ребят, если желаете помочь ответом то давайте по существу, а не просто ради флейма как сейчас есть один из ответов ниже - который не отвечает ни на однин из поставленных вопросов, но хочет узнать о "выходе за границы стринга" :)


Ответ

Итак, резюмируя ответы на вопросы:
Да, правильно.
Utf-32. Не смотря на то что в моём линуксе дефолтом кодировка utf8 в системе, и исходник сохранён в ней, сам копилятор когда читает такое L”строка” в озу данную строку занесёт к кодировке utf-32. С этим помог разобраться сайт, который показывает все варианты кодировок для конкретного символа https://www.fileformat.info/info/unicode/char/0424/index.htm Такой возможности не нашел, т.е. std::wstring = L"добро" на прямую такого нет чтобы в какой-то свой формат, но т.к. это си++ можно переопределить оператор = - но это лишняя трата времени причем бесполезно, т.к. неявные преобразования не есть хорошо, особенно для тех кто потом будет сопровождать код Правильно, но не нужно, ибо конкретная система работает с utf32 Есть, большое спасибо пользователю ixSci за его ответ, да и за его блог (который я иногда находил через поисковик и читал)
Лично я выбрал эту библиотеку http://utfcpp.sourceforge.net/, она очень проста (как по реализации и размеру, чтобы подключить к проекту в любой ос нужно всего один хедер, а сама библиотека всего в 4 файлах кода) в добавок кросплатформенна.
С этой библиотекой utf8 можно преобразовать так сказать в нативный для бинарника создаваемого моим компилятором вид очень просто:
wstring toUtf8(const string &str) { std::wstring ret; utf8::utf8to32(str.begin(), str.end(), back_inserter(ret)); return ret; }
и иметь возможность корректно перемещаться посимвольно по строке, и сравнивать как буквы так и строки if(mystr == L"g++ широкая строка")

вторник, 26 марта 2019 г.

Не вызывается деструктор у класса

Доброго времени суток. Имеется класс, который изменяет кодировку консоли. Код:
#include "stdafx.h" #include #include
class edit_locale { int old_cin; int old_cout; public: edit_locale(int); ~edit_locale(); };
int main() { edit_locale(1251); std::cout << "Иван" << std::endl;
return 0; }
edit_locale::edit_locale(int cp) { this->old_cin = GetConsoleCP(); this->old_cout = GetConsoleOutputCP(); SetConsoleCP(cp); SetConsoleOutputCP(cp); }
edit_locale::~edit_locale() { SetConsoleCP(this->old_cin); SetConsoleOutputCP(this->old_cout); }
Проблема заключается в следующем: функция SetConsole срабатывает только в конструкторе, в main - функции изменений не происходит. И деструктор не вызывается. С чем это может быть связано? Спасибо.


Ответ

Проблема в строчке
edit_locale(1251);
Вы создаёте временный объект, который тут же, в этой же строчке уничтожается.
Пишите так:
edit_locale l(1251);

среда, 16 января 2019 г.

Принцип локализации на Android

Как правильно локализовать приложение на андроид, чтобы можно было в настройках например кликнуть на radiobutton или checkbox и устанавливался выбранный язык. Я себе это как представляю, сделать, либо замещать весь текст в активити текстом другого языка при выборе, либо создать новые активити с другими языками и уже при выборе другого языка менять просто активити, либо еще какие-то есть мне не известные способы. Может кто-то сможет посоветовать рабочий способ.


Ответ

Если необходимо менять язык на лету, делайте следующее.
1) Создаете ресурсы в string.xml
Change Language Hello Welcome,
потом ресурсы для второго языка, например Французский values-fr/string.xml
Changer de langue Bonjour Bienvenue,
2) Создаете класс помощник
package devdeeds.com.changelanguage;
import android.annotation.TargetApi; import android.content.Context; import android.content.SharedPreferences; import android.content.res.Configuration; import android.content.res.Resources; import android.os.Build; import android.preference.PreferenceManager;
import java.util.Locale;
public class LocaleHelper {
private static final String SELECTED_LANGUAGE = "Locale.Helper.Selected.Language";
public static Context onAttach(Context context) { String lang = getPersistedData(context, Locale.getDefault().getLanguage()); return setLocale(context, lang); }
public static Context onAttach(Context context, String defaultLanguage) { String lang = getPersistedData(context, defaultLanguage); return setLocale(context, lang); }
public static String getLanguage(Context context) { return getPersistedData(context, Locale.getDefault().getLanguage()); }
public static Context setLocale(Context context, String language) { persist(context, language);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { return updateResources(context, language); }
return updateResourcesLegacy(context, language); }
private static String getPersistedData(Context context, String defaultLanguage) { SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); return preferences.getString(SELECTED_LANGUAGE, defaultLanguage); }
private static void persist(Context context, String language) { SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); SharedPreferences.Editor editor = preferences.edit();
editor.putString(SELECTED_LANGUAGE, language); editor.apply(); }
@TargetApi(Build.VERSION_CODES.N) private static Context updateResources(Context context, String language) { Locale locale = new Locale(language); Locale.setDefault(locale);
Configuration configuration = context.getResources().getConfiguration(); configuration.setLocale(locale);
return context.createConfigurationContext(configuration); }
@SuppressWarnings("deprecation") private static Context updateResourcesLegacy(Context context, String language) { Locale locale = new Locale(language); Locale.setDefault(locale);
Resources resources = context.getResources();
Configuration configuration = resources.getConfiguration(); configuration.locale = locale;
resources.updateConfiguration(configuration, resources.getDisplayMetrics());
return context; } }
3) Меняете язык
public class MainActivity extends AppCompatActivity {
private String mLanguageCode = "fr";
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);
//меняем Английский на Французский по клику на кнопку findViewById(R.id.btnChangeLangView).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //Change Application level locale LocaleHelper.setLocale(MainActivity.this, mLanguageCode);
//Пересоздаем Активити с новым языком. recreate(); } }); } }
Если надо, можете запомнить выбранный язык в SharedPreference и в onCreate() сетить методом LocaleHelper.setLocale(MainActivity.this, mLanguageCode).
первоисточник

понедельник, 3 декабря 2018 г.

Как правильно повернуть календарь?

Я не уверен, что мой подход правильный может есть другая идея?
Мне нужно имплементировать календарь в своем приложении с возможностью Range selection по датам.
Я для этого решил одну из самых популярных библиотек применить
https://github.com/prolificinteractive/material-calendarview
так как знаю, что Calendar View не приспособлен для Range selection
И все работает отлично пока не нужно поменять язык приложения с Английского на Иврит (так же как и Арабский слева направо)
Название месяцев меняется название дней недели тоже, но не меняется направление последовательности (оно тоже должно быть не rtl - cправа налево , а ltr - слева направо)
Вот скрин на англ

Вот как на иврите android:supportsRtl="false"

И тут тоже на иврите но android:supportsRtl="true" (не знаю почему но кроме того, что поменялось направление стрелок больше ничего)

Я нашел такой баг фикс как раз об этом
https://github.com/prolificinteractive/material-calendarview/pull/573
Это как раз то, что мне нужно, согласно этому фиксу направление должно меняться, но в моем случае видно, что это не так.
Что я делаю не так или подскажите, как можно это решить по другому?


Ответ

Вы можете использовать форк этого репозитория от того кто сделал этот коммит:
https://github.com/anasanasanas/material-calendarview
Придется использовать JitPack
В принципе, все предельно просто описано и на странице:
1 Пропишите:
allprojects { repositories { ... maven { url 'https://jitpack.io' } } }
2 Добавьте:
dependencies { ... compile 'com.github.anasanasanas:material-calendarview:1.4.4' }
Реультат: