Локализация через статический файл для Друпала 5

Прислано: jason32

пн, 23/07/2007 - 20:08

Другие статьи по теме:

Итак, проснулся я в хорошем настроении и решил наконец-то облегчить жизнь тем людям, которых раздражает кол-во запросов к базе у Друпала 5 при переводе. Для Друпал 4.7 я уже такое делал, пришла очередь пятого. Итак, без патча к сожалению не обошлось, можно и не надеяться.
файл common.inc

<?php 
function t($string$args 0) {
  global 
$locale;
  
//////////////////////////////////////////////////////////////
if (function_exists('locale_static') && $locale != 'en') {
    
$string locale_static($string);
  }
  else
///////////////////////////////////////////////////////////////
  
if (function_exists('locale') && $locale != 'en') {
    
$string locale($string);
  }
  if (!
$args) {
    return 
$string;
  }
  else {
    
// Transform arguments before inserting them
    
foreach ($args as $key => $value) {
      switch (
$key[0]) {
        
// Escaped only
        
case '@':
          
$args[$key] = check_plain($value);
        break;
        
// Escaped and placeholder
        
case '%':
        default:
          
$args[$key] = theme('placeholder'$value);
          break;
        
// Pass-through
        
case '!':
      }
    }
    return 
strtr($string$args);
  }
}
?>

Добавлены строчки, которые между вот такими полосками - ///////////////////////////////////////////////////////////////.
C патчами закончили. Приаатачиваю МОДУЛЬ, никаких теперь левых конвертеров :)
PS Как вы понимаете, модуль сырой и не особенно тестированный, так что просьба сбрасывать сюда вопросы и найденные баги и фичи.

Прикрепленный файлРазмер
locale_static-5.x-1.1-dev.tgz2.48 кб

Комментарии


Настройки просмотра комментариев

Выберите нужный метод показа комментариев и нажмите "Применить"
Опубликовано restyler в пн, 23/07/2007 - 22:03.

прошу простить мне мою лень, ставить новый сайт на локалхост долго.. дальнейший перевод через веб-админку друпала доступен? Если доступен, то куда переводы сохраняются, в бд?
Привет Самаре из Ульяновска)


Опубликовано jason32 в пн, 23/07/2007 - 22:22.

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


Опубликовано kiev1 в вт, 24/07/2007 - 00:50.

Спасибо, красиво так получилось.
С алиасами так не выйдет - при большом количестве ссылок - файл будет большой.
Да, и перегенерацию перевода можно делать по крону.


Опубликовано sas@drupal.org в вт, 24/07/2007 - 05:39.

О... спасибо, давай номер VISA баксов кину!
А от чего у тебя настроение поднимается ?
Там вот грозились функцию (system back) по замене в файлах t() на rassian вариант "накрапать", там может я тебе просто настроение подниму, раз ты такой умный и умелый :) ?


Опубликовано jeminy в вт, 24/07/2007 - 05:58.

Спасибо! Спасибо! Спасибо! *убежала пробовать* :)))


Опубликовано emzi в вт, 24/07/2007 - 07:33.

Интересно, действительно ли наблюдается прирост производительности при такой конфигурации?
Дело в том, что Друпал при генерации страницы единоразово грузит строки длиной менее 75 символов в память (в статический массив). Таким образом, для большинства вызовов функции t() обращений к базе не происходит. В основном нагрузка на БД происходит при работе в админке, т.к. длинные строки используются именно там.


Опубликовано Ю.Б. в вт, 24/07/2007 - 08:09.

Только что прикрутил на недоделанный сайт.
До включения / после (для админского входа)
главная - 4026.77ms / 1514.49 ms
статья - 1284.4ms / 1177.86 ms

(Чем бы еще раз в десять ускорить? :))


Опубликовано restyler в вт, 24/07/2007 - 08:16.

переписать t() на C я бы попробовал )


Опубликовано Ю.Б. в вт, 24/07/2007 - 08:24.

> переписать t() на C я бы попробовал )

Переписать - дело не хитрое. А дальше что?


Опубликовано PVasili в вт, 24/07/2007 - 08:25.

А несколько раз в разное время проверить? А собрать среднюю статистику? Как будет вести себя на загруженном сайте?
Скорее всего в данном случае разница с очень большой погрешностью. И репрезентативность практически 0...
Как говориться: "геморрой не стоит этих свеч"...


Опубликовано Ю.Б. в вт, 24/07/2007 - 08:44.

IMHO тут в основном играет разница в скорости работы php и БД. У меня такое подозрение, что у моего хостера на 6 хостинговых серверов всего один сервер БД.


Опубликовано sas@drupal.org в вт, 24/07/2007 - 09:14.

В любом случае - самое быстрое это то, что лежит в файлах both with or without t() , значит если основной russian надо менять все там на русский, а дальше у кого что, быстрей работает, либо перевод с файлов либо из базы, но что-то есть большие априорные сомнения, даже при отсутствие репрезентативности и хорошей корреляции, что запрос на каждый t() к базе есть быстрее чем из файлов :) SQL хорошо "держит" нагрузку - график растет медленно, не первичная нагрузка для обращения даже к одной записи есть достаточно ощутимая величина, а таких запросов и так часто по поводу перевода - не такие задачи задумывалось решать с помощью SQL...


Опубликовано emzi в вт, 24/07/2007 - 09:26.

On вт, 24/07/2007 - 13:14 sas@drupal.org says:
но что-то есть большие априорные сомнения, даже при отсутствие репрезентативности и хорошей корреляции, что запрос на каждый t() к базе есть быстрее чем из файлов

так нет же там запроса к базе на каждый t(). Один раз оно грузит все мелкие строки и потом ищет их в ассоциативном массиве. Лезет в базу только если не находит, и опять-таки, помещает найденное в массив, т.е. не более одного обращения к базе для строки.

Для сравнивающих производительность: считайте отдельно анонимов и залогиненных, и учитывайте, включен ли page cache


Опубликовано PVasili в вт, 24/07/2007 - 09:31.

Могут быть и ещё и не такие дикие комбинации :) Посему - всё это хорошо только в теории и $5 решат многие проблемы с производительностью.


Опубликовано jason32 в вт, 24/07/2007 - 11:01.

sas@drupal.orgО... спасибо, давай номер VISA баксов кину!
А от чего у тебя настроение поднимается ?

Вот от таких предложений точно подымается.... Реквизиты в профиль кинул...
Ххочется услышать рационализаторские предложения, чего не хватает в модуле.....
Да, и кстати, у кого -нить работает Хук uninstall - я так и не смог его заставить заработать - глянул, он вообще не работает, у модуль aggregator вписано удаление таблиц при анинсталле - нифига не удаляет


Опубликовано sas@drupal.org в вт, 24/07/2007 - 11:52.

Один раз оно грузит все мелкие строки и потом ищет их в ассоциативном массиве.
Ух ты ... наверно не маленький массив ? А сколько интересно ему места надо, а если Вы сведущи то наверно знаете в что в этом "не маленьком" массиве и много чего еще помещается - "светлая" картина получается, да и только :)


Опубликовано emzi в вт, 24/07/2007 - 12:35.

On вт, 24/07/2007 - 15:52 sas@drupal.org says:
Ух ты ... наверно не маленький массив

в сериализованном виде в таблице cache массив занимает 215Кб :) с учетом того, что у меня грузятся строки до 90 байт включительно.
В любом случае это меньше, чем подгружать всю локализацию из файла. Насчет того, что быстрее, как уже говорил - не знаю.
Что касается помещается-не помещается, то важнее не "чтобы помещалось", а чтобы помещалось то, что чаще требуется. Только в этом случае общая производительность сможет вырасти.


Опубликовано sas@drupal.org в вт, 24/07/2007 - 13:02.

Полный перевод от Vadbars занимает - 641 Kb, значит идут выгрузки - загрузки и обращения к базе.


Опубликовано emzi в вт, 24/07/2007 - 13:22.

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


Опубликовано Ю.Б. в вт, 24/07/2007 - 13:43.

Интересно, а можно както-то так сделать, чтобы в файл выгружались только переводы front-end, а back по-прежнему из базы брался? Или вообще английским остался.


Опубликовано emzi в вт, 24/07/2007 - 13:48.

конечно можно.


Опубликовано sas@drupal.org в вт, 24/07/2007 - 13:51.

Можно почти все :)


Опубликовано Ю.Б. в вт, 24/07/2007 - 15:18.

Напильник в руки и... Или как-то можно авоматизировать?


Опубликовано jason32 в вт, 24/07/2007 - 16:28.

файл и так весит не ахти , у меня 600кб при кол-ве полей в базе более 5000 - так что не понимаю стенаний по поводу большого размера файлов. По поводу кэша - не знаю, но вроде народ мерит производительность и она выросла , потому что у наших хостеров самое уязвимое место - это именно база, а не php - на это то всегда хвата ресурсов...


Опубликовано Ю.Б. в вт, 24/07/2007 - 21:35.

> у наших хостеров самое уязвимое место - это именно база, а не php

И как будто специально в подтверждение этого тезиса мой хостер около полуночи устроил время загрузки первой страницы сайта на Друпале >50 секунд. В то же время в другом окне броузера я вносил записи в каталог другого сайта, там же хостящегося, но сделанного на самопальном движке (два запроса к базе на страницу) - всё летало.


Опубликовано jason32 в сб, 28/07/2007 - 07:18.

а как можно выложить модуль на Drupal.org ? Кто-нибудь выкладывал? Какой механизм в деталях? Выложат ли модуль в репозиторий при наличии патча ядра, кто как думает? Просветите, плиз, кто выкладывал или знает.....


Опубликовано sas@drupal.org в сб, 28/07/2007 - 08:20.

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


Опубликовано B.X в пн, 30/07/2007 - 17:28.

Включил модуль у себя на сайте. Довольно шустро стало работать по ощущениям. Конечно, тесты хорошо бы было провести, но они что-то не вызывают доверия. Спасибо за модуль, прошлым я тоже пользовался. Хорошо бы написать Readme или что-то вроде инструкции по применению.

"а как можно выложить модуль на Drupal.org ? Кто-нибудь выкладывал? Какой механизм в деталях? Выложат ли модуль в репозиторий при наличии патча ядра, кто как думает?"

Это к vadbars'у, он может выкладывать, и больше всего об этом знает...
Здесь вот вся информация: http://drupal.org/contribute/development
Сначала надо получить CVS-аккаунт: http://drupal.org/cvs-account

Модуль выложат, там много модулей делают, которым патчи необходимы. Тот же Advanced Cache.


Опубликовано Valeratal в пн, 13/08/2007 - 06:37.

Спасибо, полезная штука

Кстати, вроде в 6-м друпале обещали как то сделать по другому локализацию


Опубликовано Влад Савицкий (гостевой логин) в пн, 13/08/2007 - 20:12.

Если Друпал установлен в подпапке (не в корне сервера), то нужно заменить в locale_static.module:
$dir=$DOCUMENT_ROOT=$_SERVER['DOCUMENT_ROOT'].'/'.file_directory_path();
на
$dir=$DOCUMENT_ROOT=dirname($_SERVER["SCRIPT_FILENAME"]).'/'.file_directory_path();


Опубликовано jason32 в вт, 14/08/2007 - 09:30.

Влад Савицкий
ага, согласен, спасибо,поправил


Опубликовано Виталий (гостевой логин) в ср, 10/10/2007 - 15:10.

Вавилов Евгений, вы молодец.
Я еще не пробовал, но сама идея сделать нормальный способ хранения локализации, давно напрашивалась.
Не понимаю как друпаллеры с орга сами до этого никак не дойдут.


Опубликовано Виталий (гостевой логин) в ср, 10/10/2007 - 15:51.

думаю, описание патча или правильный patch надо в архив приложить


Опубликовано VladSavitsky в вт, 13/11/2007 - 02:15.

Axel предлагал строки прямо в код вшивать, чтобы быстрее было. Мне кажется, что написать такой скриптик, который из РО-файла пропишет в код несложно. Чем такой вариант будет уступать статичному файлу перевода?


Опубликовано axel в чт, 29/11/2007 - 20:10.

В своё время под некоторые версии 4.x делал патчи для использования библиотеки gettext.
Плюс gettext: можно без изменений использовать po-файлы переводов поставляемые с модулями. При индексации (создание mo-файлов) скорость поиска строк не хуже, чем для php-инклюдов. Минусы: нет возможности правки перевода через вебинтерфейс - только правкой po-файлов. Минусы решения предлагаемого locale_static: больше расход памяти, т.к. переводы из файла при include полностью затягиваются в память каждый раз.


Опубликовано axel в чт, 29/11/2007 - 20:12.

Я ещё раз настоятельно не рекомендую такой подход. Такие радикальные средства имеют смысл очень редко. Для повседневного применения для разгрузки БД будет идеален модуль сделанный jason32, либо адаптация gettext.


Опубликовано PVasili в чт, 29/11/2007 - 20:22.

Давно сделан и работает ;)


Опубликовано Nexor в пн, 14/01/2008 - 00:55.

Есть пара рац. предложений.

1. Сохранять в файл только те строки, которые менее N символов длиной, остальное грузить из базы. Достигая компромисса между размером файла и обращениями к базе.

2. Слегка изменить сам формат создаваемого php-файла, можно уменьшить его размер на 3-5%.
или использовать serialize/unserialize, которые работают быстрее, однако размер файла в таком случае увеличится примерно на 10%.

3. Использовать кэш. Если искомой строки нет в кэше , то она считывается из базы и добавляется в кэш-массив. Теоретически, через какое-то время активного пользования сайтом, он должен содержать самые часто используемые строки. Можно сохранять в файл именно их. Хотя в данном случае файл скорее всего будет не нужен, по-сути он и есть кэш.

В 6ке сделано так:
1. Если перевода нет, обращамся к базе и считываем все строки из кэша
2. Если их нет, считываем все строки длиной менее 75 символов и загоняем в кэш
3. Если искомой строки в массиве нет, считываем ее из базы (Здесь бы неплохо еще добавить эту строку в кэш, но в коде drupal этого не реализовано)
4. Если ее и там нет, значит вставляем ее непереведенный прототип в базу и очищаем кэш (хотя логичнее было бы добавить ее туда)

В 5ке примерно также, но есть неоптимизированные места вроде вызова locale_refresh_cache в locale

В общем логика была и есть одна - грузить в кэш все, что меньше 75 символов.

Так что грешить на множественные запросы к базе из-за модуля locale несправедливо.

В большинстве случаев запрос к переводам(к кэшу) на сессию один.
И заменять его считыванием 600-1000 килобайтным файлом, который php еще должен распарсить, мне кажется сомнительным удовольствием.

Я бы пошел по пути накопления в кэше статистически чаще используемых строк, а не строк длиной менее 75 символов, как сделано в drupal, хотя это тоже вопрос спорный.


Опубликовано Nexor в пн, 14/01/2008 - 14:03.

А вообще все уже сломано до нас.

Пакет патчей advcache кэширует потенциально ресурсоемкие места, такие как конвертация путей в синонимы и обратно, поисковые запросы, таксономию, узлы, форум, комменты.

Патч File-based caching содает кэш в файлах, вместо базы.

Модуль boost позволяет создавать статические страницы в html.

Кто-нибудь пробовал сравнивать производительность кэша на БД и файлах ?
На мой взгляд, хранение кэша в базе не целесообразно, т.к. это просто блочные данные, без всякой структуризации.


Опубликовано Nexor в вт, 15/01/2008 - 18:13.

В общем, может кого-нибудь заинтересует, идея locale_static вдохновила меня создать include
-based cache, как замену стандартному api кэша drupal.
Идея такова: все кэшируемые данные преображаются в статический php-код и сохраняются в файлах, которые затем загружаются директивой include. Т.к. php все включения держит в памяти, то ускорение заметно.
Таким образом, кэшируются переводы, таксономия, карта синонимов, меню и все что использует cache api.
пока провожу тесты
На первый взгляд скорость генерации страниц админки по сравнению с кэшем в БД возросла на порядок.


Опубликовано orbisnull в ср, 16/01/2008 - 15:36.

Думаю это будет верно при большом кол-ве оперативки и наличии eacceleratora


Опубликовано andypost@drupal.org в ср, 16/01/2008 - 16:03.

Нужно очень внимательно подходить к вопросу что кешировать!
имхо, например для ноды нужно хранить рендер тизера и тела, а коменты и ссылки хранить отдельно и генерить - они зависсят от прав доступа как и меню


Опубликовано Nexor в чт, 17/01/2008 - 22:10.

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

Загвоздка возникла в функции cache_clear_all, которая по маске ключа, очищает соответствующие записи в выбранной таблице кэшей.

Т.к. имя файла = некая функция(имя ключа, имя таблицы), то всякие маски и вилдкарды реализовать не просто. Пока, при удалении любого элемента кэша в любой таблице, очищается он весь, что сказывается на производительности.

По поводу сериализации:
В апи 6го drupal, кэш реализован более грамотно, в качестве данных ему передается не строка сериализованных данных, как в 5м, а сами данные.

И только в случае, если их тип не является строкой, происходит сериализация.

serialize/unserialize ресурсоемкие функции, особенно это заметно на массивах в 600-1000 кб.

В случае кэша на файлах, сериализация становится ненужной. В 6ке достаточно заменить cache.inc, в 5ке пришлось убрать serialize/unserialize во всем коде.

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

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


Опубликовано andypost@drupal.org в пт, 18/01/2008 - 02:22.

По поводу таблиц - есть предположение, что это сделано специально, чтобы lock table который вызывается при записи в кеш не блокировал весь кеш, а только часть, иначе это станет "бутылочным горлышком", а так как кеш например для страниц очищается достаточно часто - получение переменных и меню будут ждать, пока очистится/обновится таблица - оно и так притормаживает на большой посещаемости!


Опубликовано Nexor в пт, 18/01/2008 - 10:31.

lock table на самом деле не нужен для одиночной записи в базу. Что можно видеть на примере 6ки, там строки db_lock_table($table); db_unlock_tables(); убрали из кода.

Как написано в комментариях к cache_set, это сделано
1. для более быстрых выборок/вставок.
2. для разделения часто обновляемых и статичных данных.
3. якобы query кэш mysql работает лучше с множеством мелких статичных таблиц.

мне кажется, тут есть спорные моменты. как-то можно было по-другому. Не жесткое определение таблиц усложняет управление таким кэшом.


Опубликовано Nexor в вт, 22/01/2008 - 20:31.

Может быть найдутся желающие испытать кэш на вложениях, поэтому привожу результат.
Модифицированный файл cache.inc для drupal 5
Установка: распаковать и скопировать cache.inc поверх существующего в папке includes. Вручную создать папку files/cache.
Настройки не требует, никаких своих ключей в базе не создает.

Данные в файлах кэшируются не все подряд.
То, какие таблицы кэшировать в файлах, а какие в базе, определяют ключи массива $keys в функции filecache_enabled.
По-умолчанию в файлах кэшируются таблицы cache,cache_node, cache_path, cache_taxonomy, остальные - как обычно, в БД.

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

Пожелания и сообщения о багах приветствуются.


Опубликовано kiev1 в ср, 23/01/2008 - 13:00.

Спасибо, интересно


Опубликовано andypost@drupal.org в вт, 19/02/2008 - 09:05.

Интересная статья появилась на Lullabot

Действительно простой способ перекрыть локализацию своим методом, актуально и для 5 и 6 версий


Опубликовано jason32 в вт, 19/02/2008 - 09:54.

так такой же и реализован, просто специально усложнён... Или я что-то не понимаю.....


Новое на сайте

Ссылки партнёров