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

Удобный текстовый CMS WikICrowd - новая версия 0.0.16

WikiCrowd logoДавно не было новых версий, и вот свершилось :). В новой версии WikiCrowd есть поддержка тем, так что он окончательно стал полноценной CMS.

Уже даже сайт на нем один есть — Артишок (он в зачаточном состоянии, есть только одна страница, но тем не менее :).

Шаблоны темы пишутся на XSL и CSS (и, при необходимости, PHP) — они и раньше так работали, просто теперь можно легко добавлять свои собственные.

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

Парсер для OZON.ru - версия 1.8 - релиз!

Случился релиз нашего проекта парсера XML-каталогов OZON.ru :). Теперь представление товарных категорий OZON.ru на вашем сайте можно сделать за несколько минут.

Скачать парсер можно по адресу: stasdavydov.com/ozonru-parser/.

Парсер OZON.ru

На прошлой неделе мы запустили новый совместный проект с OZON.ru - парсер XML-каталогов OZON.ru для удобства работы партнеров интернет-магазинов.

Теперь создавать клоны озона стало очень просто :).

Парсер предназначен, главным образом, для автоматического представления ветки XML-каталогов товаров на любом сайте.

Локализация XSL, PHP и JavaScript из одного XML источника

Изящный способ минимальными средствами сделать полную локализацию веб-приложения.

В проекте WikiCrowd нам понадобилось сделать локализацию. Мы используем XSL для генерации UI, backend написан на PHP и еще есть много JavScript'а. И на всех уровнях нужно выводить локализованный текст.

XSL

С XSL все достаточно просто. Очень хорошее описание локализации XSL есть на сайте Студии Лебедева. Для каждого языка получается отдельный XML файл:

<locale language="English">
<message id="AccessRights" text="New user rights"/>
...

Который подключается к XSL-шаблону:

<xsl:variable name="locale" select="document(concat('locale/', $LOCALE, '.xml'))/locale"/>

Локализованную строку подставляем так:

<xsl:value-of select="$locale//message[@id='Logout']/@text"/>

Его же мы решили использовать для локализации PHP и JavaScript компонент.

PHP

В PHP мы решили сделать из локализованных строк константы в отдельном namespace (чтобы случайно не пересечься) и определили функцию для обращения к ним:

$dom = new DOMDocument();
$dom->load('xml/locale/'.LOCALE.'.xml');
$messages = $dom->getElementsByTagName('message');
for($i = 0; $i < $messages->length; $i++) {
    $message = $messages->item($i);
    define('locale\\'.       $message->getAttribute('id'), $message->getAttribute('text'));
}

function getMessage($id) {
    return str_replace('\\n', "\n", constant('locale\\'.$id));
}

Там, где нужна локализованная строка, используем вызов getMessage('Configure').

JavaScript

С JavaScript оказалось все немного сложнее, потому что понадобилось локализовать не только статические строки, но и алгоритм :). Для удобства чтения мы выводим дату в формате "изменение произошло 3 часа 25 минут назад", и простой локализацией "часов" и "минут" оказалось недостаточно, потому что в русском языке алгоритм определения окончания не такой тривиальный, как, например, в английском (1 minute, 2+ minutes).

Так в XML-файле с локализованными строками появились локализованные функции:

<function id="getDaysText" params="days"><![CDATA[return days + " day" + (days > 1 ? "s" : "");]]></function>

Из локализованных строк и функций с помощью XSL генерируется исходник на JavaScript:

<?xml version="1.0" encoding="iso-8859-1" standalone="yes"?>
<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:php="http://php.net/xsl"
  exclude-result-prefixes="">
  <xsl:output
    method="text"
    version="1.0"
    indent="no"
    encoding="utf-8"
    omit-xml-declaration="yes"
    media-type="text/plain"
    cdata-section-elements=""/>

  <xsl:template match="/">
var Locale = {
<xsl:apply-templates select="//message"/>
<xsl:apply-templates select="//function"/>
  getMessage: function(id) {
    var text = this[id];
    for(var i = 1; i <xsl:text disable-output-escaping="yes"><</xsl:text> arguments.length; i++)
      text = text.replace('%' + i, arguments[i]);
    return text;
  }
};
  </xsl:template>

  <xsl:template match="message">
    <xsl:variable name="ap">'</xsl:variable>
<xsl:value-of select="@id"/>: '<xsl:value-of select="php:functionString('jsStringReplace', @text)" disable-output-escaping="yes"/>',
</xsl:template>
  <xsl:template match="function">
<xsl:value-of select="@id"/>: function(<xsl:value-of select="@params"/>) {
<xsl:value-of select="text()" disable-output-escaping="yes"/>
},
</xsl:template>

</xsl:stylesheet>

Как вы могли заметить, мы используем в PHP-расширение, позволяющее вызывать функции PHP из XSL-шаблона. Функция jsStringReplace() заменяет некоторые символы, чтобы JavaScript-код получится правильным:

function jsStringReplace($str) {
  return strtr($str, array('\''=>'\\\'', '&lt;'=>'<', '&gt;'=>'>'));
}

Обращение к локализованной строке выглядит так: Locale.Change.

До сих пор этот вариант локализации работает отлично.