Страницы

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

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

воскресенье, 15 марта 2020 г.

Мультиязычное приложение на C [закрыт]

#c #локализация #интернационализация


        
             
                
                    
                        
                            Закрыт. Этот вопрос не по теме. Ответы на него в данный
момент не принимаются.
                            
                        
                    
                
                            
                                
                
                        
                            
                        
                    
                        
                            Хотите улучшить этот вопрос? Переформулируйте вопрос,
чтобы он соответствовал тематике «Stack Overflow на русском».
                        
                        Закрыт 4 года назад.
                                                                                
           
                
        
Подскажите, как в C обычно делают мультиязичность?
    


Ответы

Ответ 1



например, с помощью gnu/gettext (там присутствует ссылка на подробнейшую англо-язычную документацию). есть статья в русскоязычной википедии, в которой приведён небольшой пример. там же, к примеру, упоминается и краткое русско-язычное руководство.

Ответ 2



в linux обычно используют gettext с C/C++. Если Qt, там свой инструментарий.

пятница, 13 марта 2020 г.

Rails - yml файл для всех языков

#ruby_on_rails #локализация #yml


Я переводил свое Rails-приложение и столкнулся со следуюшей проблемой. Не все элементы
надо переводить. Например, в en.yml у меня хранятся не только фразы, но и ссылки. Переводить
их не имеет смысла, но если их не включасть, например, в ru.yml, то будет ошибка translation_missing. 

@MichaelRadionov посоветовал использовать наследование. 

Соответственно, вопрос: Как использовать наследование в YML файлах
    


Ответы

Ответ 1



Использовать наследование не нужно. Эта функция уже включена в гем rails-i18n. Для того что-бы все работало, нужно отредактировать файл application.rb: # Автозагрузка всех языковых файлов config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] # Дефолтовый язык config.i18n.default_locale = :ru # Возврат к английскому при ошибках config.i18n.fallbacks = [:en] # Так же можно указывать какой язык использовать при ошибках config.i18n.fallbacks = {'ru' => 'en'}

понедельник, 9 марта 2020 г.

Способы мультиязычности программ на Python?

#python #python_2x #локализация


При разработке приложения с поддержкой нескольких языковых локализаций, я использую
файл, в котором храню все строковые данные программы. Раньше я обходился простым -

exec(open("файл/языковой/локолизации").read())


инициализируя таким образом все переменные со строковыми значениями в основной код
приложения.

Сейчас exec как-то не хочется использовать. Я приспособил для этих целей модуль ConfigParser.
Сейчас это выглядит вот так:

from ConfigParser import ConfigParser


config = ConfigParser()
config.read("locale.ini")
language = config.get("LOCALE", "language")  # устанавливаем локаль
section = language.upper()
config.read("{}.ini".format(language))  # читаем файл строковых данных

# Таким образом я получаю строковые значения для приложеничя.
program_title = config.get(section, "program_title")


locale.ini
(файл текущей локализации приложения):

[LOCALE]
language = english


english.ini
(файл со строковыми данными):

[ENGLISH]
program_title = Clean Master


Теперь, скажем, если мне нужно сменить язык на русский, я добавляю файл russian.ini
со строками русской локализации, а в файле locale.ini устанавливаю значение "language"
в "russian".

Получается следующее:

locale.ini 
(файл текущей локализации приложения):

[LOCALE]
language = russian


english.ini 
(файл со строковыми данными):

[RUSSIAN]
program_title = Мастер Очистки


Может быть в Python есть другие варианты вышеописанного велосипеда?
    


Ответы

Ответ 1



Вообще, есть довольно стандартный вариант - использовать библиотеку gettext, для которой есть биндинги в том числе и для Python (причем, в стандартной библиотеке, не исключено, что это реализация gettext на Python). Принцип работы примерно такой: все строки, подлежащие переводу оборачиваются в вызов специальной функции _(). Далее, программа обрабатывается утилитой pygettext, вытаскивающей все переводимые строки, в результате получается файл .pot (шаблон перевода), в который в дальнейшем можно добавить перевод. Это текстовый файл с относительно простой внутренней структурой, его можно редактировать чем-то блокнотоподобным, но есть и специализированные утилиты, например, poedit, также его можно загрузить на какой-нибудь из сервисов онлайн-перевода типа crowdin.com или transifex.com, и редактировать там совместно с другими переводчиками. Из файла .pot получается файл .po (по сути тот же .pot, но с заполненным переводом строк на нужный язык), который потом компилируется в файл .mo (бинарный файл, хотя тоже с довольно простой внутренней структурой) с помощью утилиты msgfmt из пакета gettext или утилиты msgfmt.py из пакета Python. Далее, перевод импортируется в переводимую программу при помощи команды gettext.install('mary', './locale', unicode=True) (пример отсюда, реальные параметры могут быть другими). Парочка нагугленных руководств: Международные ягнята / Хабрахабр Локализация Python-скриптов при помощи gettext Если потребуется редактировать перевод онлайн совместно с другими переводчиками, могу сказать, что упомянутые выше crowdin и transifex бесплатны для Opensource продуктов, но в crowdin с этим довольно строго, в то время как в transifex достаточно того, чтобы перевод был доступен публично, и в настройках проекта была ссылка на исходный код. При этом субъективно у crowdin более дружелюбный интерфейс.

суббота, 7 марта 2020 г.

Не отображается язык

#java #android #локализация #локаль


Проблема следующая. На одних устройствах язык (Телугу) отображается (планшет Prestigio,
samsung 6,  в том числе на эмуляторах Genymotion), на другом устройстве нет (Alcatel
One Touch, android 4.2.2). Причем в последнем устройстве длина невидимого текста определяется,
текст место занимает, в лог (Android Studio) выводится. 

Вывожу поддерживаемые устройством языки следующим образом - 

for (Locale locale : Locale.getAvailableLocales()) {
        Log.i("LOCALE", locale.getLanguage() + "_" + locale.getCountry() + " [" +
locale.getDisplayName() + "]");
    }


Отстуствие языка "te" (Telugu) в этом списке не мешает отображению на экране, кроме
Alcatel.

Как я понимаю проблема может всплыть не только в Alcatel-моделях, хотелось бы разобраться
в причинах. В какую сторону глядеть, на что обратить внимание, что еще добавить к вопросу
для ясности?

Интересно,можно ли программно определить, что шрифт не отображается, но длину/размер
строки в представлении имеет?
    


Ответы

Ответ 1



Вероятно, стандартный шрифт Алкателей не содержит нужных символов. Попробуйте включить в ваше приложение шрифт, который точно будет работать, и устанавливать его для отдельных представлений someTextView.setTypeface(Typeface.createFromAsset(getAssets(), "fonts/myfont.ttf")); или для всего макета public class FontChangeCrawler { private Typeface typeface; public FontChangeCrawler(Typeface typeface) { this.typeface = typeface; } public FontChangeCrawler(AssetManager assets, String assetsFontFileName) { typeface = Typeface.createFromAsset(assets, assetsFontFileName); } public void replaceFonts(ViewGroup viewTree) { View child; for (int i = 0; i < viewTree.getChildCount(); ++i) { child = viewTree.getChildAt(i); if (child instanceof ViewGroup) { replaceFonts((ViewGroup)child); } else if (child instanceof TextView) { ((TextView) child).setTypeface(typeface); } } } } public class MainActivity extends AppCompatActivity { @Override public void setContentView(View view) { super.setContentView(view); FontChangeCrawler fontChanger = new FontChangeCrawler(getAssets(), "fonts/myfont.otf"); fontChanger.replaceFonts((ViewGroup)this.findViewById(android.R.id.content)); } }

вторник, 25 февраля 2020 г.

Локализация -Как русифицировать страницы MAN в Linux mint?

#локализация #linux_mint #man


Как русифицировать страницы MAN  в Linux mint?
    


Ответы

Ответ 1



надеюсь, я правильно понял вопрос, что интересует отображение уже готовых, а не написание новых man-страниц. man-страницы обычно входят в пакеты с программами. например, в пакет gnupg входят такие файлы с man-страницами: $ dpkg -L gnupg | grep 'man.*gz' /usr/share/man/man1/gpg.1.gz /usr/share/man/man1/lspgpot.1.gz /usr/share/man/man1/gpg-zip.1.gz /usr/share/man/man1/gpgsplit.1.gz /usr/share/man/ru/man1/gpg.1.gz /usr/share/man/man7/gnupg.7.gz если есть соответствующий файл в каталогах /usr/share/man/ru/*/ (ru — это и есть «на русском»), то и man-страницу «по-русски» можно посмотреть. согласно man man (man-страница о самой программе man), по умолчанию на выбор языка влияет значение переменных окружения LANG, LC_MESSAGES и других, имеющих отношение к локали. (насколько мне известно, список, в порядке приоритета от большего к меньшему — LC_ALL, LANG, LC_MESSAGES, LANGUAGE). собственно, если у вас правильно настроены эти переменные для отображения русского языка в интерфейсе (посмотреть их все «разом» можно командой locale), то и man-страницы будут отображаться (при наличии) — русскоязычные. если по каким-то причинам вам не нужна перенастройка локали (или, хотя бы, переопределение какой-нибудь из перечисленных переменных), то вы можете вызвать программу man с опцией -L язык. например: $ man -L ru man на всякий случай приведу и примеры с переназначением переменных: $ LC_ALL=ru_RU.UTF-8 man man $ LANG=ru_RU.UTF-8 man man $ LC_MESSAGES=ru_RU.UTF-8 man man $ LANGUAGE=ru man man для LANGUAGE имеет смысл указывать именно так — только язык (ru), без территории (RU) и набора символов (UTF-8).

понедельник, 24 февраля 2020 г.

Как сделать программу мультиязычной?

#c_sharp #winforms #локализация #интернационализация


В программе буквально 10-20 строк которые нужно переводить? Каким образом сделать?
    


Ответы

Ответ 1



Вы можете посмотреть на msdn пошаговую инструкцию которая объясняет, как это сделать. Если коротко, то вам нужно воспользоваться менеджером ресурсов: ResourceManager LocRM = new ResourceManager("WindowsApplication1.WinFormStrings",typeof(Form1).Assembly); // вызов нужной локализации строки: MessageBox.Show(LocRM.GetString("strMessage")); ResourceManager документация

пятница, 24 января 2020 г.

Как вставить ресурсы локализации в исполняемую сборку?

#c_sharp #winforms #локализация #ресурсы


Привет, народ! Делаю приложение на windows forms (.NET Framework 4.6). Понадобилось
сделать локализацию. Сделал как указано здесь. После компиляции появляются папки с
наименованиями языков ("ru" и "en"), в которых лежат файлы <ИмяПроекта>.resources.dll.
Но мне нужно, чтобы все было в одном исполняемом файле. Если их нет, то язык присутствует
только системный. AssemblyResolve не вызывается, поэтому добавить их в ресурсы и подгружать
когда надо не получится. Есть ли какой-нибудь способ решить этот вопрос или проще сделать
свою локализацию?
    


Ответы

Ответ 1



После более внимательного изучения вопроса, оказалось, что пользоваться стандартными средствами глобализации и не использовать сопутствующие сборки не получится, это заложено в модель ресурсов платформы по умолчанию. Подробности: Упаковка и развертывание ресурсов в приложениях для настольных систем Практическое руководство. Создание локализованной версии файла ресурсов Пошаговое руководство. Локализация форм Windows Forms В таком случае если не устраивает стандартная модель ресурсов и нужна поддержка разных языков в одной сборке - придется строить что-то свое.

четверг, 9 января 2020 г.

Почему строки с fuzzy в django.po не переводятся?

#python #локализация #django


Я обновляю файл django.po таким образом:
$ python manage.py makemessages -l ru
$ python manage.py compilemessages -l ru

После этого часть строк в django.po помечаются как fuzzy и не переводятся во время
работы приложения. Например, при 
#, fuzzy
msgid "view"
msgstr "показ"

вместо показ будет view.    


Ответы

Ответ 1



При выполнении makemessage как fuzzy помечаются строки имеющие близкий msgid. Такие строки не попадают в итоговый *.mo из *.po, как предположительно неверные. Нужно их поправить и убрать пометку fuzzy.

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

Почему строки с fuzzy в django.po не переводятся?

#python #локализация #django


Я обновляю файл django.po таким образом:
$ python manage.py makemessages -l ru
$ python manage.py compilemessages -l ru

После этого часть строк в django.po помечаются как fuzzy и не переводятся во время
работы приложения. Например, при 
#, fuzzy
msgid "view"
msgstr "показ"

вместо показ будет view.    


Ответы

Ответ 1



При выполнении makemessage как fuzzy помечаются строки имеющие близкий msgid. Такие строки не попадают в итоговый *.mo из *.po, как предположительно неверные. Нужно их поправить и убрать пометку fuzzy.

четверг, 2 января 2020 г.

Почему нужно переопределять локаль для вывода локализованнах строк (например strftime())?

#python #локализация #datetime #локаль


В соответствии с документацией, strftime() должен возвращать локализованные значения
даты и времени (название месяцев и дней недели и т.д.), однако делает это лишь после
явной установки локали:

>>> locale.getlocale() # Проверим текущую локаль
('ru_RU', 'UTF-8')
>>> d1.strftime('%A')
'Sunday'
>>> locale.setlocale(locale.LC_ALL, 'ru_RU.UTF-8')
'ru_RU.UTF-8'
>>> locale.getlocale()
('ru_RU', 'UTF-8')
>>> d1.strftime('%A')
'Воскресенье'


Почему на русском начинает выводить только после переопределения локали, хотя до
этого она и так была ('ru_RU', 'UTF-8')? Более того, достаточно просто сделать resetlocale:

>>> import locale
>>> locale.getdefaultlocale()
('ru_RU', 'UTF-8')
>>> locale.getlocale()
('ru_RU', 'UTF-8')
>>> d1.strftime('%A')
'Sunday'
>>> locale.resetlocale()
>>> d1.strftime('%A')
'Воскресенье'

    


Ответы

Ответ 1



Все программы на *nix системах (не только python) стартуют, используя C (POSIX) locale до тех пор пока они не вызовут setlocale(LC_ALL, ''), чтобы активировать пользовательскую locale. Если не хотите locale активировать для процесса, то можно использовать библиотеки, которые явно позволяют язык выбрать, такие как PyICU (пример использования)—есть полегче библиотеки, которые могут работать для конкретной задачи, например humanize: >>> import datetime >>> import humanize # $ pip install humanize >>> _ = humanize.i18n.activate('ru_RU') >>> humanize.naturaltime(datetime.datetime.now()) 'сейчас' В: но почему же locale.getlocale() выдаёт ru_RU? Я бы также ожидал, что-нибудь вроде (None, None) вместо ('ru_RU', 'UTF-8') до того как setlocale(LC_ALL, '') вызвано в программе. Из документации: "Returns the current setting for the given locale category" не очевидно, что пользовательские настройки из переменных окружения (LC_*, LANG) читаются, а не текущая локаль по умолчанию ("The POSIX locale is the default global locale at entry to main()") возвращается до вызова setlocale(LC_ALL, ''). locale модуль это тонкая обёртка вокруг соответствующей C функциональности, в частности, поведение может зависеть от платформы. Текущая реализация locale.getlocale() эквивалентна C setlocale(category, NULL), которая запрашивает текущую настройку для локали ("query the current global locale setting"). Почему "the current global locale setting" не равна "the default global locale" до вызова setlocale(LC_ALL, '') я не понимаю. Может дело в слове setting vs. locale, то есть текущая настройка до вызова setlocale(LC_ALL, '') берётся из переменных окружения (LC_*, etc), а текущая локаль до вызова setlocale(LC_ALL, ''), используемая strftime(), является C (как и положено). Но это чистая спекуляция с моей стороны.

среда, 25 декабря 2019 г.

Локализация WPF-приложения

#c_sharp #wpf #xaml #локализация


Подскажите, пожалуйста, как выполнить локализацию WPF-приложения?

Ни разу до этого не приходилось писать многоязыковые приложения. Локализацию строк
интерфейса сделал по этой статье Локализация WPF приложений на лету.
Но еще необходимо сделать перевод строк, которые выдает приложение в случае ошибки
или как подсказка пользователю. Например, пользователь выбирает файл неправильного
формата и получает сообщение в зависимости от выбранного языка.
    


Ответы

Ответ 1



Нормальная локализация в C# представлена одним единственным способом - resx файлы. Для небольших проектов можно просто включить ресурсы, открываем свойства проекта и пользуемся: В проекте при этом создается resx файл с локализацией по умолчанию. Чтобы добавить ещё одну - достаточно создать (Add -> New Item -> resx) ещё один файл, дополнив имя культурой (Resources.{culture}.resx) В коде просто пишем обращение к ресурсу: Console.WriteLine(Resources.Example); Для смены языка приложения принудительно достаточно поменять CurrentUICulture. Теперь по поводу дополнительных сборок. Хороших решений тут нет, простота выше описанного решения теряется, как только вы пытаетесь сделать шаг влево\вправо. Более менее рабочее решение описано тут (enSO), но оно жутко неудобное в использовании. Как можно заметить, простота использования вида Console.WriteLine(Resources.Example); теряется и обращения происходят уже вручную. Это можно автоматизировать, но тогда уже лучше вместо стандартного генератора посмотреть в сторону шаблонов (для общего представления можно глянуть MSDN). Т.е. чтобы сделать всё в одной сборке вам придётся написать замену стандартной схеме сборки ресурсов. Стоит ли оно того - решайте сами. Если интересны варианты с шаблонами - лучше изучите вопрос и задавайте вопросы отдельно, готовое решение так не видел, самописные в разных организациях - попадались. В дополнение, как совет по поводу: Планируется, что программа будет передаваться между коллегами и не хочется создавать зависимостей. Есть click-once, хоть он и очень неудачный на мой взгляд. Но, никаких заморочек по зависимостям и куче сборок не будет.

Написание новых man-страниц

#debian #локализация #man


В /usr/share/man/man1/ находятся мануалы для программ с расширением gz. Внутри этих
gz архивов html (если верить команде file /usr/share/man/man1/ab.1) документ с похожим
содержанием: ( 

.\" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
.\" DO NOT EDIT! Generated from XML source.
.\" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
.de Sh \" Subsection
.br
.if t .Sp
.ne 5
.PP
\fB\\$1\fR
.PP
..
.de Sp \" Vertical space (when we can't use .PP)
.if t .sp .5v
.if n .sp
..
.de Ip \" List item
.br
.ie \\n(.$>=3 .ne \\$3
.el .ne 3
.IP "\\$1" \\$2
..
.TH "AB" 1 "2015-05-01" "Apache HTTP Server" "ab"

.SH NAME
ab \- Apache HTTP server benchmarking tool


Вопросы:


Это чистый html ?
Как добавить дополнительную локализацию,чтобы сохранился оригинал.Т.е переведённый
файл нужно будет добавить в этот же gz архив или создавать для новой локализации отдельный
gz архив в отдельной папке /usr/share/man/ru/man1/локализация_для_проги.gz ? 
Что означает конечная цифра 1 в названии файла ? При локализации ab.1 мне нужно будет
изменить его на ab.2 ? 

    


Ответы

Ответ 1



Это чистый html ? Нет, это даже не язык разметки. это plain-text, разбавленный командами форматирования roff. когда-то программа, понимающая это форматирование, и способная оформить текст в каком-нибудь другом формате, называлась runoff, потом пошли наследники — troff, nroff, groff. (доп. см. $ man 7 man) Как добавить дополнительную локализацию,чтобы сохранился оригинал.Т.е переведённый файл нужно будет добавить в этот же gz архив или создавать для новой локализации отдельный gz архив в отдельной папке /usr/share/man/ru/man1/локализация_для_проги.gz? Да, локализованные man-страницы надо помещать в каталоги, называющиеся по имени языка локализации. каталоги должны располагаться на том же уровне иерархии, что и каталоги для секций (см. следующий ответ), и тоже должны быть разбиты на под-каталоги с секциями (man1, man2 и т.д.). т.е., путь должен звучать примерно как: /usr/share/man/ru/man1/программа.1 (или /usr/share/man/ru/man1/программа.1.gz, если файл сжат программой gzip) Что означает конечная цифра 1 в названии файла? Это номер секции. цитата из $ man 1 man: 1 Executable programs or shell commands 2 System calls (functions provided by the kernel) 3 Library calls (functions within program libraries) 4 Special files (usually found in /dev) 5 File formats and conventions eg /etc/passwd 6 Games 7 Miscellaneous (including macro packages and conventions), e.g. man(7), groff(7) 8 System administration commands (usually only for root) 9 Kernel routines [Non standard] Для примера: $ man 1 man — это запуск программы man с передачей ей двух параметров — номера секции (1) и названия запрашиваемой страницы (man). номера секций фигурируют не только в именах каталогов, но и в именах файлов (предполагаю, что последнее — это просто дань традиции или «тяжёлое наследие») При локализации ab.1 мне нужно будет изменить его на ab.2? Нет, переименовывать не надо. Разве что файл по смыслу должен принадлежать секции 2 и размещаться каталоге ru/man2 (см. предыдущий ответ).

пятница, 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()); } }

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

Преобразование даты между строковыми представлениями

#python #python_3x #локализация #datetime


Мне приходят данные в виде 'Март 1, 2010', 'Сен. 1, 2010' и т.п. Меняю им вид вот так: 

def date_convertion(datetime):
    res = datetime.split(' ')
    res.reverse()
    return (res[0] + '-' + res[2][:-1] + '-' + res[1][:-1])


datetime получаю вот такой:

['Март 1, 2010']


на выходе функции это уже вот так:

['2010-Март-1']


Вопрос: как "Март" преобразовать в "03"? Создать словарь (он же ассоциативный массив)
и искать по ключу значение или можно это сделать иначе?
    


Ответы

Ответ 1



При преобразовании из одного строкового формата в другой, особенно если входной формат нефиксированный и возможны вариации, то полезно использовать промежуточный объект-дату, чтобы убедиться что значения были интерпретированы корректно. входная строка -> объект-дата -> выходная строка Например: datetime.strptime("входная строка", "формат") -> datetime объект -> dt.strftime("формат вывода") setlocale() вариант Если русская локаль установлена для программы или известно её название на данной платформе, то можно её активировать и попробовать распознать входные строки, используя фиксированный список форматов: #!/usr/bin/env python3 import locale from datetime import datetime locale.setlocale(locale.LC_TIME, 'ru_RU.UTF-8') # the ru locale is installed date_strings = ['Март 1, 2010', 'Сен. 1, 2010', '2015-Апрель-26'] print(date_strings) date_formats = '%B %d, %Y', '%b %d, %Y', '%Y-%B-%d' dates = [] for date_str in date_strings: date_str = date_str.replace('Сен.', 'Сент.') # fix the abbr. for date_fmt in date_formats: try: dates.append(datetime.strptime(date_str, date_fmt).date()) except ValueError: pass else: break else: print('failed to parse %r' % date_str) output_date_strings = list(map(str, dates)) print(output_date_strings) Вывод ['Март 1, 2010', 'Сен. 1, 2010', '2015-Апрель-26'] ['2010-03-01', '2010-09-01', '2015-04-26'] ICU вариант Если есть возможность установить PyICU, то можно использовать несколько локалей независимо от наличия соответствующей системной локали и без изменения глобального состояния программы (может быть полезно в многопоточном приложении) [синтакс ICU форматов для времени]: #!/usr/bin/env python3 from datetime import datetime import icu # PyICU date_strings = ['Март 1, 2010', 'Сен. 1, 2010', '2015-Апрель-26'] print(date_strings) df = icu.SimpleDateFormat('', icu.Locale('ru')) output_df = icu.SimpleDateFormat('yyyy-MM-dd') output_date_strings = [] for date_str in date_strings: date_str = date_str.replace('Сен.', 'Сент.') # fix the abbr. for pattern in 'LLLL d, yyyy', 'yyyy-LLLL-dd': df.applyPattern(pattern) try: output_date_strings.append(output_df.format(df.parse(date_str))) except icu.ICUError: pass else: break else: print('failed to parse %r' % date_str) print(output_date_strings) Результат такой же как у первой программы. str.replace() вариант Если входные данные более разнообразны, то можно ещё добавить предварительный шаг, который сделает их более регулярными, например, как date_str.replace() выше (можно словарь использовать со списком замен). Например, можно избавиться от зависимости на локаль, заменяя все названия соответствующими цифрами: for old, new in [('Март', '3'), ('Сен.', '9'), ('Апрель', '4')]: date_str = date_str.replace(old, new) После этого можно использовать datetime.strptime() c '%m %d, %Y', '%Y-%m-%d' форматами без setlocale() вызова.

Ответ 2



Кратко Многое в решении вашей проблемы зависит от формата строки. Если названия месяцев соответствуют русской локали и записаны либо полностью, либо сокращённо до трёх букв, то можете воспользоваться стандартной библиотекой datetime. В противном случае, если единого формата нет, можете задать словарь замен. Например (для двух месяцев): month = {'Март': '03', 'Апр.': '04'} Использовать его в вашем случае легко: month[res[2][:-1]]. Небольшое замечание. Решение с использованием reverse и split, конечно, работоспособно, но не очень хорошо читается. Я бы использовал на вашем месте регулярные выражения. Тогда при замене формата строки изменения в программе будут минимальными. Замена с помощью datetime Для начала задайте локаль (достаточно один раз в начале программы). Если у вас система уже настроена на русский язык, то достаточно выполнить следующие команды: import locale locale.setlocale(locale.LC_ALL, '') Если язык системы другой, то вместо пустых кавычек укажите требуемую локаль. При помощи метода strptime вы можете проанализировать строку на соответствие некоторому формату. Пример: from datetime import datetime d = datetime.strptime("Апр. 6, 2015", "%b. %d, %Y") print(d) 2015-04-06 00:00:00 Здесь %b — краткое название месяца в текущей локали, %d — номер дня, %Y — номер года (4 цифры). В переменной d будет находиться экземпляр класса datetime, который можно привести к любому другому виду. В вашем случае: print(d.strftime('%Y-%m-%d')) 2015-04-06 Перечисленный операции можно объединить в одну функцию и использовать её для добавления элементов в список: def date_convert(s): return datetime.strptime(s, "%b. %d, %Y").strftime('%Y-%m-%d') [date_convert(d) for d in dates] Здесь dates — список строк, хранящих даты в указанном вами формате. Если требуется одновременно использовать две локали, то действия с датами можно выполнять, например, внутри with написав контекстный процессор. Библиотека datetime

Ответ 3



Добавление элемента в список или в ассоциативный массив Добавление элемента в список производится с помощью функции append: my_list.append( new_element ) Другой способ: my_list += [ new_element ] Добавление в ассоциативный массив выполняется так: my_dict.update({ new_key : new_element }) или ещё проще: my_dict[ new_key ] = new_element Это если говорить в общем. У вас же вопрос немного туманный и не совсем понятно, что вы пытаетесь сделать. Преобразование даты между форматами Преобразование даты осуществляется обычно с помощью функции strptime, которая из вашей строки сделает объект даты, с которым можно выполнять дальнейшие манипуляции, в том числе форматирование в другой формат. Это будет выглядеть так: d = datetime.datetime.strptime(d_string, fmt) d_string2 = d.strfime(fmt2) В данном случае я преобразовал исходную строку d_string из формата fmt в формат fmt2, результат записан в d_string2. (правда это к спискам не имеет никакого отношения).

Ответ 4



import functools, datetime, icu _Replace = [('фев', 'февр'), ('ноя', 'нояб'), ('май', 'мая'), ('сен', 'сент'), ] MonthReplace = (_Replace + [(s.capitalize(), r) for (s, r) in _Replace]) # для автозамены + capitalize AllLocales = (En, Ru,) = list(map(icu.Locale, ['en', 'ru', ])) TZ = icu.ICUtzinfo.getDefault() # time zone, ~ в 2012г была другая, эти даты парсит на час назад s_rus = 'авдимнопсфчя' # первые буквы имен месяцев и недель S_Rus = set(s_rus + s_rus.upper()) IcuDateMasks = ['dd/MMM/yy HH:mm:ss', 'dd/MMM/yy HH:mm', 'EEE, dd MMM y HH:mm:ss', 'EEE, dd MMM y HH:mm', 'EEE, dd MMM y', 'EEE MMM dd HH:mm:ss y', ] # http://userguide.icu-project.org/formatparse/datetime DateMaskForIcu = {(mask, lcl): icu.SimpleDateFormat(mask, lcl) for mask in IcuDateMasks for lcl in AllLocales} @functools.lru_cache() def str_to_datetime(datetime_str: str) -> 'datetime.datetime': (dtime_str, lcl) = _find_locale(datetime_str.split('+', 1)[0].strip()) for mask in IcuDateMasks: # выбрать правильный формат маски try: return datetime.datetime.fromtimestamp(icu.DateFormat.parse(DateMaskForIcu[mask, lcl], dtime_str), TZ, ).replace(tzinfo=None) except icu.ICUError: continue raise UserWarning(f'"{dtime_str}" не распознана в локали "{lcl}", ни по одной из масок "{IcuDateMasks}" !!!') def _find_locale(datetime_str: str) -> (str, 'icu.Locale'): if any((s in datetime_str) for s in S_Rus): # рус locale for (s, r) in MonthReplace: if s in datetime_str: datetime_str = datetime_str.replace(s, r, 1) # 'правильные' имена месяцев break return datetime_str, Ru else: return datetime_str, En if __name__ == '__main__': print(str_to_datetime('04/июн/12 11:56')) # 2012-06-04 11:56:00 print(str_to_datetime('15/Jan/19 2:49')) # 2019-01-15 02:49:00 print(str_to_datetime('15/Фев/19 20:42:01')) # 2019-02-15 20:42:01 print(str_to_datetime('Пт, 02 ноя 2018 14:26:00')) # 2018-11-02 14:26:00

вторник, 10 декабря 2019 г.

Android. Локализация

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


Нужно сделать так, что бы при некоторых локалях использовался по дефолту русский,
а при некоторых английский. Вижу такое решение: во всех соотвествующих папках values-xx,
вставить файл такой же как и в values-ru, а в других такой же файл как и в values-en.
Но ведь их довольно много... можно как то по - другому?    


Ответы

Ответ 1



да, можно разместить в ресурсах values-xx с указанием кода нужной локали(коды локалей можно посмотреть вот в этой таблице во второй колонке), а строковые ресурсы разместить в values-en и values-ru. При запуске приложения читаем локаль из values-xx и пишем Locale locale = new Locale("код прочитанной локаили"); Locale.setDefault(locale); Configuration config = new Configuration(); config.locale = locale; getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics()); UPD: английский язык я бы посоветовл сделать по умолчанию и разместить в папкe values без модификаторов. UPD[2]: Как я понял из задачи, то есть группы локалей, которым нужно показывать английский интерфейс, а другим группам русский. Так вот, в тех группах, где нужен русский интерфейс вы в value-xx пишите строковый ресурс с локалью "ru", аналогично для английской. Когда будете считывать локаль String localeCode = getResourses().getString(R.string.locale) андроид сам определить от куда взять. А потом выполняете Locale locale = new Locale(localeCode);...

Ответ 2



UPD. Прочитав еще раз, понял что не подходит. Больше подойдет предыдущий ответ на вопрос: тут Оригинал:тут Мой краткий перевод-пересказ: Идеальным решением было бы использование множества модификаторов имени для папки ресурсов из одной группы (values-ru-ua-en-fr), но разрешены только модификаторы из разных групп (drawable-en-hdpi) Но это все еще не означае, что вам придется бесполезно копировать кучу одинаковых файлов. На помощь тут приходят ссылки на ресурсы (ориг. alias resources). Ссылка на http://developer.android.com/

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

Как сменить язык пользователю на сайте Django?

#python #django #локализация


Делаю возможность на сайте переключаться между русской, английской и украинской версией.
Обернул строки в шаблонах, которые надо перевести, в тег {% trans %}, строки в коде,
всё перевёл и скомпилировал перевод. Также установил locale_url.

В settings.py прописал:

LANGUAGE_CODE = 'Ru-ru'
LANGUAGES = (
('en', 'English'),
('ru', 'Russian'),
('uk', 'Ukrainian'),
)

TIME_ZONE = 'Europe/Kiev'
USE_I18N = True
USE_L10N = True
USE_TZ = True

LOCALE_PATHS = (
'locale',
 # os.path.join(BASE_DIR, 'locale'),
)


Переключать язык через POST, так как это делается в django.conf.urls.i18n мне не
захотелось, поэтому создал такое представление:

def select_lang(request, code):

go_next = request.META.get('HTTP_REFERER', '/')
response = HttpResponseRedirect(go_next)
if code and translation.check_for_language(code):
    if hasattr(request, 'session'):
        request.session['django_language'] = code
    else:
        response.set_cookie(settings.LANGUAGE_COOKIE_NAME, code)
    translation.activate(code)
return response


Перехожу в браузере на /lang/uk, страница перезагружается, а язык остаётся прежний.
Если вводить адрес /uk/about - страница переводится, но при переходе на другую язык
опять возвращается.

В чем проблема, подскажите, пожалуйста!

Вот мои middleware, может в них дело:

MIDDLEWARE_CLASSES = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.locale.LocaleMiddleware',
]


P.S. язык сайта по дефолту русский, как и весь текст в коде и в шаблонах. Но у меня
по умолчанию отображается английский. Через заголовки запроса
"Accept-Language en-US,en;q=0.5"

P.S.S. функцию вьюхи проверял, на выходе у request.session['django_language'] стоит
код языка, который мне надо.
    


Ответы

Ответ 1



Нужно в метод добавить еще: request.session['_language'] = code В сессии django хранит 2 параметра: django_language и _language

вторник, 16 июля 2019 г.

Как использовать языки, которые не поддерживаются официально в “windows phone”?

Доброго времени суток, Хэшкод. Насколько я понял, сейчас в WP7 язык приложения по умолчанию подстраивается под язык в настройках (регион + язык -> язык интерфейса) Статей по данной тематике довольно много, и все довольно просто. Но существует проблема. WP7 поддерживает не так уж много языков, а у меня например есть необходимость использовать языки, которые не входят в список поддерживаемых. Попробовал было установить язык напрямую: Thread.CurrentThread.CurrentCulture = new CultureInfo("ыы-ЫЫ"); // ыы-ЫЫ - аббревиатура никому не известного языка Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture; Однако так сделать не получилось, т.к. на неизвестные языки программа ругается. С известными все проходит. Как можно использовать такие языки? Есть у кого идеи? [обновлено 10.09.2012] Так, более актуальный вопрос: Я тут внезапно заметил, что после смены языка требуется перезагрузка ОС. Это вообще нормально? И можно ли как-то эту фигню обойти?


Ответ

Вариант решения описан здесь: Localization with an unsupported language На первый взгляд - работает. Как проверю свой вариант, отпишусь о результатах. Сделал, действительно работает, хотя подводных камней довольно много. Как будет время - распишу решение подробно. Итак: Возможности для выстрела в ногу (обратить внимание тем, кто сначала написал в стиле, рекомендованном Майкрософт(как я), а потом вынужден будет реализовывать новый язык. Все обращения к ресурсам придется переписывать. Это печально. Поехали): В классе LocalizedResources.cs путь к ресурс-менеджеру описывается в стиле: _rman = new global::System.Resources.ResourceManager("AppName.Folder.ResourcesApp", typeof(ResourcesApp).Assembly); для известных языков где: AppName - имя приложения Folder - папка, в которой лежат ресурсы. У меня это была папка Resources. Если в корне - соответственно ничего не пишем. ResourcesApp - то, как называются наши файлы для известных языков. В примере он один и называется Resource(для английского). Т.е. для английского это будет Resource.resx или Resource.en-US.resx или Resource.en-UK.resx, для русского Resource.ru-RU.resx и.т.п. Постфикс(а.к.а ru-RU) не имеет значения, нужный язык потом выберется через метод SwitchCulture для неизвестных соответственно используется перегруженный метод SwitchCulture public void SwitchCulture(string UnsupportedCulture) { _rman = new global::System.Resources.ResourceManager("App.Resources.XXX" + UnsupportedCulture, typeof(ResourcesApp).Assembly); } где XXX это то, как полностью называется файл с ресурсами для неизвестного языка. В примере эти файлы называются Resource_Klingon.resx и Resource_Vulcan.resx. // там должно быть подчеркивание между словами, почему-то не отображается У меня было соответственно ResourcesApp.LanguageName.resx Т.е. в примере путь выглядел, как "PhoneApp1.Resource_", в моем случае "App.Resources.ResourcesApp." Для обращения к ресурсам используется метод Get. Соответственно все обращения в стиле: Resources.resourceName придется заменить на LocalizedResources.Resources.Get("resourceName") Аналогичная ситуация со связыванием через Binding. Вместо обращений, типа: "{Binding Path=LocalizedResources.someName, Source={StaticResource LocalizedStrings}}" используются {"Binding Source={StaticResource LocalizedStrings}, Converter={StaticResource LocalizedStrings}, ConverterParameter=someName}"

четверг, 11 июля 2019 г.

Мультиязычный интерфейс

Хочу создать мультиязычный интерфейс. Переписывать весь код, заменяя весь текст на переменные из собственно созданного файла ресурсов, мне было лень. Я воспользовался классом CultureInfo. Также мне помог урок на ютубе. В итоге сделать мультиязычный интерфейс у меня получилось, однако язык интерфейса меняется только в новом экземпляре формы. Никакие update, resumlayout, refresh не обновляют текст на форме( возможно конечно я не для всех методов знаю назначение, но я попробовал).
Для простоты тестирования, я повесил это все на кнопку с кодом:
Thread.CurrentThread.CurrentUICulture = New CultureInfo("en-150") Dim t As New Form1 t.Show()


Ответ

Можно создать ComponentResourceManager, передав ему тип формы, и рекурсивно вызвать ApplyResources для всех контролов. Примерно так:
Private Shared Sub ChangeLanguage() For Each frm As Form In Application.OpenForms LocalizeForm(frm) Next End Sub
Private Shared Sub LocalizeForm(frm As Form) Dim manager = New ComponentResourceManager(frm.GetType()) manager.ApplyResources(frm, "$this") ApplyResources(manager, frm.Controls) End Sub
Private Shared Sub ApplyResources(manager As ComponentResourceManager, ctls As Control.ControlCollection) For Each ctl As Control In ctls manager.ApplyResources(ctl, ctl.Name) ApplyResources(manager, ctl.Controls) Next End Sub
Применять примерно так:
Thread.CurrentThread.CurrentUICulture = New CultureInfo("ru-ru") ChangeLanguage()
Вариант на C#:
private static void ChangeLanguage() { foreach (Form frm in Application.OpenForms) { LocalizeForm(frm); } }
private static void LocalizeForm(Form frm) { var manager = new ComponentResourceManager(frm.GetType()); manager.ApplyResources(frm, "$this"); ApplyResources(manager, frm.Controls); }
private static void ApplyResources(ComponentResourceManager manager, Control.ControlCollection ctls) { foreach (Control ctl in ctls) { manager.ApplyResources(ctl, ctl.Name); ApplyResources(manager, ctl.Controls); } }
код честно взят с enSO, Change language at runtime in C# winform

воскресенье, 7 июля 2019 г.

Как прочитать локализированую строку?

Создал новый проект в С#, windows forms, поставил label1 на форму написал ему Text: Hello, дальше изменил Language формы на русский изменил Text label1 на Привет, создался файл ресурсов Form1.ru.resx. Как теперь мне получить этот привет програмно? Вопрос в том, как добавить строку самому а не измения компонент для некого языка и потом в зависимости от языка читать эту строку. Как програмно читать String1?


Ответ

То что Вы делаете не совсем правильно. Дело в том, что при попытке добавить вручную строку в resx-файл для формы возникает предупреждение о том что это делать крайне нежелательно, т.к. может повредить форму (дословно: editing this item could corrupt the project item).
Вобщем если Вам нужно только менять текст лейбла на форме, то ничего вбивать в resx не надо. Дизайнер все сам вобъет. Если же Вы хотите вывести какой-то текст программно (MessageBox или динамический текст на форме), то лучше создать свой файл resx.
Вот тут подробно расписано, как работать со своими resx-файлами.

среда, 5 июня 2019 г.

Мультиязычное приложение на C [закрыт]

Подскажите, как в C обычно делают мультиязичность?


Ответ

например, с помощью gnu/gettext (там присутствует ссылка на подробнейшую англо-язычную документацию).
есть статья в русскоязычной википедии, в которой приведён небольшой пример.
там же, к примеру, упоминается и краткое русско-язычное руководство