doldonius: (Default)
Doldonius ([personal profile] doldonius) wrote2010-09-18 09:56 am

Программистам на подумать

Предложение насчет i18n прибили тапком. Резоны:

1. Интерфейс системы перевода (видимо, речь об унаследованной от LJ) совершенно ни к черту;

2. Очень трудно координировать работу переводчиков-добровольцев;

3. Они не знают, как сделать, чтобы стало легко поддерживать перевод в актуальном состоянии (что, видимо, обусловлено ровно теми же причинами, что проблема 2).

Кроме того, в старом подробном разборе упомянуто, что в LJ i18n сделана типичным пыхопоидальным методом: вместо текста в страницу впыживается запрос к базе данных. Так делают все пыхопоиды — следовательно, это неправильно. Должен существовать Правильный Способ, одновременно уменьшающий нагрузку на серверы и облегчающий жизнь как англоязычным кодерам, так и переводчикам.

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

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

На этом остановлюсь, ибо опасно близок к русской программистской идее (переписать все к разэтакой матери с нуля). Что скажете, сэры? Не попадался ли где ровно такой велосипед? И если нет, насколько сложно его изобрести?
link01: (Default)

[personal profile] link01 2010-09-18 10:58 am (UTC)(link)
Симпатичная система перевода сделана в Qt, хотя здесь она годится только в качестве источника вдохновения.


Текстовые сообщения Qt встраиваются в код, и каждое сообщение, предназначенное для последующего перевода, заворачивается в макрос tr(). После окончания отладки наступает очередь переводчика; он натравливает на код инструмент под названием Qt Linguist, который находит эти сообщения и позволяет переводчику создавать дополнительные файлы с текстами переводов. Эти дополнительные файлы подхватываются приложением во время работы в зависимости от какой-то переменной окружения ($LANG или $LOCALE).

Главное - что
1) Сообщения хранятся в тексте программы. Переводы хранятся в дополнительных файлах и подхватываются во время исполнения.
2) Сообщения (и переводы)
- целостны; они не разбиваются на мелкие части а-ля cout << numFiles << "files of" << totalFiles << "totalFiles read.\n".
- уникальны; для двух одинаковых сообщений в разных местах придется делать два перевода.
3) сообщения заворачиваются в макрос tr(), что
- позволяет Qt Linguist автоматически искать их в тексте,
- обеспечивает подковерную автоматику по поиску и замене исходного текста переводом во время исполнения.

Выглядит это примерно так:

statusBar()->showMessage(tr("Loaded %1").arg(fileName), 2000);

(%1 и .arg(fileName) - это слегка мутировавший printf; fileName подставляется на место %1.)
link01: (Default)

[personal profile] link01 2010-09-18 04:51 pm (UTC)(link)
Ну прям нельзя и... :)))
link01: (Default)

Приветик!

[personal profile] link01 2010-09-18 06:37 pm (UTC)(link)
Получилось. :)
link01: (Default)

[personal profile] link01 2010-09-18 04:53 pm (UTC)(link)
В любом случае, мне придется искать, где в браузере можно сказать AcceptLanguage: ru. Или перекомпилировать браузер.

Тут, скорее всего, надо раздавать переводы не по запросу браузера, а смотреть в DNS, откуда человек запрашивает.
link01: (Default)

[personal profile] link01 2010-09-18 05:01 pm (UTC)(link)
Угу. Читаю.
link01: (Default)

[personal profile] link01 2010-09-18 04:50 pm (UTC)(link)
http://212.75.221.62/test/
У меня выдает "Hello!" стилем h1.

Перевод средствами apache - это очень заманчиво, хотя и вносит небольшое количество ошибок (человек не сможет вставить в свою заметку слова "Help" или "Home"). Я пока слабо представляю себе, что умеет этот content negotiation, и с чем его едят. Ушел читать и думать.

Системы совместной разработки - не работал я никогда совместно, ничего не могу сказать (краснеет). :))) Думаю, что
1) все системы умеют примерно одно и то же,
2) придется использовать ту систему, которую использует команда Dreamwidth - у них, скорее всего, есть вполне рабочая служба оповещения об изменениях.
link01: (Default)

[personal profile] link01 2010-09-18 05:24 pm (UTC)(link)
Мысль: если уговорить команду Dreamwidth обрамлять каждое сообщение специальным символом, замаскированным под комментарий, например <!--tr-begin--> и <!--tr-end--> (или лучше вот так - <!--tr-begin-10552--> и <!--tr-end-10552-->, где 10552 - уникальный номер сообщения в базе), то, скорее всего, после формирования страницы и до выдачи ее пользователю apache позволит прогнать ее через дополнительный фильтр.
link01: (Default)

[personal profile] link01 2010-09-18 05:37 pm (UTC)(link)
Я имею в виду, что страницы в любом случае формируются динамически, и перенаправлением на нужный файл мы не обойдемся.

Делать полноценную систему перевода (и распределения работы переводчиков), встроенную в движок Dreamwidth, - дело крайне сложное.

Но мы можем
1) в выдаваемой движком странице отмечать строки, требующие перевода, специальными значками, замаскированными под комментарии HTML,
2) перед выдачей страницы пользователю пропускать ее через дополнительный фильтр, который ищет разметку и заменяет нужные строки на их переводы.

Таким образом, система перевода потребует минимального вмешательства в движок.
link01: (Default)

[personal profile] link01 2010-09-18 06:53 pm (UTC)(link)
ОК. Моя есть подумать. Разве что вот это -
Страницы формируются на основе постоянных шаблонов.
надо проверить. Возможно, шаблоны размечены цифрами, которые означают номер строки в базе.
link01: (Default)

[personal profile] link01 2010-09-19 11:56 am (UTC)(link)
Что удалось выяснить: LJ написан на Perl с дополнительным уровнем в виде языка BML - личного изобретения Фитцпатрика. К основным страницам с расширением .bml прилагается файл с сообщениями с расширением .bml.text; как это выглядит, можно посмотреть здесь:

http://code.livejournal.org/trac/livejournal/browser/trunk/htdocs/update.bml
http://code.livejournal.org/trac/livejournal/browser/trunk/htdocs/update.bml.text

Например, в update.bml формируется какой-то заголовок:

$$title = $ML{'.error.cantpost.title'};

Значение .error.cantpost.title берется из update.bml.text:

.error.cantpost.title=Can't Post

Perl-а я не знаю, библиотеки огромные, поэтому что делает $ML с .error.cant.post, для меня это страшная тайна. (Возможно, $ML определено в $LJHOME/cgi-bin/Apache/BML.pm, который я нашел в моей инсталляции, но который почему-то не отображается в репозиториях LJ и DW.)

После того, как вычисляется результат страницы .bml, он, вероятно, подвергается трансформациям CSS, которые и дают отображаемую страницу.

Далее. Система перевода включает в себя несколько таблиц (ml_text, ml_domain и др.) К этим таблицам определенно имеет отношение файл сообщений для английского языка

http://code.livejournal.org/trac/livejournal/browser/trunk/bin/upgrading/en.dat

Скорее всего, ключами в таблицах переводов являются строки типа ".error.cantpost.title".

Пока что больше ничего не известно. Выводы:

1) Отображение целостной страницы для переводчика представляется проблематичным.
2) Скорее всего, придется использовать фитцпатриковскую систему перевода отдельных сообщений.
3) Зато можно оценить объем перевода, исходя из размера en.dat; около 150K.
link01: (Default)

[personal profile] link01 2010-09-19 05:23 pm (UTC)(link)
Мысль (да, я знаю, что "залипание" характерно для шизофрении): проблема со строками заключается в том, что никто не знает, где какая строка хранится, где она подхватывается, преобразуется и переводится в этом многоуровневом и многокомпонентном глючеве.

Эта проблема решается тупо и в лоб: имея тестовую инсталляцию, можно найти, допустим, 50 файлов, в которых хранятся исходные строки. Составляем каталог файлов и строк, и в каждую строку дописываем ее уникальный номер. Было "Cannot Post", стало "882 Cannot Post". Помеченная строка проходит через все уровни глючева (о которых теперь можно забыть) и отображается на готовой странице. В результате мы сразу видим, к какой странице относится какое сообщение - и задача пития сакэ кувшинамипостраничного перевода сразу упрощается.

В общем, завтра я попробую заполучить себе тестовый экземпляр dreamwidth - они раздают аккаунты со свежими экземплярами, а там посмотрим.
link01: (Default)

[personal profile] link01 2010-09-20 02:31 pm (UTC)(link)
Жду, когда пришлют подтверждение и пароль. (Да, link01 мне и самому не нравится, но чего бы мне хотелось, я еще не придумал.)
link01: (Default)

[personal profile] link01 2010-09-22 01:03 pm (UTC)(link)
Дениза письмо прислала. Говорит - ты с ума сошелэто очень трудно, если хочешь этим заниматься - ответь на это письмо, и мы дадим тебе аккаунт." - Ответил. Продолжаю наблюдение.
link01: (Default)

[personal profile] link01 2010-09-18 06:59 pm (UTC)(link)
На сегодня у меня все. :)
link01: (Default)

[personal profile] link01 2010-09-18 05:57 pm (UTC)(link)
Более того, если делать систему перевода в виде внешнего фильтра, то здесь можно будет продумать и спроектировать с нуля систему распределения работы переводчиков.
temmokan: (Default)

[personal profile] temmokan 2010-09-29 12:56 am (UTC)(link)
Устроит ли gettext? Популярная вещь, файлы переводов (исходники) чисто текстовые, координировать обновление таких не слишком сложно.

Вроде бы на drupaler.ru создание переводов для Drupal (через gettext) вполне отлаженный процесс
temmokan: (Default)

[personal profile] temmokan 2010-09-29 08:37 am (UTC)(link)
Контекст нужен в любом случае. Говоря конкретно о gettext, там уже собран весь инструментал для сбора текстовых строк и создания контекста (как в смысле комментариев к тому, что надо перевести, так и в смысле namespace).
link01: (Default)

[personal profile] link01 2010-09-29 07:50 am (UTC)(link)
Очередной раунд переписки. Дениз предлагает начать длинную и обстоятельную беседу в dw_dev, я отвечаю "спасибо, посмотрим" и продолжаю просить аккаунт. :)
link01: (Default)

[personal profile] link01 2010-09-29 12:26 pm (UTC)(link)
Ну, дык. :) Только что Софи прислала мне логин/пароль, все работает, вечером приступим. Я им пообещал, что если найду чего интересного, напишу в dw_dev.