Перейти к содержанию
Форум поддержки пользователей VamShop

Новый принцип локализации VaM Shop!


support

Рекомендуемые сообщения

Со следующей версии VaM Shop я постепенно буду переходить на новый принцип локализации (проще говоря - мультиязычности) магазина.

Сначала хотел на gettext делать, но там проблема в том, что нужно компилировать языковые файлы, что очень неудобно для пользователя.

Принцип останется аналогичен gettext, но перевод будет виден сразу, без всяких компиляций. Для хранения переводов используются XML файлы.

Что есть сейчас:

1. Перевод разбросан по разным php файлам и сделан через константы.

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


<p><label for="firstname" title="{$ENTRY_FIRST_NAME_ERROR}">{#text_firstname#}</label> {$INPUT_FIRSTNAME}</p>
[/code] т.е. не понятно, где текст, где его искать и как его исправлять. При новом подходе к локализации будет хорошая читаемость кода (если не нужен будет мультиязычный магазин, можно будет сразу в шаблоне править тексты, не копаясь по файлам), например вышеуказанный код будет выглядеть так:
[code]
<p><label for="firstname" title="[[First name error]]">[[Your name:]]</label> {$INPUT_FIRSTNAME}</p>
т.е. тот код, который должен быть мультиязычным, Вы просто заключаете в [[ ]], затем просто добавляете текст, который между [[ ]] в языковой файл russian.xml и переводите. Можно также вставлять между {translate}{/translate} Можно помещать в скобки например картинки, для того что б для одного языка была одна картинка, для другого - другая. В переводимых строках можно использовать html тэги, что также иногда важно, можно например легко добавить css стиль к нужному тексту, а затем через файл стилей изменить внешний вид элемента. 1. Перевод будет храниться в XML файлах и выглядеть следующим образом:

<?xml version="1.0" encoding="utf-8" ?>
<locale lang="ru">
  <header>
      <project>VaM Shop</project>
      <create>2007-10-13 17:24</create>
      <revise>2007-10-13 19:15</revise>
      <trans>Александр Меновщиков</trans>
      <lang>Русский</lang>
  </header>
  <message>
      <id><Your name:></id>
      <string>Ваше имя:></string>
  </message>
  <message>
      <id>First name error</id>
      <string>Вы не указали имя</string>
  </message>
</locale>
[/code] 2. Так же и текст в исходных файлах, т.е. в php файлах указывается через константы, например:
[code]
$breadcrumb->add(NAVBAR_TITLE_ACCOUNT, vam_href_link(FILENAME_ACCOUNT, '', 'SSL'));
Тоже не ясно, что за константа, не видно её значение, не понятно где искать её определение. При новом подходе данный код будет выглядеть так:

$breadcrumb->add(t("Мои данные") vam_href_link(FILENAME_ACCOUNT, '', 'SSL'));
[/code]

т.е. будет видно где текст находится, опять же, перевод для этой строки будет всё в том же XML файле, а не как сейчас разделение на /lang/russian/russian.php и /lang/russian/lang_russian.conf

Ещё одна проблема с константами, это проблема переводов на другие языки и их устаревание.

Например, человек сделал перевод VaM Shop на украинский и выложил его на загрузку.

VaM Shop разививается, добавляются новые языковые файлы, новые текстовые константы.

Проходит год, человек хочет поставить украинский перевод на текущую версию...

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

При новом подходе такая ситуация также решена.

Пусть перевод будет сделан только 10%, всё равно, он будет работать без ошибок, просто не переведённые части будут выведены на языке оригинала, на английском.

Это тоже мне кажется очень важным, особенно вспоминая свой опыт сборки osC VaM и переводов сборки на украинский и иврит, которые я вынужден был убрать как раз из-за того, что они устарели и не работали на текущей версии.

Вобщем, при новом подходе будет решено три, на мой взгляд, важных проблемы:

1. Все тексты будут сконцентрированы в одном месте.

2. Будет улучшена читаемость исходного кода.

3. Текст в магазине всегда будет выведен в человеческом, читаемом виде, даже если нет перевода этого куса текста, он будет выведен на языке оригинала, т.е. на английском.

Ссылка на сообщение
Поделиться на другие сайты

Любопытно. Тема больная :)

Есть несколько "но":

1. Перевод дело неоднозначное, контекстно-зависимое. В старом (или устаревшем?) варианте это решалось просто - много разных констант с одинаковым значением, которые, в зависимости от контекста можно было переводить по разному. Особенно это ощущалось при переводе английский->русский. Хотя и при переводе в обратном направлении это тоже даст о себе знать.Самый простой пример из детства - "миру", "мир", "мира". Или "земля": earth, land, soil.

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

2. Преемственность перевода версиям. Представь себе ситуацию, когда ты в очередной версии решил таки наконец-то использовать букву "ё". Конечно предыдущий перевод работать будет. Впрочем и старый вариант тоже, можно сказать, "работал". Только в старом варианте выводились непонятные имена констант, а теперь будет выводиться непонятный текст на незнакомом языке. Так что это вовсе не решает проблему.

3. Раз уж ты заговорил про перевод. Очень будет полезен инстументарий "локализатора". Чтобы можно было сесть и перевести всё элементы (фразы). А при очередном обновлении посмотреть что у тебя лишнее, что нового. И чтобы можно было посмотреть где эти фразы используются. Посмотри как сделано в cp-erp - не пример для подражания, но и этот опыт интересен.

Ссылка на сообщение
Поделиться на другие сайты

Андрей

Да, тема больная, везде конечно есть проблемы, но мне кажется такой вариант более интересным, во всяком случае посмотрим, я сразу всё равно не смогу все сделать в новом стиле, сначала хочу вообще убрать conf файл /lang/russian/lang_russian.conf, какое-то время будет совмещаться два подхода.

cp-erp не видел, но сейчас посмотрю, спасибо.

Ссылка на сообщение
Поделиться на другие сайты

Саша!

Я ведь не отговариваю тебя. Да, этот вариант интереснее, естественнее выглядит, явно удобнее в использовании. Я просто хочу чтобы ты обратил внимание на некоторые проблемы, которые могут возникнуть при его использовании.

Извини, АпИчатка, правильное название ck-erp - http://sourceforge.net/projects/ck-erp

Ссылка на сообщение
Поделиться на другие сайты

Скачал ck-erp

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

Ссылка на сообщение
Поделиться на другие сайты

Переделал все html шаблоны по-новому принципу.

Так лучше смотрятся, сразу видно где текст, где нет.

Да и теперь в шаблонах сверху нет строки:


{config_load file="$language/lang_$language.conf" section="index"}
[/code]

Файл тоже проще смотрится без неё.

Ссылка на сообщение
Поделиться на другие сайты

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

На conf файлах 0.2-0.3 sec, на xml файлах 0.9-1.1 sec.

Вот теперь и не знаю, видимо, тот вариант, что есть сейчас (conf файлы + константы) и не самый худший вариант.

Ссылка на сообщение
Поделиться на другие сайты

Сейчас я использую вариант вот такой (сообщение Aztek) - http://www.phpinsider.com/smarty-forum/viewtopic.php?t=84&postdays=0&postorder=asc&start=0

Вот так:


function t($string, $args = array()) {
global $xml;

if(empty($xml)) {
if(file_exists("lang/{$_SESSION['language']}/{$_SESSION['language']}.xml")) {
$xml = getXmlTree("lang/{$_SESSION['language']}/{$_SESSION['language']}.xml");
} else {
return strtr($string, $args);
}
}

foreach($xml[0]['children'] as $tag) {
if($tag['tag'] == "MESSAGE") {
if($tag['children'][0]['value'] == $string) {
if($tag['children'][1]['value'] != "") {
return strtr($tag['children'][1]['value'], $args);
}
}
}
}

return strtr($string, $args);
}

function getChildren($vals, &$i) {
$children = array();

if(!isset($vals[$i]['attributes'])) {
$vals[$i]['attributes'] = "";
}

while(++$i < count($vals)) {
if(!isset($vals[$i]['attributes'])) {
$vals[$i]['attributes'] = "";
}

if(!isset($vals[$i]['value'])) {
$vals[$i]['value'] = "";
}

switch ($vals[$i]['type']) {
case 'complete':
array_push($children, array('tag' => $vals[$i]['tag'], 'attributes' => $vals[$i]['attributes'], 'value' => $vals[$i]['value']));
break;
case 'open':
array_push($children, array('tag' => $vals[$i]['tag'], 'attributes' => $vals[$i]['attributes'], 'children' => getChildren($vals, $i)));
break;
case 'close':
return $children;
break;
}
}

return $children;
}

function getXmlTree($file) {
$data = implode("", file($file));
$xml = xml_parser_create();
xml_parser_set_option($xml, XML_OPTION_SKIP_WHITE, 1);
xml_parse_into_struct($xml, $data, $vals, $index);
xml_parser_free($xml);

$tree = array();
$i = 0;
array_push($tree, array('tag' => $vals[$i]['tag'], 'attributes' => $vals[$i]['attributes'], 'children' => getChildren($vals, $i)));

return $tree;
}
[/code] Например в коде:
[code]
t("Translate text");
А файл перевода выглядит так:

<?xml version="1.0" encoding="utf-8" ?>
<locale lang="ru">
  <header>
      <project>VaM Shop</project>
      <create>2007-10-13 17:24</create>
      <revise>2007-10-13 19:15</revise>
      <trans>Александр Меновщиков</trans>
      <lang>Русский</lang>
  </header>
  <message>
      <id>Translate text</id>
      <string>Перевод</string>
  </message>
</locale>
[/code]

Правда сейчас у меня XML файл почти 90Kb весит с русским переводом, почти 2500 строк.

Вот я и думаю, стоит ли дальше использовать для перевода XML или вернуться к старым conf + константы.

Ведь, по идее, чем больше будет файл, тем медленнее будет.

Если все тексты вынести в XML, файл получится довольно большим, наверняка 300-400Kb.

Вообще я так полазил по фоурмам, почитал статьи, вроде бы такой вариант как я выше привёл и есть самый оптимальный, многие именно его советуют использовать для парсинга XML. В том же Zend Framework тоже такой способ используется.

Ссылка на сообщение
Поделиться на другие сайты

Саша,

Я особо не задумывался о скорости обработки. Тоже использовал механизм xml_parser_create.

1. Попробуй посмотри http://ru2.php.net/manual/ru/ref.simplexml.php

2. В твоём случае стоило-бы использовать кеширование (дата изменения xml-файла есть, кеш-файла тоже есть). Отпарсил xml и в кеш его.

3. xml_parser проверяет xml-файл на валидность. Нужно ли это тебе в данном случае? Может вернуться к ini-файлу?

Ссылка на сообщение
Поделиться на другие сайты

Да я наверное действительно останусь на том варианте как сейчас, т.е. conf + константы.

Это вариант про запас оставлю, на будущее, может придумаю что.

Ссылка на сообщение
Поделиться на другие сайты
×
×
  • Создать...