Pull to refresh

Comments 32

Так связки есть только к JavaScript, Rust и Python, или всё же есть Си-шный API? Всё-таки универсальная библиотека по хорошему должна быть доступна из любых языков.
Судя по всему, пока только вышеперечисленные.
Так не бывает: сопровождение неограниченного списка языков разработчиком просто невозможно — требуется участие причастных к самому языку (целевому), а тут от разработчика мало что зависит кроме выбора языка разработки, который широко используется для создания биндингов или поддержки промежуточных биндингов для такого языка.
В этом смысле да, требуются биндинги/API на C

Так на чём сама либа написана? Или это вовсе не биндинги, а именно полноценные реализации имелись в виду?

Тогда на C я бы очень хотел отдельную реализацию, а не биндинги. Пихать интерпретатор полноценного языка (особенно в C, когда это дело порой нужно залить на микроконтроллер) ради одной либы — не самая хорошая идея ИМХО.

Что-то мне подсказывает, что gettext местами тоже жирноват для микроконтроллеров

Спорить тут не буду, самому аж интересно стало, можно ли его впихнуть на ESP32 (с SD картой для файлов). Но остаюсь при мнении, что проге на C лучше уж использовать и либы на C.

Комментарии локализаторов: нет

Ну как же www.gnu.org/software/gettext/manual/html_node/Modifying-Comments.html#Modifying-Comments

Создан для: Языков семейства С

Вот перечень поддерживаемых типов файлов/языков для xgettext
C, C++, ObjectiveC, PO, Shell, Python, Lisp, EmacsLisp, librep, Scheme, Smalltalk, Java, JavaProperties, C#, awk, YCP, Tcl, Perl, PHP, GCC-source, NXStringTable, RST, Glade, Lua, JavaScript, Vala, Desktop

Привязка аргументов: позиционная

Это к gettext лишь косвенно относится (там нет форматтера аргументов, используется стандартный) и зависит от языка программы — в Python прекрасно работают ключи.

В gettext использует три формата файлов — *.po, *.pot и *.mo. Это влияет на внедрение gettext в производственный цикл, добавляя этапы вроде извлечения и компиляции сообщений.

По факту .po и .pot это один и тот-же формат, .pot и .mo автоматически генерируемые, их не нужно хранить в репозитории. Компиляция это ещё и проверка синтаксиса, а автоматическое извлечение сообщений — это наиболее полезная функция в gettext.
xgettext + msgmerge это как-раз то, что избавляет от головной боли при работе с большим числом сообщений. Пока Fluent сам по себе не предлагает решения этих проблем, с каждым id нужно возиться вручную.

P.S. Fluent гораздо лучше .po в качестве формата, но xgettext отнюдь не так плох, и исторически хорошо себя зарекомендовал как достаточно простое и удобное решение, для большинства случаев вполне достаточное. Лучшее враг хорошего :)
Я не настоящий разработчик, поэтому мне сложно судить о технической стороне вопроса. Но с точки зрения локализатора, я полностью разделяю мнение авторов fluent про болезненность подхода «оригинал = идентификатор». Надеюсь, что у fluent тоже появится механизм для извлечения сообщений и превращения их в ID в коде, тогда все (разработчики, переводчики) будут рады.
Ну тогда по технической части мелкие неточности, кроме уже указанных
Идентификатор сообщения: исходная строка

Обычно да, но есть ещё msgctx точнее было бы написать контекст + исходная строка

не умеет работать с форматированием дат и чисел
Fluent активно использует стандартизованные библиотеки и алгоритмы CLDR, ICU

В большинстве случаев форматированием дат и чисел уже занимаются функции ОС/браузера/окружения, которые как раз и используют ICU(CLDR) и gettext этому никак не мешает. В том же JavaScript этим обычно занимается Intl, и он существует независимо от Fluent.

Шаблоны сообщений: необходимы (.pot)

Но ведь .ftl и есть тот самый шаблон. Непосредственно для переводчиков сам .pot не нужен — после генерации и обновления .po файлов его можно удалить, его не хранят.
Технически он есть, вот такой временный генерируемый файл. Но после настройки сборки о существовании .pot или .mo можно забыть и работать только с обновляемыми .po

Не раскрыта тема устаревших переводов, .po может их хранить/накапливать и «воскрешать» в случае необходимости — вот такая «память переводов» из коробки :)
На всякий случай напомню, что это перевод, а не моя оригинальная статья :-)

В большинстве случаев форматированием дат и чисел уже занимаются функции ОС/браузера/окружения, которые как раз и используют ICU(CLDR) и gettext этому никак не мешает. В том же JavaScript этим обычно занимается Intl, и он существует независимо от Fluent.

Имхо, это некорректный подход. Не обязательно локаль браузера/ОС соответствует локали сайта/продукта, и получается мешанина из, например, английского текста и китайской даты. Следовательно — плохой UX.
Не обязательно локаль браузера/ОС соответствует локали сайта/продукта, и получается мешанина из, например, английского текста и китайской даты.

Эмм… я не писал о том что нужно обязательно использовать текущую локаль браузера/ОС. Обычно ОС поддерживает вполне солидный набор локалей, можно выбрать наиболее подходящую, не обязательно текущую/по умолчанию.
При взаимодействии с другими программами в GNU/Linux например скорее всего они (другие программы) будут использовать текущую локаль системы и для консистентности продукт должен работать так-же
Я имел в виду такую ситуацию:
Есть программа, UI на русском. В системе выбрана английская локаль США. Если программа будет полагаться на форматирование чисел по локали системы, то получится, что в русском интерфейсе цифры будут отформатированы на американский манер. Или я не прав, и можно заставить софт (с gettext) использовать именно правила форматирования для русского языка, независимо от локали системы?
Да, можно форматировать дату на любой локали, которая поддерживается ОС независимо от текущей. Это никак не относится к gettext, обычно это стандартная библиотека.

P.S. Для Python gettext — стандартная библиотека.
Спасибо за дополнение в комментарии. За это люблю habr — очень много полезного можно почерпнуть из обсуждений.
Я как-то упустил из виду что это перевод :) извините.
Официальная позиция разработчиков Fluent вполне ожидаема — и маркетинг им не чужд.

Да что там говорить, если очень многие не могут осилить даже gettext. Конкретно на Хабре раз в 3-6 месяцев появляется очередная статья об очередном «гениальном» способе перевода, который является примитивной костыльной надстройкой над каким-нибудь Excel/CSV.


А тут какой-то новый инструмент, по которому не найти ни капли информации, да еще не знаю, поддерживается ли хоть одним инструментом для переводчиков, таким как Weblate...


Кроме того, часть перечисленных недостатков не являются недостатками gettext. Например, про изменение исходных текстов и потерю переводов: в gettext есть встроенные средства для того, чтобы не терять переводы (fuzzy), а кроме того, наверное, в идеальном случае инструмент перевода должен интегрироваться с Translation Memory что для gettext, что для любого другого формата.

Fuzzy отдельным абзацем упомянут как неидеальный (по мнению разработчиков fluent) способ сохранения переводов. И я с ними согласен.

Насколько знаю gettext не запрещает использовать идентификаторы, как строки.
Хотя это и не принято.


Выглядит проект интересно, но, где примеры? на сайт зашел… там пример напоминает просто форматирование. локализации не увидел(по крайней мере на главной).
нужны примеры на всех уровнях, а так же более широкую поддержку ЯП.

Насколько знаю gettext не запрещает использовать идентификаторы, как строки.

Вот пользователи C локали спасибо скажут вам за id без значений вместо строк. Плюс предупреждения о несовпадении переносов строк/символов форматирования (%s, %d, etc.). Последнее, кстати, ИМХО плюс в сторону строк против id.

"Просто форматирование" — это когда форматные строки зашиты в коде. А когда они все вынесены в отдельный файл, выбираемый в зависимости от языка — это уже локализация.

Так я и говорю, нужны примеры как это работает в коде. Именно пример локализации через Fluent.

В живую Fluent я ещё не использовал, но зато пользовался gettext. И после того, что я узнал про возможности Fluent, использовать gettext у меня больше нет желания.
Я программист и мой первый шок от gettext был когда я понял, что для получения перевода с поддержкой множественных форм, я должен в коде использовать отдельную функцию и передать ей варианты написания куска текста, зависящего от числа. Как так? Зачем я, как программист, должен думать про множественные формы?
Позднее мне стало понятно почему так получилось в gettext — потому что он разрешает использовать текст как id сообщения, а значит должен уже в коде приложения иметь всю информацию необходимую для генерации текста, даже если вообще нет ни каких переводов.
В Fluent с этим всё становится легко и просто. Для получения перевода в коде используется только одна функция, и мне не надо при этом думать про множественные формы даже для одного (например английского) языка. А ещё в Fluent (в отличии от gettext) можно в рамках одного сообщения использовать несколько разных чисел для выбора множественной формы разных частей строки. А можно использовать вообще не числа, а например пол «персонажа» и вообще любой другой «селектор», который может повлиять на перевод.
С Fluent в принципе не нужны инструменты для извлечения «строк» из кода, не надо их мержить с уже имеющимися переводами, т.к. в коде есть только id сообщений. Тут конечно есть минус — можно забыть добавить id в переводы если у вас нет тестов в приложении, которые вероятно выдадут ошибку при запросе не существующего перевода.
По поводу инструментов для работы с переводами — у Mozilla есть в гитхабе опен-сорсное веб-приложение для совместной работы над переводами (они используют его для перевода своих проектов), название не помню, но в одной с предыдущих статей про Fluent на хабре оно упоминалось.
Зачем я, как программист, должен думать про множественные формы?


Вот это ключевая ценность Fluent. Пусть локализаторы/переводчики/UX-writer'ы думают, как писать контент, им за это платят.
Разработчик всё равно должен передать все «селекторы» из кода, просто дальнейшая логика работы по построению сообщения сброшена на «локализаторов/переводчиков/UX-writerов». Гибкость Fluent усложняет оценку затрат на переводы и тестирование/контроль качества.
Для всяких энтузиастов и опенсорса это хорошее решение, но в мире коммерческих переводов, где цена зависит от объема текста — маловероятно что переводчики будут заморачиваться с логикой без дополнительных капиталовложений. Почему переводчик на русский должен писать целую пачку сообщений с учётом комбинаций числа и рода, в то время когда в английском это была лишь пара строк?
(Переведут «Сообщений: X» и хватит :) )
gettext довольно строго регламентирует plural, изначально требуя все формы, необходимые с учётом языка. Хотя это и дубово — это фиксированный и заранее известный объем работы для переводчиков и QA. А вот креатив с Fluent уже не так прост и предсказуем.
Зависит от того, как построен процесс. Если текст отдают на аутсорс переводчику, которому платят за объём, то вы совершенно правы. И там переводчику всё равно, плывёт у вас UI или не плывёт.
А если это штатный UX-копирайтер или локализатор — то объёмы могут быть незначительные. Я работал и в роли аутсорса, и в роли штатного локализатора, поэтому знаю, о чём говорю.
Но в обоих случаях у программиста обычно нет знаний такого количества человеческих языков, чтобы во всех нужных местах подставить селекторы и прочее.
Про «селекторы» я имел ввиду, что для того, чтобы логика построения в Fluent работала, разработчики всё равно должны передать число, род в саму систему — в контекст сообщения. Вместо явной привязки к конкретному сообщению эти дополнительные данные привязываются к сущности в Fluent являющимися контекстом для сообщений. Разработчик должен откуда-то взять род/число/социальный статус/возраст (и прочие «селекторы») и передать их в Fluent — должен знать что они там нужны (пусть даже и не понимать как и зачем они используются).
Но в обоих случаях у программиста обычно нет знаний такого количества человеческих языков, чтобы во всех нужных местах подставить селекторы и прочее.

Переводчик не сможет использовать селектор по роду/числу, если этих данных у него нет. А передать их может только разработчик.

Не все компании могут себе позволить держать штатных переводчиков/локализаторов :(.
Разработчик должен откуда-то взять род/число/социальный статус/возраст


Всё правильно: если данных негде взять, то будет один вариант. А если есть — разработчик просто передаёт этот параметр, и дальше локализатор решает, как быть.

Не все компании могут себе позволить держать штатных переводчиков/локализаторов :(

А кто с этим спорит? Не бывает одного решения, которое идеально подойдёт для всех кейсов.

Объясню на примере моего любимого AliExpress, где я бы очень хотел внедрить Fluent. У нас тут поддержка 18 языков, но только пять из них — штатными копирайтерами, остальное — аутсорс. Используя флюент, мы могли бы сделать красиво хотя бы пять языков, а остальные оставить в безопасном generic варианте без учёта вариативности. Но мы не можем: либо всё, либо ничего. А правила plural в каком-нибудь арабском и русском значительно отличаются, поэтому нужно городить кучу селекторов со стороны разработчиков, а у них и так работы хватает.
Возможность сделать красиво целых 5 языков — это замечательно.
Кстати комментарий очень полезный — он как раз наглядно показывает зачем и почему Fluent :). Удачи в этом нелёгком деле.

P.S. При работе только с аутсорсом преимущества Fluent не так хорошо выражены. На примере с plural gettext явно выдаёт нужное количество форм на перевод, но всё равно иногда (не часто) переводчиков приходится дополнительно просить, чтобы различные формы вообще использовали в переводе o_O.

P.P.S. Доля сообщений/текстов, требующих дополнительной языко-зависимой логики построения обычно не так велика, чтобы это было какой-то острой проблемой, но всё зависит от типа приложений.
Only those users with full accounts are able to leave comments. Log in, please.