Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

Babel и handlebars, пора бы и подружить

Anna | 16.06.2014 | нет комментариев
Думаю многим знаменит такой пакет как Babel, либо PyBabel.
чудесный пакет для локализации, тот, что основываются на gettext, как и все остальное ( по крайней мере мне знаменитое) в современном мире.

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

Должен предварительно оговориться, что у меня не было никакого ограничения в выборе спецтехнологий.
У нас в финальном счете для билда статики применяется полный комплект — ruby(compass), node(coffee,grunt,requirejs), python(бэкенд и основа каждого и каждая), шелл скрипты, в всеобщем ограничения нет никакого.

Кстати если это кому-либо увлекательно могу детально расписать о сборке билда отдельным постом, там requirejs scss все вышеперечисленное, на данный момент около 1000 файлов входящих в билд deployment на heroku и не-heroku одной кнопкой. На мой взор в целом процесс увлекателен, но не знаю на чем отменнее заострить внимание

Т.е по сути все что нужно было обнаружить — кто горазд:
a) Пройтись по образцам handlebars
b) Уметь трудиться по тому же тезису что и Babel — т.е строка это и есть ключ, а не константы, когда все хранится в отдельных файлах.
c) Подготовить из обнаруженных строк .po файл

Дальше теснее руки развязаны и вероятностей хватает.

Потратив несколько часов на поиск итог был неутешительный, такого отчего то никто не сделал.
Верить в это категорично не хотелось, но все существующее было «не то» и «не так».

Что делали и умели существующие решения?
Они с переменным триумфом выдирали регэксами строки. Не умели трудиться с ngettext, либо не умели трудиться по тезису «строка=ключ», а только константы.

Все это было нужно устранить.
Задача сразу же была разбита на пункты, так же воспользуюсь моментом и опишу всю цепочку, которую хотелось получить.

1) Определить текст перевода в образцах, правило «строка=ключ»
Так гораздо комфортней в работе, чем когда ключ=имя константы. Цена ошибки так же поменьше, максимум кто либо получит текст на английском, взамен перевода

2) Передать текст в babel, а так же номер строки
Это нужно, т.к при обновлениях babel не сумеет определить, что именно изменилось, если у него не будет номеров строк
3) Возвести из строк .po файлы, собственно это задача babel
4) Из .po файлов позже перевода сделать .json файлы и передать кому либо теснее на сторону заказчика. Конвертация — задача po2json
5) Сделать helper-ы для handlebars, как однострочные, так и блочные с помощью ngettext
Вновь таки, многообразие ради комфорта повседневного
6) Оба варианта обязаны уметь трудиться с параметрами
7) Оба варианта обязаны передать текст для перевода «на верх», кому то, кто и держит у себя те самые .json файлы
8) Данный же кто-то должен подставлять полученные из образца параметры в финальную строку.

На 8й пункт был выбран Jed, чудесная библиотека со встроенным sprintf, что сразу же решало задачу комфортной передачи параметров.

1-й пункт был ключевым, его подсмотреть так нигде и не получилось.
Длинно рассматривал регекспы и прикидывал свои — все не нравилось. Криво, неудовлетворительно, ненадежно.
Еще дольше рассматривал скомпилированный в javascript код образцов. Оттуда получить строки было довольно легко.
Но самая идея такого подхода ужасала.
К тому же — это не решало загвоздку, что необходимо знать где строка была встречена в подлинном образце.

Пришлось глядеть исходники handlebars и здесь снизошло озарение — его лексер написан с поддержкой jison и парсер jisona, использующий лексику непринужденно handlebars, зашит вовнутрь.
И вызывая способ Handlebars.parse(template) дозволено получить JSON конструкцию образца.
Казалось бы все восхитительно — но номеров строк так и нет.

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

Дальше оставалось дело техники, собрать все вместе, прикрутить к babel в качестве extractor-а
Т.е:
Функция на python(extractor) которая вызывает node.js скрипт подгружающий пропатченный handlebars.js.
Дальше данный скрипт рекурсивно проходит по структуре, собирает строки и возвращает в экстрактор в необходимом ему формате. Каждая логика babel остается постоянной. Логика извлечения строк — так же родная от handlebars.js. Все это не может не радовать.

Само собой данный пост не имел бы смысла, не будь последующих строк. Думаю, что как минимум время затраченное на искания положительного направления для экспорта строк я кому либо сэкономлю.
— pip install pybabel-hbs
— github.com/tigrawap/pybabel-hbs

Пакет устанавливается совместно с патченным handlebars, а в исходниках есть примеры реализации helper-ов (правда на coffee)
Само же применение в темплейтах получилось лично для меня совершенным, 4 хелпера на гитхабе, здесь самый «толстый», для наглядности

{{#ntrans num_to_check_aganst param_1="something" num=num_to_check_against}}
    Some text to be translated with %(param_1)s and %(num)s
{{else}}
    Some plural text to be translated with %(param_1)s and %(num)s
{{/ntrans}}

В конфиг же babel-а необходимо добавить

[hbs: path/to/project/**.hbs] 

Для работы нужно чтоб в окружении был node.js.
В планах оптимизация, чтоб node.js не запускался всякий раз для всякого файла отдельно, а один раз за все время жизни основного процесса babel. 
Это реализовано в версии 0.2.0, пока пост был на модерации.
Само собой убыстрение получилось недурное, пачка из 150 образцов стала обрабатываться за ~минуту.
До этого занимало пару минут, что было вовсе неприемлимо.
Но и минута для такого колва слишком много.

Значительно(еще в 4 раза) получилось оптимизировать за счет того, что первоначально передавал данные в node.js из python через pexpect, сейчас же (версия 0.2.1) передаю только наименование файла и теснее node.js его считывает. (здесь безусловно минус в том, что оба открывают файл по очереди)
Теперь обработка 150 файлов занимает поменьше 15 секунд. Есть еще простор для убыстрения процесса, но меня пока что устраивает.
С учетом того, что запускать Зачастую не необходимо — good enough итог.

— Этика сей басни такова, раньше чем часами писать и тестировать регулярные выражения, выискивать окольные пути для разбора какого либо языка — стоит посмотреть как он разбирает сам себя. Допустимо так проще.
В финальном счете, каждая задача решалась несколькими строчками вписанными в сам handlebars.js, а то что сегодня предлагается на просторах интернета это… как минимум не комфортно.

Источник: programmingmaster.ru
Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB