Учим symfony кодировке cp-1251

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

Не смотря на то, что в интернациональных проектах в основном используется кодировка UTF, у нас не всегда это дело приветствуется. Видимо так сложилось исторически, что большая часть рунета все-таки говорит на cp-1251…

Для того чтобы научить symfony общаться в кодировке cp-1251, необходимо слегка поправить конфиги приложения:

apps/<yourApp>/config/settings.yml

all:
.settings:
charset: cp1251

apps/<yourApp>/config/view.yml

default:
http_metas:
content-type: text/html; charset=windows-1251
metas:
language: ru

apps/<yourApp>/templates/layout.yml

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ru" lang="ru">

Тепереь убедим symfony, что БД у нас также желает общаться на cp-1251. Для этого правим config/databases.yml:

all:
propel:
class: sfPropelDatabase
param:
dsn: mysql://user:password@host/db
encoding: cp1251

В текущей версии (1.0.6)  возникает еще один казус: symfony считает, что в заголовках и мета-тэгах нужно обязательно экранировать каждый символ кириллицы… Для пользователя возможно это и не заметно – отображается у него все по-русски. А вот если заглянуть в html-код, то увидите вы там приблизительно следующее:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ru" lang="ru">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251" />
<meta name="title" content="&#1058;&#1077;&#1089;&#1090;&#1086;&#1074;&#1099;&#1077;
&#1087;&#1088;&#1086;&#1077;&#1082;&#1090;" />
<meta name="robots" content="index, follow" />
<meta name="description" content="&#1058;&#1077;&#1089;&#1090;&#1086;&#1074;&#1099;&#1077;
&#1087;&#1088;&#1086;&#1077;&#1082;&#1090;" />
<meta name="keywords" content="&#1058;&#1077;&#1089;&#1090;&#1086;&#1074;&#1099;&#1077;
&#1087;&#1088;&#1086;&#1077;&#1082;&#1090;" />
<meta name="language" content="ru" />
<title>&#1058;&#1077;&#1089;&#1090;&#1086;&#1074;&#1099;&#1077;
&#1087;&#1088;&#1086;&#1077;&#1082;&#1090;</title>

Пока официальной таблетки для этого нет, лечить приходиться это путем замены htmlentities на htmlspecialchars в следующих файлах:

lib/symfony/response/sfWebResponse.class.php

464  public function addMeta($key, $value, $replace = true, $escape = true)
465 {
466 $key = strtolower($key);
467
468 if (sfConfig::get("sf_i18n"))
469 {
470 $value = $this->getContext()->getI18N()->__($value);
471 }
472
473 if ($escape)
474 {
475 $value = htmlspecialchars($value, ENT_QUOTES, sfConfig::get("sf_charset"));
476 }
477
478 if ($replace || !$this->getParameter($key, null, "helper/asset/auto/meta"))
479 {
480 $this->setParameter($key, $value, "helper/asset/auto/meta");
481 }
482 }

lib/symfony/config/sfViewConfigHandler.class.php

218  protected function addHtmlHead($viewName = "")
219 {
220 $data = array();
221
222 foreach ($this->mergeConfigValue("http_metas", $viewName) as $httpequiv => $content)
223 {
224 $data[] = sprintf(" \$response->addHttpMeta("%s", "%s", false);", $httpequiv,
str_replace("\"", "\\\"", $content));
225 }
226
227 foreach ($this->mergeConfigValue("metas", $viewName) as $name => $content)
228 {
229 $data[] = sprintf(" \$response->addMeta("%s", "%s", false, false);", $name,
str_replace("\"", "\\\"", preg_replace("/&(?=\w+;)/", "&",
htmlspecialchars($content, ENT_QUOTES, sfConfig::get("sf_charset")))));
230 }
231
232 return implode("\n", $data)."\n";
233 }

Ну вот вроде бы и все - теперь symfony прекрасно дружит с кодировкой cp-1251.