From 7a84347bbd01ab8405a41039f04ef0451d6390e4 Mon Sep 17 00:00:00 2001 From: "qiang.xue" Date: Sun, 6 Sep 2009 01:04:11 +0000 Subject: [PATCH] merge from yiidoc. --- docs/blog/ja/prototype.auth.txt | 6 +- docs/blog/ja/prototype.summary.txt | 4 +- docs/blog/pl/comment.admin.txt | 4 +- docs/blog/ru/comment.model.txt | 146 ++++++++++ docs/blog/ru/post.admin.txt | 127 +++++++++ docs/blog/ru/post.create.txt | 198 ++++++++++++++ docs/blog/ru/post.display.txt | 117 ++++++++ docs/blog/ru/post.model.txt | 200 ++++++++++++++ docs/blog/ru/prototype.scaffold.txt | 4 +- docs/guide/de/basics.component.txt | 6 +- docs/guide/de/basics.namespace.txt | 2 +- docs/guide/de/caching.overview.txt | 2 +- docs/guide/de/database.ar.txt | 10 +- docs/guide/de/extension.create.txt | 38 ++- docs/guide/de/extension.overview.txt | 3 +- docs/guide/de/extension.use.txt | 68 ++++- docs/guide/de/topics.url.txt | 6 +- docs/guide/es/basics.entry.txt | 2 +- docs/guide/pl/basics.component.txt | 4 +- docs/guide/pl/basics.namespace.txt | 5 +- docs/guide/pl/caching.data.txt | 10 +- docs/guide/pl/caching.overview.txt | 2 +- docs/guide/pl/changes.txt | 13 +- docs/guide/pl/database.ar.txt | 5 +- docs/guide/pl/extension.create.txt | 37 ++- docs/guide/pl/extension.overview.txt | 3 +- docs/guide/pl/extension.use.txt | 86 +++++- docs/guide/pl/topics.auth.txt | 6 +- docs/guide/pl/topics.url.txt | 9 +- docs/guide/pl/topics.webservice.txt | 9 +- docs/guide/pt/extension.overview.txt | 33 +++ docs/guide/pt/extension.use.txt | 238 ++++++++++++++++ docs/guide/ru/basics.component.txt | 126 ++++----- docs/guide/ru/basics.controller.txt | 6 +- docs/guide/ru/basics.namespace.txt | 38 +-- docs/guide/ru/basics.view.txt | 148 +++++----- docs/guide/ru/caching.overview.txt | 2 +- docs/guide/ru/database.ar.txt | 9 +- docs/guide/ru/database.arr.txt | 4 +- docs/guide/ru/extension.create.txt | 37 ++- docs/guide/ru/extension.overview.txt | 21 +- docs/guide/ru/extension.use.txt | 64 ++++- docs/guide/ru/topics.url.txt | 13 +- docs/guide/zh_cn/topics.security.txt | 108 ++++++++ framework/messages/bg/yii.php | 388 +++++++++++++-------------- framework/messages/de/yii.php | 2 +- framework/messages/es/yii.php | 2 +- framework/messages/ru/yii.php | 341 ++++++++++++----------- 48 files changed, 2113 insertions(+), 599 deletions(-) create mode 100644 docs/blog/ru/comment.model.txt create mode 100644 docs/blog/ru/post.admin.txt create mode 100644 docs/blog/ru/post.create.txt create mode 100644 docs/blog/ru/post.display.txt create mode 100644 docs/blog/ru/post.model.txt create mode 100644 docs/guide/pt/extension.overview.txt create mode 100644 docs/guide/pt/extension.use.txt create mode 100644 docs/guide/zh_cn/topics.security.txt diff --git a/docs/blog/ja/prototype.auth.txt b/docs/blog/ja/prototype.auth.txt index 9c60fc3b8e..cc6ea7e22c 100644 --- a/docs/blog/ja/prototype.auth.txt +++ b/docs/blog/ja/prototype.auth.txt @@ -42,11 +42,11 @@ class UserIdentity extends CUserIdentity } ~~~ -`authenticate()` メソッドにおいて、 `User` クラスを用いて `User` テーブルの行を参照しています。`User` テーブルの `username` 列は特定のユーザ名(大文字小文字の区別なし)と同一です。`User` クラスは前のセクションで `yiic` ツールによって作られたものであることを思い出してください。`User` クラスは [CActiveRecord] を継承しているため、 [ActiveRecord 機能](http://www.yiiframework.com/doc/guide/database.ar)を、オブジェクト指向に(OOP)のっとったやり方で `User` テーブルにアクセスすることができます。 +`authenticate()` メソッドにおいて、 `User` クラスを用いて `User` テーブルの行を参照しています。`User` テーブルの `username` 列は特定のユーザ名(大文字小文字の区別なし)と同一です。`User` クラスは前のセクションで `yiic` ツールによって作られたものであることを思い出してください。`User` クラスは [CActiveRecord] を継承しているため、 [ActiveRecord 機能](http://www.yiiframework.com/doc/guide/database.ar)を、オブジェクト指向(OOP)にのっとったやり方で `User` テーブルにアクセスすることができます。 `UserIdentity` クラスでは、`getId()` メソッドをオーバーライドして、`User` テーブルから見つかったユーザの `id` を返すようにしています。元の実装では、代わりにユーザ名を返すようになっていました。`username` と `id` プロパティはともにユーザセッションに保存され、コードのどこからでも `Yii::app()->user` でアクセスすることが可能です。 -> Tip|ヒント: `UserIdentity` クラスにおいて、対応するクラスファイルを読み込むことなく [CUserIdentity] を参照しています。 これは [CUserIdentity] が Yii framework のコアクラスであるためです。Yii は任意のコアクラスが最初に参照されたときに、自動的のそのクラスファイルを読み込みます。`User` クラスでも同じことが行われています。 なぜなら、 `User` クラスファイルが、`/wwwroot/blog/protected/models` ディレクトリ以下にあり、アプリケーション初期構成の書きコードで PHP の `include_path` に追加されているからです。 +> Tip|ヒント: `UserIdentity` クラスにおいて、対応するクラスファイルを読み込むことなく [CUserIdentity] を参照しています。 これは [CUserIdentity] が Yii framework のコアクラスであるためです。Yii は任意のコアクラスが最初に参照されたときに、自動的のそのクラスファイルを読み込みます。`User` クラスでも同じことが行われています。 なぜなら、 `User` クラスファイルが、`/wwwroot/blog/protected/models` ディレクトリ以下にあり、アプリケーション初期構成の下記コードで PHP の `include_path` に追加されているからです。 > > ~~~ > [php] @@ -81,4 +81,4 @@ switch($identity->errorCode) 修正後の `UserIdentity` クラスを確認するため、ブラウザで URL `http://www.example.com/blog/index.php` にアクセスし、 `User` テーブルのユーザ名とパスワードでログインしてみてください。 [ブログデモ](http://www.yiiframework.com/demos/blog/) で提供されるデータベースを利用した場合、ユーザー名 `demo` 、パスワード `demo` でアクセスできるはずです。このブログシステムにはユーザ管理機能はありません。そのため、ユーザーはウェブインターフェースで、自身のアカウントを変更したり、新しいアカウントを作成出来ません。ユーザ管理機能はブログアプリケーションの将来の機能拡張として検討されるでしょう。 -
$Id: prototype.auth.txt 702 2009-02-18 19:29:48Z qiang.xue $
\ No newline at end of file +
$Id: prototype.auth.txt 702 2009-02-18 19:29:48Z qiang.xue $
diff --git a/docs/blog/ja/prototype.summary.txt b/docs/blog/ja/prototype.summary.txt index 96502594cd..e7bec75223 100644 --- a/docs/blog/ja/prototype.summary.txt +++ b/docs/blog/ja/prototype.summary.txt @@ -11,10 +11,10 @@ 6. 記事とコメントの CRUD 基本操作ができるようコードを実装しました 7. 認証メソッドを変更し、 `User` テーブルに対してチェックするように変更しました -新しいプロジェクトでは、多くの場合、この最初の参るストーン 1 から 4 の手順をこなすことになるでしょう。 +新しいプロジェクトでは、多くの場合、この最初のマイルストーン 1 から 4 の手順をこなすことになるでしょう。 `yiic` ツールによって生成されたコードは、データベーステーブルのための完全な CRUD 操作機能を実装しますが、実際に利用する際にはしばしば、変更する必要があります。この理由から、次の2つのマイルストーンでは、初期の要求を満たすように、投稿とコメントについて発生する CRUD コードをカスタマイズします。 一般的には、最初に[モデル](http://www.yiiframework.com/doc/guide/basics.model)クラスファイルで、適切な[バリデーション](http://www.yiiframework.com/doc/guide/form.model#declaring-validation-rules)ルールを加え、[リレーションオブジェクト](http://www.yiiframework.com/doc/guide/database.arr#declaring-relationship)を宣言する変更を行います。その後、それぞれの CRUD 操作のために[コントローラアクション](http://www.yiiframework.com/doc/guide/basics.controller)と[ビュー](http://www.yiiframework.com/doc/guide/basics.view)コードを変更します。 -
$Id: prototype.summary.txt 683 2009-02-16 05:20:17Z qiang.xue $
\ No newline at end of file +
$Id: prototype.summary.txt 683 2009-02-16 05:20:17Z qiang.xue $
diff --git a/docs/blog/pl/comment.admin.txt b/docs/blog/pl/comment.admin.txt index 9da10ed033..103f994e5f 100644 --- a/docs/blog/pl/comment.admin.txt +++ b/docs/blog/pl/comment.admin.txt @@ -78,7 +78,7 @@ public function actionList() $criteria=new CDbCriteria; $criteria->condition='Comment.status='.Comment::STATUS_PENDING; - $pages=new CPagination(Comment::model()->count()); + $pages=new CPagination(Comment::model()->count($criteria)); $pages->pageSize=self::PAGE_SIZE; $pages->applyLimit($criteria); @@ -110,4 +110,4 @@ Zaleca się aby żądania GET nie modyfikowały danych na serwerze. W przeciwnym możemy mieć do czynienia z niebezpieczeństwem, że użytkownik nieumyślnie może zmienić dane po stronie serwera parokrotnie jeśli będzie odświeżał stronę kilka razy. -
$Id: comment.admin.txt 1050 2009-05-22 20:06:18Z qiang.xue $
\ No newline at end of file +
$Id: comment.admin.txt 1335 2009-08-15 20:34:36Z qiang.xue $
\ No newline at end of file diff --git a/docs/blog/ru/comment.model.txt b/docs/blog/ru/comment.model.txt new file mode 100644 index 0000000000..9faf0b8a9a --- /dev/null +++ b/docs/blog/ru/comment.model.txt @@ -0,0 +1,146 @@ +Доработка модели Comment +======================== + +Также, как и в модели `Post`, в модели `Comment` нам необходимо поправить методы +`rules()`, `relations()` и `safeAttributes()`. Кроме того, нужно задать свои +подписи некоторым полям в методе `attributeLabels()`. + + +Изменение метода `rules()` +-------------------------- + +Начнём с уточнения правил валидации, сгенерированных при помощи `yiic`. +Для комментариев будем использовать следующие правила: + +~~~ +[php] +public function rules() +{ + return array( + array('author,email,content', 'required'), + array('author,email,url','length','max'=>128), + array('email','email'), + array('url','url'), + array('verifyCode', 'captcha', 'on'=>'insert', + 'allowEmpty'=>!Yii::app()->user->isGuest), + ); +} +~~~ + +Здесь мы указываем, что атрибуты `author`, `email` и `content` обязательны. +Длина `author`, `email` и `url` не может превышать 128 символов. Атрибут `email` +должен содержать корректный email-адрес. `url` должен содержать корректный URL. +Атрибут `verifyCode` должен проверяться как код [CAPTCHA](http://ru.wikipedia.org/wiki/Captcha). + +Здесь `verifyCode` используется для хранения кода подтверждения, введённого +пользователем для того, чтобы оставить комментарий. Так как в таблице `Comment` +поля `verifyCode` нет, нам надо явно описать его как public свойство класса. +Для его валидации используется специальный валидатор `captcha`, которому +соответствует класс [CCaptchaValidator]. Более того, валидация будет проводиться +только при добавлении нового комментария(см. параметр `on`). Для аутентифицированных +пользователей валидация не требуется(см. параметра `allowEmpty`). + + +Изменение метода `safeAttributes()` +----------------------------------- + +Далее изменим метод `safeAttributes()`. Укажем атрибуты, которые могут быть +назначены пакетно. + +~~~ +[php] +public function safeAttributes() +{ + return array('author', 'email', 'url', 'content', 'verifyCode'); +} +~~~ + +Приведённый выше код также показывает, что форма комментирования будет состоять +из нескольких полей: автор, почта, URL, текст и код подтверждения. + + +Изменение метода `relations()` +------------------------------ + +При разработке портлета «последние комментарии» нам необходимо получить список +последних комментариев с информации о записях, связанных с ними. Поэтому мы +добавляем информацию об отношении в метод `relations()`: + +~~~ +[php] +public function relations() +{ + return array( + 'post'=>array(self::BELONGS_TO, 'Post', 'postId', + 'joinType'=>'INNER JOIN'), + ); +} +~~~ + +Стоит отметить, что тип join для отношения `post` — `INNER JOIN`. Сделано это +так как комментарий должен относиться к записи. + + +Изменение метода `attributeLabels()` +------------------------------------ + +Изменим метод `attributeLabels()`. Зададим свои подписи атрибутам. Метод возвращает +массив пар имя атрибута-подпись. При вызове [CHtml::activeLabel()], сначала +будет проверено, существует ли своя подпись. Если подпись не задана — будет +сгенерирована подпись по умолчанию. + +~~~ +[php] +public function attributeLabels() +{ + return array( + 'author'=>'Имя', + 'url'=>'Сайт', + 'content'=>'Комментарий', + 'verifyCode'=>'Код подтверждения', + ); +} +~~~ + +> Tip|Подсказка: Подпись по умолчанию генерируется на основе имени атрибута. + Сначала имя разбивается на слова учитывая camelCase. Затем каждый символ каждого + слова переводится в верхний регистр. К примеру, атрибуту с именем `verifyCode` + будет присвоена подпись `Verify Code`. + + +Изменение процесса сохранения +----------------------------- + +Так как мы хотим обновлять количество комментариев для каждой записи при удалении +или публикации нового комментария, нам необходимо изменять соответствующее поле +записи. Для этого переопределим методы `afterSave()` и `afterDelete()` модели +`Comment`. Также переопределим метод `beforeValidate()`. Это позволит нам +конвертировать текст из формата Markdown в HTML и выставлять время создания +комментария. + +~~~ +[php] +protected function beforeValidate($on) +{ + $parser=new CMarkdownParser; + $this->contentDisplay=$parser->safeTransform($this->content); + if($this->isNewRecord) + $this->createTime=time(); + return true; +} + +protected function afterSave() +{ + if($this->isNewRecord && $this->status==Comment::STATUS_APPROVED) + Post::model()->updateCounters(array('commentCount'=>1), "id={$this->postId}"); +} + +protected function afterDelete() +{ + if($this->status==Comment::STATUS_APPROVED) + Post::model()->updateCounters(array('commentCount'=>-1), "id={$this->postId}"); +} +~~~ + + +
$Id: comment.model.txt 814 2009-03-10 18:00:11Z qiang.xue $
diff --git a/docs/blog/ru/post.admin.txt b/docs/blog/ru/post.admin.txt new file mode 100644 index 0000000000..1ed67f6c97 --- /dev/null +++ b/docs/blog/ru/post.admin.txt @@ -0,0 +1,127 @@ +Управление записями +=================== + +Под управлением записями подразумевается отображение их списка в административном +разделе и их удаление. Этот функционал реализуется в действиях `admin` и `delete` +соответственно. Код, сгенерированный при помощи `yiic` почти не нуждается в +изменениях. Ниже мы объясним, как реализованы эти действия. + + +Отображение записей в виде таблицы +---------------------------------- + +Действие `admin` выводит все записи (включая неопубликованные) в виде таблицы, +разбитой на несколько страниц и поддерживающей сортировку по нескольким колонкам. +Далее приведён метод `actionAdmin()` контроллера `PostController`: + +~~~ +[php] +public function actionAdmin() +{ + $criteria=new CDbCriteria; + + $pages=new CPagination(Post::model()->count()); + $pages->applyLimit($criteria); + + $sort=new CSort('Post'); + $sort->defaultOrder='status ASC, createTime DESC'; + $sort->applyOrder($criteria); + + $posts=Post::model()->findAll($criteria); + + $this->render('admin',array( + 'posts'=>$posts, + 'pages'=>$pages, + 'sort'=>$sort, + )); +} +~~~ + +Данный код очень похож на используемый в `actionList()`. Главное отличие в том, +что мы используем объект [CSort] для представления информации о сортировке +(т.е. какие колонки и в каком порядке сортировать). [CSort] используется +отображением `admin` для создания ссылок в заголовке таблицы. Щелчок по такой +ссылке вызывает перезагрузку страницы с сортировкой данных по данной колонке. + +Ниже приведён код отображения `admin`: + +~~~ +[php] +

Manage Posts

+ + + + + + + + +$post): ?> + + + + + + + +
link('status'); ?>link('title'); ?>link('createTime'); ?>link('updateTime'); ?>
statusText); ?>title), + array('show','id'=>$post->id)); ?>createTime); ?>updateTime); ?>
+ +
+widget('CLinkPager',array('pages'=>$pages)); ?> +~~~ + +Понять код довольно просто. Мы делаем цикл по всем записям и каждую отображаем +в строке таблицы. В заголовке мы используем [CSort] для создания ссылок для +сортировки. В самом конце мы подключаем виджет [CLinkPager], который отображает +при необходимости постраничную разбивку. + +> Tip|Подсказка: При выводе текста мы используем [CHtml::encode()] для + кодирования сущностей HTML. Это позволяет избежать атак через [межсайтовый + скриптинг](/doc/guide/ru/topics.security). + + +Удаление записей +---------------- + +При выводе записи с использованием действия `show` мы показываем ссылку +`удалить`(`delete`) если текущий пользователь является владельцем системы. +При нажатии на ссылку запись будет удалена. Так как удаление записи вызывает +изменение данных, логично использовать для этого метод POST, поэтому для генерации +кнопки `удалить` мы воспользуемся следующим кодом: + +~~~ +[php] +array('post/delete','id'=>$post->id), + 'confirm'=>"Вы уверены, что хотите удалить запись?", +)); ?> +~~~ + +Метод [CHtml::linkButton()] генерирует ссылку, нажатие на которую вызывает отправку +методом POST формы, в которой она располагается. Здесь мы указываем, что форма +должна быть отправлена по URL, сгенерированному в соответствии с +`array('post/delete','id'=>$post->id)`. В нашем приложении это будет +`/blog/index.php?r=post/delete&id=1`. То есть действие `delete` контроллера +`PostController`. Также мы указываем, что при нажатии должен быть показан диалог +подтверждения. Это даёт пользователю шанс отказаться от удаления записи. + +Код действия `delete` говорит сам за себя, поэтому приведём его как есть: + +~~~ +[php] +public function actionDelete() +{ + if(Yii::app()->request->isPostRequest) + { + // we only allow deletion via POST request + $this->loadPost()->delete(); + $this->redirect(array('list')); + } + else + throw new CHttpException(400,'Плохой запрос какой-то…'); +} +~~~ + + +
$Id: post.admin.txt 1050 2009-05-22 20:06:18Z qiang.xue $
diff --git a/docs/blog/ru/post.create.txt b/docs/blog/ru/post.create.txt new file mode 100644 index 0000000000..2bebb1822f --- /dev/null +++ b/docs/blog/ru/post.create.txt @@ -0,0 +1,198 @@ +Создание и редактирование записей +================================= + +После того, как мы закончили с моделью `Post`, займёмся контроллером +`PostController` и его отображениями. В данном разделе мы настроим правила +доступа операций CRUD. Затем изменим код, отвечающий за `создание`(`create`) и +`обновление`(`update`). В завершение мы реализуем предварительный просмотр для +обеих операций. + + +Настройка правил доступа +------------------------ + +Первое, что мы запланировали — настройка +[прав доступа](/doc/guide/ru/topics.auth#access-control-filter). Код, +сгенерированный при помощи `yiic` нам не подойдёт. + +Необходимо изменить метод `accessRules()` в файле +`/wwwroot/blog/protected/controllers/PostController.php` следующим образом: + +~~~ +[php] +public function accessRules() +{ + return array( + array('allow', // все пользователи могут использовать действия 'list' и 'show' + 'actions'=>array('list', 'show'), + 'users'=>array('*'), + ), + array('allow', // аутентифицированные пользователи могут всё + 'users'=>array('@'), + ), + array('deny', // все остальные не могут ничего + 'users'=>array('*'), + ), + ); +} +~~~ + +Описанные выше правила разрешают всем пользователям выполнять действия +`list` и `show`. Аутентифицированным — любые действия, включая `admin`. +Всем остальным пользователям запрещено всё. Стоит отметить, что правила +применяются в порядке их описания. Первое сработавшее правило определяет, +давать доступ или не давать. К примеру, если текущий пользователь является +владельцем системы и пытается зайти на страницу создания записи, будет применено +второе правило и доступ будет разрешён. + + +Правки в действиях `create` и `update` +-------------------------------------- + +Операции `create` и `update` довольно похожи. В обоих случаях требуется +вывести HTML форму для сбора данных, вводимых пользователем. Также требуется +валидация и сохранение данных в БД. Главное отличие в том, что при `update` +форма будет заполняться данными о редактируемой записи. По этой причине `yiic` +генерирует вложенное отображение `/wwwroot/blog/protected/views/post/_form.php`, +которое включается как в отображение `create`, так и отображение `update` для +вывода HTML формы. + +Для начала изменим файл `_form.php` таким образом, чтобы форма собирала только +нужные нам данные: `title`, `content` и `status`. Для первых двух атрибутов мы +используем текстовые поля. Для `status` — выпадающий список с всеми возможными +состояниями записи: + +~~~ +[php] +statusOptions); ?> +~~~ + +> Tip|Подсказка: Для получения состояний можно вместо + `Post::model()->statusOptions` использовать `Post::model()->getStatusOptions()`. + Это возможно так как `Post` является компонентом, что даёт нам возможность + использовать [свойства](/doc/guide/ru/basics.component#component-property), + определённые как методы (геттеры). + +Далее изменим класс `Post` таким образом, чтобы он автоматически выставлял +некоторые атрибуты (такие, как `createTime` и `authorId`) непосредственно перед +сохранением записи в БД. Перекроем метод `beforeValidate()`: + +~~~ +[php] +protected function beforeValidate($on) +{ + $parser=new CMarkdownParser; + $this->contentDisplay=$parser->safeTransform($this->content); + if($this->isNewRecord) + { + $this->createTime=$this->updateTime=time(); + $this->authorId=Yii::app()->user->id; + } + else + $this->updateTime=time(); + return true; +} +~~~ + +В данном методе мы используем [CMarkdownParser] для того, чтобы конвертировать +текст в [формате Markdown](http://daringfireball.net/projects/markdown/) в HTML +и сохранить результат в `contentDisplay`. Сделано это для того, чтобы +не конвертировать текст каждый раз при отображении записи. Если запись новая, +мы выставляем время создания(`createTime`) и автора(`authorId`). Иначе мы +выставляем время обновления(`updateTime`) как текущее время. Стоит отметить, что +данный метод вызывается автоматически при вызове методов модели `validate()` +или `save()`. + +Так как мы хотим сохранить теги записи в таблицу `Tag`, нам понадобится добавить +в класс `Post` метод, который будет вызываться автоматически после сохранения +записи: + +~~~ +[php] +protected function afterSave() +{ + if(!$this->isNewRecord) + $this->dbConnection->createCommand( + 'DELETE FROM PostTag WHERE postId='.$this->id)->execute(); + + foreach($this->getTagArray() as $name) + { + if(($tag=Tag::model()->findByAttributes(array('name'=>$name)))===null) + { + $tag=new Tag(array('name'=>$name)); + $tag->save(); + } + $this->dbConnection->createCommand( + "INSERT INTO PostTag (postId, tagId) VALUES ({$this->id},{$tag->id})")->execute(); + } +} + +public function getTagArray() +{ + // break tag string into a set of tags + return array_unique( + preg_split('/\s*,\s*/',trim($this->tags),-1,PREG_SPLIT_NO_EMPTY) + ); +} +~~~ + +Сначала удаляем все записи, связанные с данной из таблицы `PostTag`. Затем +вставляем новые теги в таблицу `Tag` и добавляем соответствующую запись в `PostTag`. +Логика в данном случае немного сложная, поэтому вместо использования +[ActiveRecord](/doc/guide/ru/database.ar), мы пишем выражения SQL и выполняем +их напрямую через соединение с БД. + +> Tip|Подсказка: Хорошим тоном является отделение бизнес-логики, такой как + `beforeValidate()` и `afterSave()`, описанные выше и размещение её в моделях, + а не в контроллерах. + + +Реализация предварительного просмотра +------------------------------------- + +Кроме изменений, описанных выше, нам необходимо добавить возможность +предварительного просмотра, которая позволит нам оценить запись до её +сохранения в БД. + +Для того, чтобы добавить кнопку «предварительный просмотр» и само отображение +записи, изменим представление `_form.php`. Просмотр отображается только при +нажатии кнопки и если не произошло ошибок валидации. + +~~~ +[php] +'previewPost')); ?> +...... +hasErrors()): ?> +...отображаем предварительный просмотр модели $post... + +~~~ + +Добавим в методы `actionCreate()` и `actionUpdate()` контроллера `PostController` обработку +запроса на предварительный просмотр. Ниже приведён код `actionCreate()`, который +очень похож на то, что необходимо сделать и в `actionUpdate()`: + +~~~ +[php] +public function actionCreate() +{ + $post=new Post; + if(isset($_POST['Post'])) + { + $post->attributes=$_POST['Post']; + if(isset($_POST['previewPost'])) + $post->validate(); + else if(isset($_POST['submitPost']) && $post->save()) + $this->redirect(array('show','id'=>$post->id)); + } + $this->render('create',array('post'=>$post)); +} +~~~ + +При нажатии на кнопку «предварительный просмотр» мы вызываем `$post->validate()` +для выполнения валидации введённых данных. Если же нажали на кнопку +«сохранить»(submit) — пробуем сохранить запись при помощи `$post->save()`, +который также выполняет валидацию данных. Если сохранение прошло успешно, +(не возникли ошибки валидации и данные сохранились в БД без ошибки) — +перенаправляем пользователя на страницу только что созданной записи. + +
$Id: post.create.txt 766 2009-02-27 17:22:13Z qiang.xue $
diff --git a/docs/blog/ru/post.display.txt b/docs/blog/ru/post.display.txt new file mode 100644 index 0000000000..14c79e5649 --- /dev/null +++ b/docs/blog/ru/post.display.txt @@ -0,0 +1,117 @@ +Отображение записей +=================== + +В нашем приложении запись может показываться как отдельно, так и среди других +записей. Первое реализуется действием `show`, второе — `list`. В данном разделе +мы изменим оба действия для достижения первоначальных требований. + + +Изменение действия `show` +------------------------- + +Действие `show` реализовано в методе `actionShow()` контроллера `PostController`. +Отдаваемый пользователю HTML генерируется из отображения `show`, находящегося +в файле `/wwwroot/blog/protected/views/post/show.php`. + +Ниже приведён код действия `show` контроллера `PostController`: + +~~~ +[php] +public function actionShow() +{ + $this->render('show',array( + 'post'=>$this->loadPost(), + )); +} + +private $_post; + +protected function loadPost($id=null) +{ + if($this->_post===null) + { + if($id!==null || isset($_GET['id'])) + $this->_post=Post::model()->findbyPk($id!==null ? $id : $_GET['id']); + if($this->_post===null || Yii::app()->user->isGuest && + $this->_post->status!=Post::STATUS_PUBLISHED) + throw new CHttpException(404,'Кто здесь?!'); + } + return $this->_post; +} +~~~ + +Наши изменения в основном коснулись метода `loadPost()`. В нём мы получаем запись +из таблицы `Post`, используя параметр `id` из GET. Если запись не найдена или +не опубликована (при этом пользователь является гостем) — показываем ошибку 404. +Иначе возвращаем объект записи методу `actionShow()`, который передаёт объект +отображению `show`. + +> Tip|Подсказка: Yii перехватывает исключения HTTP (экземпляры класса + [CHttpException]) и отображает их на страницах ошибок с соответствующими + предопределёнными шаблонами. Процесс изменения этих шаблонов в вашем приложении + будет описан в конце данного руководства. + +Изменения в отображении `show` в основном затрагивают форматирование и стили +отображения записи, поэтому на нём мы останавливаться не будем. + + +Изменение действия `list` +------------------------- + +Как и в действии `show`, мы будем изменять действие `list` в двух местах: +метод `actionList()` контроллера `PostController` и отображение +`/wwwroot/blog/protected/views/post/list.php`. Требуется добавить поддержку +отображения записей с определённым тегом. + +Ниже приведён изменённый метод `actionList()` контроллера `PostController`: + +~~~ +[php] +public function actionList() +{ + $criteria=new CDbCriteria; + $criteria->condition='status='.Post::STATUS_PUBLISHED; + $criteria->order='createTime DESC'; + + $withOption=array('author'); + if(!empty($_GET['tag'])) + { + $withOption['tagFilter']['params'][':tag']=$_GET['tag']; + $postCount=Post::model()->with($withOption)->count($criteria); + } + else + $postCount=Post::model()->count($criteria); + + $pages=new CPagination($postCount); + $pages->applyLimit($criteria); + + $posts=Post::model()->with($withOption)->findAll($criteria); + + $this->render('list',array( + 'posts'=>$posts, + 'pages'=>$pages, + )); +} +~~~ + +Мы создаём критерий запроса, ограничивающий отображаемые записи опубликованными и +сортирующий их в обратном порядке в соответствии с временем их создания. После +этого мы подсчитываем общее число записей, подходящих под критерий. Это количество +используется в компоненте постраничной разбивки для определения общего количества +страниц, необходимых для отображения записей. Далее мы получаем из БД сами данные +и передаём их в отображение `list`. + +Стоит отметить, что при заданном GET параметре `tag` мы делаем запрос используя +`tagFilter` и передавая ему значение параметра. Включение `tagFilter` в запрос +позволит нам сделать единственный JOIN запрос для получения записей с определённым +тегом. Без этого Yii разобьёт запрос на два (для достижения большей эффективности) +и вернёт неправильный результат. + +Отображению `list` передаются два параметра: `$posts` и `$pages`. Первый является +списком записей, которые необходимо отобразить. Второй содержит информацию для +постраничной разбивки (такую, как общее кол-во страниц или текущая страница). +Отображение `list` содержит [виджет](/doc/guide/ru/basics.view#widget) постраничной +разметки, который автоматически делает разбивку на несколько страниц, если +записей достаточно много. + +
$Id: post.display.txt 1200 2009-07-04 17:46:06Z qiang.xue $
diff --git a/docs/blog/ru/post.model.txt b/docs/blog/ru/post.model.txt new file mode 100644 index 0000000000..c81ac5cb41 --- /dev/null +++ b/docs/blog/ru/post.model.txt @@ -0,0 +1,200 @@ +Доработка модели Post +===================== + +Модель `Post`, сгенерированная при помощи `yiic`, нуждается в следующих изменениях: + + - метод `rules()`: задаёт правила валидации атрибутов модели; + - метод `relations()`: задаёт отношения с связанными объектами; + - метод `safeAttributes()`: определяет, какие атрибуты могут быть назначены + пакетно (в основном используется при передаче пользовательского ввода в модель); + +> Info|Информация: [Модель](/doc/guide/ru/basics.model) состоит из набора атрибутов, + каждый из которых ассоциируется с соответствующим полем в таблице БД. + Атрибуты могут быть описаны явно как переменные класса, либо использоваться без + какого-либо описания. + + +Изменение метода `rules()` +-------------------------- + +В первую очередь необходимо определить правила валидации, которые позволят +убедится в том, что данные, полученные от пользователя корректны до их вставки в БД. +К примеру, атрибут `status` модели `Post` должен быть целым числом, равным 0, 1 или 2. +Консоль `yiic` генерирует правила валидации для каждой модели. При этом +используется структура БД, поэтому некоторые правила могу оказаться неточными. + +Основываясь на анализе требований, изменим метод `rules()` следующим образом: + +~~~ +[php] +public function rules() +{ + return array( + array('title, content, status', 'required'), + array('title', 'length', 'max'=>128), + array('status', 'in', 'range'=>array(0, 1, 2)), + array('tags', 'match', 'pattern'=>'/^[\w\s,]+$/', + 'message'=>'В тегах можно использовать только буквы.'), + ); +} +~~~ + +В коде выше мы определили, что атрибуты `title`, `content` и `status` являются +обязательными для заполнения. Длина `title` не должна превышать 128 символов. +Значение `status` может быть 0 (черновик), 1 (опубликовано) или 2 (в архиве). +В `tags` могут содержаться только буквы, запятые и пробелы. Все остальные +атрибуты (`id`, `createTime` и т.д.) не будут валидироваться т.к. их значения +пользователь не задаёт. + +После того, как мы сделали описанные изменения, мы можем зайти на страницу +создания записи и проверить, что новые правила валидации работают. + +> Info|Информация: Правила валидации используются при вызове методов модели +[validate()|CModel::validate] или [save()|CActiveRecord::save]. За более +подробной информацией о правилах валидации обратитесь к +[полному руководству](/doc/guide/ru/form.model#declaring-validation-rules). + + +Изменение метода `safeAttributes()` +----------------------------------- + +Перейдём к изменению метода `safeAttributes()`. Нам необходимо указать, какие +атрибуты могут быть назначены пакетно. При передаче пользовательского ввода +модели мы часто используем пакетное назначение для того, чтобы упростить код: + +~~~ +[php] +$post->attributes=$_POST['Post']; +~~~ + +Без использования данной возможности нам бы пришлось написать: + +~~~ +[php] +$post->title=$_POST['Post']['title']; +$post->content=$_POST['Post']['content']; +// и т.д. +~~~ + +Несмотря на то, что пакетное назначение удобно, существует потенциальная опасность, +если злоумышленник передаст значение, которое не должно было сохраняться или +должно было изменяться исключительно разработчиком. К примеру, `id` записи, +которую мы обновляем, не должен изменяться. + +Для того, чтобы этого не допустить, мы должны разрешить пакетное назначение +только атрибутам `title`, `content`, `status` и `tags`. Для этого необходимо +реализовать метод `safeAttributes()` следующим образом: + +~~~ +[php] +public function safeAttributes() +{ + return array('title', 'content', 'status', 'tags'); +} +~~~ + +> Tip|Подсказка: Самый простой способ узнать, какие атрибуты должны быть перечислены + в safeAttributes — ознакомиться с HTML-формой, которая используется для ввода + данных. Те атрибуты, которые присутствуют в форме, могут считаться безопасными. + Так как эти атрибуты заполняются пользователем, чаще всего для них определены + правила валидации. + + +Изменение метода `relations()` +------------------------------ + +Далее укажем в методе `relations()` связанные с записью объекты. После этого мы +сможем использовать [реляционную ActiveRecord (RAR)](/doc/guide/ru/database.arr) +для получения связанных с записью данных, таких как информацию об авторе и +комментарии. Сложные SQL запросы с JOIN в этом случае не потребуются. + +Определим метод `relations()`: + +~~~ +[php] +public function relations() +{ + return array( + 'author'=>array(self::BELONGS_TO, 'User', 'authorId'), + 'comments'=>array(self::HAS_MANY, 'Comment', 'postId', + 'order'=>'??.createTime'), + 'tagFilter'=>array(self::MANY_MANY, 'Tag', 'PostTag(postId, tagId)', + 'together'=>true, + 'joinType'=>'INNER JOIN', + 'condition'=>'??.name=:tag'), + ); +} +~~~ + +Выше описано следующее: + + * Запись принадлежит автору(`User`), связь с которым устанавливается на основе + поля записи `authorId`; + * Запись может содержать много комментариев(`Comment`), связь с которыми + устанавливается на основе поля комменария `postId`. Комментарии сортируются по + времени их создания. + +Отношение `tagFilter` немного сложнее. Оно используется для явного пересечения +таблицы `Post` с таблицей `Tag` и выбора только строк определённым тегом. Мы +покажем, как использовать это отношение, когда будем реализовывать отображение +записей. + +Задав описанные выше отношения, мы можем получить информацию об авторе и +комментариям к записи следующим образом: + +~~~ +[php] +$author=$post->author; +echo $author->username; + +$comments=$post->comments; +foreach($comments as $comment) + echo $comment->content; +~~~ + +Более подробно использование и определение отношений описано в +[полном руководстве](/doc/guide/ru/database.arr). + +Текстовое представление для статуса +----------------------------------- + +Так как статус записи хранится в БД в виде числа, нам необходимо получить его +текстовое представление для отображения пользователям. Для этого дополним +модель `Post`: + +~~~ +[php] +class Post extends CActiveRecord +{ + const STATUS_DRAFT=0; + const STATUS_PUBLISHED=1; + const STATUS_ARCHIVED=2; + + ...... + + public function getStatusOptions() + { + return array( + self::STATUS_DRAFT=>'Черновик', + self::STATUS_PUBLISHED=>'Опубликовано', + self::STATUS_ARCHIVED=>'В архиве', + ); + } + + public function getStatusText() + { + $options=$this->statusOptions; + return isset($options[$this->status]) ? $options[$this->status] + : "unknown ({$this->status})"; + } +} +~~~ + +В приведённом коде мы определили константы класса для представления возможных +значений статуса. Эти константы используются для улучшения читаемости кода. +Был определён метод `getStatusOptions()`, возвращающий соответствия +числовых значений статуса и его текстовых представлений. Также мы реализовали +метод `getStatusText()`, который возвращает текстовое представление статуса +текущей записи. + +
$Id: post.model.txt 814 2009-03-10 18:00:11Z qiang.xue $
diff --git a/docs/blog/ru/prototype.scaffold.txt b/docs/blog/ru/prototype.scaffold.txt index 42b757af84..940fb566f2 100644 --- a/docs/blog/ru/prototype.scaffold.txt +++ b/docs/blog/ru/prototype.scaffold.txt @@ -103,7 +103,7 @@ http://www.example.com/blog/index.php?r=comment `create` и `update`. * Подобный набор файлов представлений также сгенерирован для комментариев. -Чтобы лучше понять, как используются файлы выше, рассмотрим, что происходи +Чтобы лучше понять, как используются файлы выше, рассмотрим, что происходит при отображении списка постов: 1. [Входной скрипт](basics.entry) выполняется Web-сервером и инициализирует экземпляр @@ -114,4 +114,4 @@ http://www.example.com/blog/index.php?r=comment 5. Метод `actionList()` генерирует представление `list` с данными записей. -
$Id: prototype.scaffold.txt 683 2009-02-16 05:20:17Z qiang.xue $
\ No newline at end of file +
$Id: prototype.scaffold.txt 683 2009-02-16 05:20:17Z qiang.xue $
diff --git a/docs/guide/de/basics.component.txt b/docs/guide/de/basics.component.txt index cbe82761c5..5964850f7d 100644 --- a/docs/guide/de/basics.component.txt +++ b/docs/guide/de/basics.component.txt @@ -143,12 +143,12 @@ aufrufen. ~~~ [php] // $name ist ein eindeutiger Bezeichner des Behaviors in der Komponente -$behavior->attach($name,$component); +$component->attachBehavior($name,$behavior); // test() ist eine Methode des Behaviors $component->test(); ~~~ -Auf ein verbundenes Verhalten kann wie auf eine normale Eigenschaft der Komponente +Auf ein verbundenes Behavior kann wie auf eine normale Eigenschaft der Komponente zugegriffen weden. Wenn zum Beispiel ein Behavior namens `tree` mit einer Komponente verbunden ist, erhalten wir eine Referenz auf dieses Behavior wie folgt erhalten: @@ -183,4 +183,4 @@ es eine oder mehrere seiner Methoden mit einigen Events der Komponente verbinden. Dadurch kann kann das Behavior den normalen Prozessablauf innerhalb einer Komponente überwachen oder verändern. -
$Id: basics.component.txt 683 2009-02-16 05:20:17Z qiang.xue $
+
$Id: basics.component.txt 1328 2009-08-15 18:45:51Z qiang.xue $
diff --git a/docs/guide/de/basics.namespace.txt b/docs/guide/de/basics.namespace.txt index ef19569c72..1e2e5ef603 100644 --- a/docs/guide/de/basics.namespace.txt +++ b/docs/guide/de/basics.namespace.txt @@ -82,4 +82,4 @@ Ein Pfad-Alias kollidiert nicht mit einem Namespace. > reserviert bleibt und benutzerdefinierte Klassen mit anderen Präfixen > versehen werden. -
$Id: basics.namespace.txt 1299 2009-08-07 00:25:55Z qiang.xue $
+
$Id: basics.namespace.txt 1310 2009-08-08 16:03:46Z qiang.xue $
diff --git a/docs/guide/de/caching.overview.txt b/docs/guide/de/caching.overview.txt index 985759b64a..e5450640bd 100644 --- a/docs/guide/de/caching.overview.txt +++ b/docs/guide/de/caching.overview.txt @@ -94,4 +94,4 @@ Die Existenz von gecachten Daten wird nicht garantiert, selbst wenn diese niemals verfallen. Benutzern Sie daher einen Cache niemals als beständigen Speicher (speichern Sie dort also z.B. keine Sessiondaten). -
$Id: caching.overview.txt 1084 2009-06-02 17:35:38Z qiang.xue $
+
$Id: caching.overview.txt 1309 2009-08-08 12:37:23Z qiang.xue $
diff --git a/docs/guide/de/database.ar.txt b/docs/guide/de/database.ar.txt index 52761efca9..efff873817 100644 --- a/docs/guide/de/database.ar.txt +++ b/docs/guide/de/database.ar.txt @@ -515,6 +515,10 @@ eine AR-Instanz gelöscht wird/wurde. - [afterConstruct|CActiveRecord::afterConstruct]: diese wird aufgerufen, nachdem eine AR-Instanz mit dem `new` Operator erstellt wurde. + - [beforeFind|CActiveRecord::beforeFind]: diese wird aufgerufen, bevor eine +Abfrage (z.B. `find()`, `findAll()`) mit einem AR-Finder durchgeführt wird. +Diese Methode steht seit Version 1.0.9 zur Verfügung. + - [afterFind|CActiveRecord::afterFind]: diese wird aufgerufen, nachdem eine AR-Instanz als Ergebnis einer Abfrage erstellt wurde. @@ -680,4 +684,8 @@ Abfragekriterium. [php] $contents=Content::model()->findAll(); ~~~ -
$Id: database.ar.txt 1167 2009-06-23 02:56:45Z qiang.xue $
+ +Beachten Sie, dass der Standardbereich nur für +`SELECT`-Abfragen verwendet wird. Bei `INSERT`-, `UPDATE`- und +`DELETE`-Statements wird er ignoriert. +
$Id: database.ar.txt 1391 2009-09-04 19:46:04Z qiang.xue $
diff --git a/docs/guide/de/extension.create.txt b/docs/guide/de/extension.create.txt index 4b50f3589f..b4c6b8fcb2 100644 --- a/docs/guide/de/extension.create.txt +++ b/docs/guide/de/extension.create.txt @@ -47,6 +47,42 @@ ersten mal auf sie zugegriffen wird. Falls eine Anwendungskomponente unmittelbar nach der Anwendungsinstanz erzeugt werden muss, sollte der Anwender sie in der Eigenschaft [CApplication::preload] aufführen. +Behavior +-------- + +Um ein Behavior zu erstellen, muss das [IBehavior]-Interface implementiert +werden. Bequemerweise enthält Yii bereits die Basisklasse [CBehavior], +die dieses Interface implementiert und einige weitere Komfortfunktionen +anbietet. Kindklassen müssen hauptsächlich die Methoden implementieren, die +sie ihren Komponenten bereitstellen wollen. + +Wenn man Behaviors für [CModel] und [CActiveRecord] entwickeln möchte, kann +man auch [CModelBehavior] bzw. [CActiveRecordBehavior] erweitern. Diese +Basisklassen bieten zusätzliche, an [CModel] bzw. [CActiveRecord] angepasste +Features. Die [CActiveRecordBehavior]-Klasse implementiert z.B. eine Reihe von +Methoden, die auf die Events im Lebenszyklus eines ActiveRecord-Objekts +reagieren. Eine Kindklasse kann diese Methoden überschreiben, um so +angepassten Code einzuschleusen, der im Lebenszyklus eines AR ausgeführt wird. + +Der folgende Code zeigt ein Beispiel eines ActiveRecord-Behaviors. Wenn dieses +Behavior an ein AR-Objekt angebunden und dann dessen `save()`-Methode +aufgerufen wird, setzt es automatisch die Attribute `create_time` und +`update_time` auf den aktuellen Zeitstempel. + +[code] +class TimestampBehavior extends CActiveRecordBehavior +{ + public function beforeSave($event) + { + if($this->owner->isNewRecord) + $this->owner->create_time=time(); + else + $this->owner->update_time=time(); + } +} +[/code] + + Widget ------ @@ -228,4 +264,4 @@ Eine allgemeine Erweiterungskomponente zu entwickeln, bedeutet, eine Klasse zu schreiben. Auch hier gilt: Die Komponente sollte in sich geschlossen sein, so dass sie von anderen Entwicklern einfach eingesetzt werden kann. -
$Id: extension.create.txt 749 2009-02-26 02:11:31Z qiang.xue $
+
$Id: extension.create.txt 1392 2009-09-04 20:39:11Z qiang.xue $
diff --git a/docs/guide/de/extension.overview.txt b/docs/guide/de/extension.overview.txt index 76853e7298..707c4e4692 100644 --- a/docs/guide/de/extension.overview.txt +++ b/docs/guide/de/extension.overview.txt @@ -12,6 +12,7 @@ Eine Erweiterung dient normalerweise einem bestimmten Zweck. In Yii-Begriffen kann sie wie folgt klassifiziert werden: * [Anwendungskomponente](/doc/guide/basics.application#application-component) + * [Behavior](/doc/guide/basics.component#component-behavior) * [Widget](/doc/guide/basics.view#widget) * [Controller](/doc/guide/basics.controller) * [Action](/doc/guide/basics.controller#action) @@ -35,4 +36,4 @@ Kategorien fällt. Tatsächlich ist Yii so konzipiert, dass fast sein gesamter Code erweitert oder angepasst werden kann, um individuellen Bedürfnissen gerecht zu werden. -
$Id: extension.overview.txt 759 2009-02-26 21:23:53Z qiang.xue $
+
$Id: extension.overview.txt 1392 2009-09-04 20:39:11Z qiang.xue $
diff --git a/docs/guide/de/extension.use.txt b/docs/guide/de/extension.use.txt index dcd3fe3234..04a5a4e1eb 100644 --- a/docs/guide/de/extension.use.txt +++ b/docs/guide/de/extension.use.txt @@ -59,6 +59,72 @@ erst dann, wenn zum ersten mal auf sie zugegriffen wird), außer, wir führen sie in der Eigenschaft `preload` auf. +Behavior +-------- + +[Behavior](/doc/guide/basics.component#component-behavior) können mit allen +möglichen Komponenten verwendet werden. Dies erfordert zwei Schritte. Zunächst +wird das Behavior an die gewünschte Komponente angebunden. Danach wird eine +Behaviormethode über die Komponente aufgerufen. Zum Beispiel: + +~~~ +[php] +// $name ist ein eindeutiger Bezeichner des Behaviors in der Komponente +$component->attachBehavior($name,$behavior); +// test() ist eine Methode des Behaviors +$component->test(); +~~~ + +Statt über die `attachBehavior`-Methode wird ein Behavior in der Regel meist +per Konfiguration an eine Komponente angebunden. Der folgende +[Konfigurationsausschnitt](/doc/guide/basics.application#application-configuration) +würde z.B. ein Behavior an eine [Applikationskomponente](/doc/guide/basics.application#application-component) +anbinden: + +~~~ +[php] +return array( + 'components'=>array( + 'db'=>array( + 'class'=>'CDbConnection', + 'behaviors'=>array( + 'xyz'=>array( + 'class'=>'ext.xyz.XyzBehavior', + 'property1'=>'value1', + 'property2'=>'value2', + ), + ), + ), + //.... + ), +); +~~~ + +Dieser Code bindet das Behavoir `xyz` and die `db`-Komponente der Anwendung +an. Dies wird durch die in [CApplicationComponent] definierte Eigenschaft `behaviors` +ermöglicht. Indem wir in dieser Eigenschaft eine Liste von +Behaviorkonfigurationen übergeben, bindet die Komponente die entsprechenden +Behaviors beim Initialisieren an. + +Bei [CController]-, [CFormModel]- and [CActiveModel]-Klassen, die in der Regel +erweitert werden, werden Behavior durch Überschreiben der +`behaviors()`-Methode angebunden. Zum Beispiel: + +~~~ +[php] +public function behaviors() +{ + return array( + 'xyz'=>array( + 'class'=>'ext.xyz.XyzBehavior', + 'property1'=>'value1', + 'property2'=>'value2', + ), + ); +} + + +~~~ Widget ------ @@ -248,4 +314,4 @@ Eigenschaften konfigurieren oder ihre Methoden aufrufen. Möglicherweise möchten wir sie auch erweitern, um neue Kindklassen zu erstellen. -
$Id: extension.use.txt 1299 2009-08-07 00:25:55Z qiang.xue $
+
$Id: extension.use.txt 1392 2009-09-04 20:39:11Z qiang.xue $
diff --git a/docs/guide/de/topics.url.txt b/docs/guide/de/topics.url.txt index 82221a06c9..03600ac4a2 100644 --- a/docs/guide/de/topics.url.txt +++ b/docs/guide/de/topics.url.txt @@ -132,7 +132,9 @@ GET-Parameter erscheinen innerhalb der Regel in diesem Format: wobei `ParamName` den Namen des GET-Parameters angibt und das optionale `ParamMuster` einen regulären Ausdruck, der für das Auffinden dieses -Parameters verwendet werden soll. Beim Erstellen einer URL werden diese +Parameters verwendet werden soll. Falls `ParamMuster` nicht angegeben wird, +bedeutet das, dass alle Zeichen außer dem Schrägstrich `/` als Parameterwert +verwendet werden. Beim Erstellen einer URL werden diese Parameterplatzhalter durch die entsprechenden Parameterwerte ersetzt. Und beim Auswerten einer URL werden die entsprechenden GET-Parameter mit den gefundenen Werten gefüllt. @@ -269,4 +271,4 @@ einer statischen Webseite aus. Setzen Sie dazu einfach die gewünschte Endung über die Eigenschaft [urlSuffix|CUrlManager::urlSuffix] der [urlManager|CWebApplication::urlManager]-Komponente. -
$Id: topics.url.txt 1273 2009-07-22 21:32:23Z qiang.xue $
+
$Id: topics.url.txt 1342 2009-08-17 14:55:58Z qiang.xue $
diff --git a/docs/guide/es/basics.entry.txt b/docs/guide/es/basics.entry.txt index e393a81405..64b99df2c6 100644 --- a/docs/guide/es/basics.entry.txt +++ b/docs/guide/es/basics.entry.txt @@ -19,7 +19,7 @@ $configFile='path/to/config/file.php'; Yii::createWebApplication($configFile)->run(); ~~~ -Este script incluyer el archivo principal de Yii framework `yii.php`, crea la instancia +Este script incluye el archivo principal de Yii framework `yii.php`, crea la instancia de aplicación web con la configuración especificada y inicia su ejecución. Modo Debug diff --git a/docs/guide/pl/basics.component.txt b/docs/guide/pl/basics.component.txt index 12b2693151..c4cc496ed8 100644 --- a/docs/guide/pl/basics.component.txt +++ b/docs/guide/pl/basics.component.txt @@ -131,7 +131,7 @@ poprzez komponent: ~~~ [php] // $name jednoznacznie identyfikuje zdarzenie komponentu -$behavior->attach($name,$component); +$component->attachBehavior($name,$behavior); // test() jest metodą $behavior $component->test(); ~~~ @@ -170,4 +170,4 @@ potężne. Zachowanie, dołączane do komponentu, może dołączyć pewną czę do pewnych zdarzeń komponentu. W taki sposób, zdarzeniu udostępnia się możliwość obserwowania lub zmiany zwykłego przepływu wykonywania czynności komponentu. -
$Id: basics.component.txt 683 2009-02-16 05:20:17Z qiang.xue $
\ No newline at end of file +
$Id: basics.component.txt 1328 2009-08-15 18:45:51Z qiang.xue $
\ No newline at end of file diff --git a/docs/guide/pl/basics.namespace.txt b/docs/guide/pl/basics.namespace.txt index a2270ccabe..8ed02cd7a7 100644 --- a/docs/guide/pl/basics.namespace.txt +++ b/docs/guide/pl/basics.namespace.txt @@ -15,10 +15,11 @@ możemy zdefiniować nowe aliasy ścieżek. Dla wygody, Yii predefiniuje domyśl - `system`: wskazuje katalog framework Yii; - `application`: wskazuje do [folderu głównego aplikacji](/doc/guide/basics.application#application-base-directory); - `webroot`: wskazuje na katalog zawierający plik [skryptu wejściowego](/doc/guide/basics.entry). Alias ten został wprowadzony wraz z wersją 1.0.3. + - `ext`: wskazuje na katalog zawierający wszystkie [rozszerzenia](/doc/guide/extension.overview) stron trzecich. Alias ten został wprowadzony wraz z wersją 1.0.8. Dodatkowo, jeśli aplikacja używa [modułów](/doc/guide/basics.module) alias główny jest również predefiniowany dla każdego ID modułu i wskazuje na -katalog główny odpowiedniego modułu. Funkcjonalność ta jest dostępna od version 1.0.3. +katalog główny odpowiedniego modułu. Funkcjonalność ta jest dostępna od wersji 1.0.3. Używając [YiiBase::getPathOfAlias()] alias może zostać przetłumaczony na odpowiadającą mu ścieżkę. Na przykład `system.web.CController` będzie przetłumaczony jako `yii/framework/web/CController`. @@ -64,4 +65,4 @@ od klas zdefiniowanych przez użytkownika. Zaleca się, aby prefix 'C' był zare wyłącznie dla frameworku Yii a klasy użytkownika były poprzedzone prefiksem składającym się z innej litery. -
$Id: basics.namespace.txt 766 2009-02-27 17:22:13Z qiang.xue $
\ No newline at end of file +
$Id: basics.namespace.txt 1315 2009-08-09 04:07:35Z qiang.xue $
\ No newline at end of file diff --git a/docs/guide/pl/caching.data.txt b/docs/guide/pl/caching.data.txt index 06e4ad286a..baf28d2d73 100644 --- a/docs/guide/pl/caching.data.txt +++ b/docs/guide/pl/caching.data.txt @@ -47,6 +47,14 @@ unikalne spośród wszystkich innych zmiennych, które mogą być zbuforowane w NIE WYMAGA się, aby ID było unikalne pomiędzy aplikacjami, ponieważ komponent cache jest wystarczająco zmyślny aby rozróżniać te same ID w różnych aplikacjach. + +Część systemów buforowania pamięci, takich jak MemCache, APC, wspierają pobieranie +wartości wielokrotnie zbuforowanych w trybie wsadowym, co może objawić się zredukowaniem +obciążenia związanego z pobieraniem zbuforowanych danych. Poczynając od wersji 1.0.8 +nowa metoda [mget()|CCache::mget] została dostarczona w celu wykorzystania tej właściwości. +W przypadku kiedy używany system buforowania nie wspiera tej funkcjonalności +metoda [mget()|CCache::mget] zasymuluje ją. + Aby usunąć zbuforowaną wartość z bufora wywołujemy metodę [delete()|CCache::delete]; aby usunąć całą wartość z bufora wołamy [flush()|CCache::flush]. Bądź bardzo ostrożny podczas wywoływania [flush()|CCache::flush] ponieważ usuwa ono dane, które zostały @@ -104,4 +112,4 @@ Poniżej znajduje się podsumowanie dostępnych zależności buforowania: - [CExpressionDependency]: zależność jest zmieniona jeśli zmieni się rezultat określonego wyrażenia PHP. Klasa ta jest dostępna od wersji 1.0.4. -
$Id: caching.data.txt 891 2009-03-25 15:20:56Z qiang.xue $
\ No newline at end of file +
$Id: caching.data.txt 1290 2009-08-06 16:13:11Z qiang.xue $
\ No newline at end of file diff --git a/docs/guide/pl/caching.overview.txt b/docs/guide/pl/caching.overview.txt index 96f2420152..2de5f925d5 100644 --- a/docs/guide/pl/caching.overview.txt +++ b/docs/guide/pl/caching.overview.txt @@ -81,4 +81,4 @@ W następnych dwóch podpunktach opowiemy jak używać buforowania na tych pozio buforowanych danych nawet jeśli nie wygasa. Dlatego też, nie używaj buforu jako miejsca stałego składowania (np. nie używaj buforu do przechowywania danych sesji). -
$Id: caching.overview.txt 1084 2009-06-02 17:35:38Z qiang.xue $
\ No newline at end of file +
$Id: caching.overview.txt 1309 2009-08-08 12:37:23Z qiang.xue $
\ No newline at end of file diff --git a/docs/guide/pl/changes.txt b/docs/guide/pl/changes.txt index 587477f1f0..57f1215dea 100644 --- a/docs/guide/pl/changes.txt +++ b/docs/guide/pl/changes.txt @@ -3,6 +3,17 @@ Nowe funkcjonalności Ta strona zawiera streszczenie najważniejszych nowych funkcji wprowadzonych w każdym wydaniu Yii. +Wersja 1.0.8 +------------- + + * Dodano wsparcie dla pobierania wartości wielokrotnie buforowanych w jendym czasie + - [Buforowanie danych](/doc/guide/caching.data) + + * Wprowadzono nowy, domyślny alias dla ścieżki głównej `ext`, który wskazuje na katalog zawierający wszystkie + rozszerzenia stron trzecich. + - [Używanie rozszerzeń](/doc/guide/extension.use) + + Wersja 1.0.7 ------------- @@ -49,4 +60,4 @@ Wersja 1.0.5 * Rozszerzono[CUrlManager] o wsparcie dla parametryzacji reguł dla części URL zawierającej trasę. Zobacz: - [Parametryzacja trasy w regułach URL](/doc/guide/topics.url#parameterizing-routes) -
$Id: changes.txt 1168 2009-06-23 14:52:48Z qiang.xue $
\ No newline at end of file +
$Id: changes.txt 1299 2009-08-07 00:25:55Z qiang.xue $
\ No newline at end of file diff --git a/docs/guide/pl/database.ar.txt b/docs/guide/pl/database.ar.txt index e2d4d5c13b..6f71e72747 100644 --- a/docs/guide/pl/database.ar.txt +++ b/docs/guide/pl/database.ar.txt @@ -477,6 +477,9 @@ w klasach potomnych aby dostosować ich sterowanie kolejnością zadań (ang. wo - [afterConstruct|CActiveRecord::afterConstruct]: jest wywoływana dla każdej instancji AR utworzonej za pomocą operatora `new`. + - [beforeFind|CActiveRecord::beforeFind]: jest wywoływana zanim instancja AR zostanie + użyta do wykonania zapytania (np. `find()`, `findAll()`). Dostępna od wersji 1.0.9. + - [afterFind|CActiveRecord::afterFind]: jest wywoływana dla każdej instancji AR utworzonej jako rezultat zapytania. @@ -627,4 +630,4 @@ $contents=Content::model()->findAll(); Zauważ, że domyślne nazwane podzbiory mają zastosowanie tylko dla zapytań `SELECT`. Są one ignorowane dla zapytań `INSERT`, `UPDATE` oraz `DELETE`. -
$Id: database.ar.txt 1167 2009-06-23 02:56:45Z qiang.xue $
\ No newline at end of file +
$Id: database.ar.txt 1391 2009-09-04 19:46:04Z qiang.xue $owner->isNewRecord) + $this->owner->create_time=time(); + else + $this->owner->update_time=time(); + } +} +[/code] + + Widżet ------ @@ -208,4 +243,4 @@ Tworzenie rozszerzeń generycznych komponentów to jak pianie klasy. Również t komponent powinien być samowystarczalny, tak że może ony być w łatwy sposób wykorzystany przez innych deweloperów. -
$Id: extension.create.txt 749 2009-02-26 02:11:31Z qiang.xue $
\ No newline at end of file +
$Id: extension.create.txt 1392 2009-09-04 20:39:11Z qiang.xue $
\ No newline at end of file diff --git a/docs/guide/pl/extension.overview.txt b/docs/guide/pl/extension.overview.txt index 64e612b690..ae458d306e 100644 --- a/docs/guide/pl/extension.overview.txt +++ b/docs/guide/pl/extension.overview.txt @@ -11,6 +11,7 @@ Rozszerzenie zazwyczaj służy jednemu celu. W nazewnictwie Yii, można to sklas następująco: * [komponent aplikacji](/doc/guide/basics.application#application-component) + * [zachowanie](/doc/guide/basics.component#component-behavior) * [widżet](/doc/guide/basics.view#widget) * [kontroler](/doc/guide/basics.controller) * [akcja](/doc/guide/basics.controller#action) @@ -30,4 +31,4 @@ Rozszerzenie może być również komponentem, który nie należy do żadnej z w wymienionych kategorii. W rzeczy samej, framework Yii jest starannie zaprojektowany, tak że niemal każda jego część kodu może być rozszerzona oraz dostosowana do indywidualnych potrzeb. -
$Id: extension.overview.txt 759 2009-02-26 21:23:53Z qiang.xue $
\ No newline at end of file +
$Id: extension.overview.txt 1392 2009-09-04 20:39:11Z qiang.xue $
\ No newline at end of file diff --git a/docs/guide/pl/extension.use.txt b/docs/guide/pl/extension.use.txt index e50e4aa6dc..ecbcf49e09 100644 --- a/docs/guide/pl/extension.use.txt +++ b/docs/guide/pl/extension.use.txt @@ -12,13 +12,15 @@ Używanie rozszerzeń zwykle obejmuje następujące trzy kroki: Każde rozszerzenie posiada nazwę, która jednoznacznie identyfikuje ją spośród wszystkich rozszerzeń. Biorąc pod uwagę rozszerzenie nazwane `xyz`, możemy zawsze -użyć aliasu ścieżki `application.extensions.xyz` by zlokalizować jego główny katalog, +użyć aliasu ścieżki `ext.xyz` by zlokalizować jego główny katalog, który zawiera wszystkie pliki z `xyz`. + Różne rozszerzenia posiadają różne wymagania dotyczące importowania, konfiguracji oraz użycia. W dalszej części, podsumujemy najczęściej używane scenariusze dotyczące rozszerzeń, zgodnie z kategoriami opisanymi w [przeglądzie](/doc/guide/extension.overview). + Komponent aplikacji --------------------- @@ -32,7 +34,7 @@ return array( // 'preload'=>array('xyz',...), 'components'=>array( 'xyz'=>array( - 'class'=>'application.extensions.xyz.XyzClass', + 'class'=>'ext.xyz.XyzClass', 'property1'=>'value1', 'property2'=>'value2', ), @@ -45,6 +47,68 @@ Następnie możemy uzyskać dostęp do komponentu w każdym miejscu używając ` Komponent zostanie leniwie stworzony (to znaczy, będzie utworzony wtedy gdy zażądamy dostępu do niego po raz pierwszy) chyba, że wpiszemy go do właściwości `preload`. +Zachowanie (ang. Behavior) +-------- + +[Zachowanie](/doc/guide/basics.component#component-behavior) może być używane w różnego +rodzaju komponentach. Jego użycie obejmuje dwa kroki. W Pierwszym kroku zachowanie jest +dołączane do komponentu docelowego. W drugim kroku metoda zachowania wywoływana jest +poprzez komponent docelowy. Na przykład: + +~~~ +[php] +// $name jednoznacznie identyfikuje zachowanie w komponencie +$component->attachBehavior($name,$behavior); +// test() jest metodą zachowanie $behavior +$component->test(); +~~~ + +Częściej zachowanie jest dołączane do komponentu w sposób configurowalny zamiast wywoływania +metody `attachBehavior`. Na przykład aby dołączyć zachowanie do +[komponentu aplikacji](/doc/guide/basics.application#application-component), powinniśmy +użyć następującej [konfiguracji aplikacji](/doc/guide/basics.application#application-configuration): + +~~~ +[php] +return array( + 'components'=>array( + 'db'=>array( + 'class'=>'CDbConnection', + 'behaviors'=>array( + 'xyz'=>array( + 'class'=>'ext.xyz.XyzBehavior', + 'property1'=>'value1', + 'property2'=>'value2', + ), + ), + ), + //.... + ), +); +~~~ + +Powyższy kod załącza zachowanie `xyz` do komponentu aplikacji `db`. Możemy tak +zrobić ze wzdlędu na to, że [CApplicationComponent] definiuje właściwość o nazwie `behaviors`. +Poprzez przypisanie tej właściwości listy zawierającej konfigurację zachowań, komponent +dołączy odpowiednie zachowanie w momencie inicjalizacji komponentu. + +Dla klas [CController], [CFormModel] oraz [CActiveModel], które zazwyczaj są rozszerzane +dołączanie zachowań odbywa się poprzez nadpisanie ich metody `behaviors()`. Na przykład: + +~~~ +[php] +public function behaviors() +{ + return array( + 'xyz'=>array( + 'class'=>'ext.xyz.XyzBehavior', + 'property1'=>'value1', + 'property2'=>'value2', + ), + ); +} +~~~ + Widżet ------ @@ -56,12 +120,12 @@ w następujący sposób, ~~~ [php] // widżet który nie potrzebuje zawartości -widget('application.extensions.xyz.XyzClass', array( +widget('ext.xyz.XyzClass', array( 'property1'=>'value1', 'property2'=>'value2')); ?> // widżet, który posiada zawartość -beginWidget('application.extensions.xyz.XyzClass', array( +beginWidget('ext.xyz.XyzClass', array( 'property1'=>'value1', 'property2'=>'value2')); ?> @@ -86,7 +150,7 @@ class TestController extends CController { return array( 'xyz'=>array( - 'class'=>'application.extensions.xyz.XyzClass', + 'class'=>'ext.xyz.XyzClass', 'property1'=>'value1', 'property2'=>'value2', ), @@ -115,7 +179,7 @@ class TestController extends CController { return array( array( - 'application.extensions.xyz.XyzClass', + 'ext.xyz.XyzClass', 'property1'=>'value1', 'property2'=>'value2', ), @@ -141,7 +205,7 @@ aplikacji](/doc/guide/basics.application#application-configuration): return array( 'controllerMap'=>array( 'xyz'=>array( - 'class'=>'application.extensions.xyz.XyzClass', + 'class'=>'ext.xyz.XyzClass', 'property1'=>'value1', 'property2'=>'value2', ), @@ -169,7 +233,7 @@ class MyModel extends CActiveRecord // lub CFormModel return array( array( 'attr1, attr2', - 'application.extensions.xyz.XyzClass', + 'ext.xyz.XyzClass', 'property1'=>'value1', 'property2'=>'value2', ), @@ -191,7 +255,7 @@ dla aplikacji konsolowej: return array( 'commandMap'=>array( 'xyz'=>array( - 'class'=>'application.extensions.xyz.XyzClass', + 'class'=>'ext.xyz.XyzClass', 'property1'=>'value1', 'property2'=>'value2', ), @@ -221,11 +285,11 @@ Aby używać generycznych [komponentów](/doc/guide/basics.component), najpierw dołączyć ich plik klasy używając ~~~ -Yii::import('application.extensions.xyz.XyzClass'); +Yii::import('ext.xyz.XyzClass'); ~~~ Następnie, możemy utworzyć instancję tej klasy, skonfigurować jej właściwości oraz zawołać jej metody. Możemy również rozszerzyć go do tworzenia nowych klas potomnych. -
$Id: extension.use.txt 749 2009-02-26 02:11:31Z qiang.xue $
\ No newline at end of file +
$Id: extension.use.txt 1392 2009-09-04 20:39:11Z qiang.xue $
\ No newline at end of file diff --git a/docs/guide/pl/topics.auth.txt b/docs/guide/pl/topics.auth.txt index 24ce0302c1..4f0769b325 100644 --- a/docs/guide/pl/topics.auth.txt +++ b/docs/guide/pl/topics.auth.txt @@ -466,8 +466,8 @@ ich uzywać do tworzenia hierarchii autoryzacji w sposób bardziej intuicyjny. ### Używanie reguł biznesowych Podczas definiowania hierarchii autoryzacji, możemy powiązać rolę, zadanie lub operację z tak zwaną *reguły biznesowej* (ang. business rule). -Możemy również powiązać regułę biznesową podczas przypisywania roli do użytkownika. Reguła biznesowa jest fragmentem kodu PHP (dokładniej rzecz ujmując wyrażeniem PHP ), -które jest wykonywane podczas sprawdzania dostępności. Zwracana przez kod wartość jest używana do określenia, czy rola lub przypisanie ma zastosowanie dla aktualnego +Możemy również powiązać regułę biznesową podczas przypisywania roli do użytkownika. Reguła biznesowa jest fragmentem kodu PHP, +który jest wykonywany podczas sprawdzania dostępności. Zwracana przez kod wartość jest używana do określenia, czy rola lub przypisanie ma zastosowanie dla aktualnego użytkownika. W powyższym przykładzie, powiązaliśmy regułe bizesową z zadaniem `updateOwnPost` task. W regule biznesowej po prostu sprawdzamy czy ID aktualnego użytkownika jest identyczne jak to określone przez ID autora postu. Informacja o poście w ablicy `$params` jest dostarczana przez programistę podczas sprawdzania dostępności. @@ -550,4 +550,4 @@ $bizRule='return Yii::app()->user->isGuest;'; $auth->createRole('guest','gość', $bizRule); ~~~ -
$Id: topics.auth.txt 1275 2009-07-23 20:05:48Z qiang.xue $
\ No newline at end of file +
$Id: topics.auth.txt 1282 2009-08-01 01:07:54Z qiang.xue $
\ No newline at end of file diff --git a/docs/guide/pl/topics.url.txt b/docs/guide/pl/topics.url.txt index d4df18db5d..0ebe962727 100644 --- a/docs/guide/pl/topics.url.txt +++ b/docs/guide/pl/topics.url.txt @@ -136,9 +136,10 @@ się we wzorcu reguły jako specjalne znaczniki o formacie: gdzie `ParamName` określa nazwe parametru GET, a opcjonalny `ParamPattern` definiuje wyrażenie regularne, które ma być używane do badania dopasowania wartości parametru -GET. Gdy tworzymy adres URL znaczniki tych parametrów zostaną zastąpione odpowiednimi -wartościami parametru GET; podczas przetwarzania adresu URL odpowiednie parametry GET -zostaną wypełnione wynikami tego przetwarzania. +GET. W przypadku gdy pominięto `ParamPattern`, oznacza to, że parametr ten może zawierać +wszystkie znaki poza ukośnikiem `/`. Gdy tworzymy adres URL znaczniki tych parametrów +zostaną zastąpione odpowiednimi wartościami parametru GET; podczas przetwarzania +adresu URL odpowiednie parametry GET zostaną wypełnione wynikami tego przetwarzania. Pokażmy kilka przykładów by wyjaśnić jak działają reguły adresów URL. Zakładamy, że nasz zestaw reguł składa się z trzech, widocznych poniżej: @@ -266,4 +267,4 @@ do strony statycznej. Aby to zrobić po prostu skonfiguruj komponent [urlManager|CWebApplication::urlManager] ustawiając jego właściwość [urlSuffix|CUrlManager::urlSuffix] na taki sufiks, jaki ci odpowiada. -
$Id: topics.url.txt 1273 2009-07-22 21:32:23Z qiang.xue $
\ No newline at end of file +
$Id: topics.url.txt 1342 2009-08-17 14:55:58Z qiang.xue $
\ No newline at end of file diff --git a/docs/guide/pl/topics.webservice.txt b/docs/guide/pl/topics.webservice.txt index ac8ab37fb3..9e380d6dec 100644 --- a/docs/guide/pl/topics.webservice.txt +++ b/docs/guide/pl/topics.webservice.txt @@ -175,6 +175,13 @@ class Post extends CActiveRecord * @soap */ public $title; + + + public static function model($className=__CLASS__) + { + return parent::model($className); + } + } ~~~ @@ -216,4 +223,4 @@ wywoływanej poprzez [CWebService::methodName]. Może wtedy zwrócić wartość false, jeżeli z pewnych powodów zdalna metoda nie powinna być wywoływana (np. nieautoryzowany dostęp). -
$Id: topics.webservice.txt 265 2008-11-23 12:30:16Z weizhuo $
\ No newline at end of file +
$Id: topics.webservice.txt 1308 2009-08-07 23:43:11Z qiang.xue $
\ No newline at end of file diff --git a/docs/guide/pt/extension.overview.txt b/docs/guide/pt/extension.overview.txt new file mode 100644 index 0000000000..1817772978 --- /dev/null +++ b/docs/guide/pt/extension.overview.txt @@ -0,0 +1,33 @@ +Visão Geral +=========== + +Estender o Yii é uma atividade comum durante o desenvolvimento. Por exemplo, +quando você cria um novo controle, você estende o framework herdando da classe +[CController]; quando você cria um novo widget, você está estendendo a classe [CWidget] +ou outro widget existente. Se o código estendido for projetado para a reutilização +por terceiros, o chamamos de *extensão*. + +Uma extensão normalmente atende a um único propósito. No Yii, ela pode ser classificada +como: + + * [componente da aplicação](/doc/guide/basics.application#application-component) + * [widget](/doc/guide/basics.view#widget) + * [controle](/doc/guide/basics.controller) + * [ação](/doc/guide/basics.controller#action) + * [filtro](/doc/guide/basics.controller#filter) + * [comando de console](/doc/guide/topics.console) + * validador: um validador é uma classe que estende de [CValidator]. + * helper: um helper é uma classe somente com métodos estáticos. São como funções + globais, que utilizam o nome da classe como seu namespace. + * [módulo](/doc/guide/basics.module): um módulo é uma unidade de software independente, + que contém [modelos](/doc/guide/basics.model), [visões](/doc/guide/basics.view), + [controles](/doc/guide/basics.controller) e outros componentes de suporte. Em + diversos aspectos, um módulo lembra uma [aplicação](/doc/guide/basics.application). + A principal diferença é que um módulo está dentro de uma aplicação. Por exemplo, + podemos ter um módulo com funcionalidades para o gerenciamento de usuários. + +Uma extensão também pode ser um componente que não se encaixe em nenhuma das categorias +acima. Na verdade, o Yii é cuidadosamente projetado de forma que, praticamente +todo seu código possa ser estendido e customizado para atender necessidades individuais. + +
$Id: extension.overview.txt 755 2009-02-26 17:46:33Z qiang.xue $
diff --git a/docs/guide/pt/extension.use.txt b/docs/guide/pt/extension.use.txt new file mode 100644 index 0000000000..a78044432e --- /dev/null +++ b/docs/guide/pt/extension.use.txt @@ -0,0 +1,238 @@ +Usando Extensões +================ + +A utilização de uma extensão normalmente envolve os seguintes passos: + + 1. Faça o download da extensão no [repositório](http://www.yiiframework.com/extensions/) + do Yii. + 2. Descompacte a extensão no diretório `extensions/xyz`, dentro do + [diretório base da aplicação](/doc/guide/basics.application#application-base-directory), + onde `xyz` é o nome da extensão. + 3. Importe, configure e utilize a extensão. + +Cada extensão tem um nome que a identifica unicamente. Dada uma extensão chamada +`xyz`, podemos sempre utilizar o path alias `ext.xyz` para localizar seu diretório +base, que contém todos os arquivos de `xyz`. + +> Note|Nota: O path alias `ext` está disponível a partir da versão 1.0.8. Nas versões +anteriores, precisávamos utilizar `application.extensions` para nos referir ao diretório +base das extensões. Nos exemplos a seguir, vamos assumir que `ext` está definido, +Caso você utilize a versão 1.0.7, ou anterior, substitua o path alias por +`aaplication.extensions`. + +Extensões diferentes tem requisitos diferentes para importação, configuração e +utilização. Abaixo, resumimos os tipos mais comuns de utilização de extensões, +de acordo com as categorias descritas na [visão geral](/doc/guide/extensions.overview). + +Componente de Aplicação +----------------------- + +Para utilizar um [componente de aplicação](/doc/guide/basics.application#application-component), +primeiro precisamos alterar a [configuração da aplicação](/doc/guide/basics.application#application-configuration) +adicionando uma nova entrada na propriedade `components`, como no código abaixo: + +~~~ +[php] +return array( + // 'preload'=>array('xyz',...), + 'components'=>array( + 'xyz'=>array( + 'class'=>'ext.xyz.XyzClass', + 'property1'=>'value1', + 'property2'=>'value2', + ), + // configurações de outros componentes + ), +); +~~~ + +Dessa forma, podemos acessar o componente em qualquer lugar utilizando +`Yii::app()->xyz`. O componente será criado somente quando for acessado pela primeira vez, +a não ser que ele tenha sido adicionado na propriedade `preload`. + +Widget +------ + +[Widgets](/doc/guide/basics.view#widget) são utilizados principalmente nas +[visões](/doc/guide/basics.view). Dada uma classe widget, chamada `XyzClass`, +pertencente a extensão `xyz`, podemos utiliza-la da seguinte maneira: + +~~~ +[php] +// um widget que não precisa de conteúdo para seu corpo +widget('ext.xyz.XyzClass', array( + 'property1'=>'value1', + 'property2'=>'value2')); ?> + +// um widget que precisa de conteúdo para o seu corpo +beginWidget('ext.xyz.XyzClass', array( + 'property1'=>'value1', + 'property2'=>'value2')); ?> + +...conteúdo do corpo do widget... + +endWidget(); ?> +~~~ + +Ação +---- + +[Ações](/doc/guide/basics.controller#action) são utilizadas por um +[controle](/doc/guide/basics.controller) para responder à uma requisição específica +do usuário. Dada a classe da ação `XyzClass`, pertencente a extensão `xyz`, +podemos utiliza-la sobrescrevendo o método [CController::actions] na classe de +nosso controle: + +~~~ +[php] +class TestController extends CController +{ + public function actions() + { + return array( + 'xyz'=>array( + 'class'=>'ext.xyz.XyzClass', + 'property1'=>'value1', + 'property2'=>'value2', + ), + // outras ações + ); + } +} +~~~ + +Dessa forma, a ação pode ser acessada através da [rota](/doc/guide/basics.controller#route) +`test/xyz`. + +Filtro +------ + +[Filtros](/doc/guide/basics.controller#filter) também são utilizados por um +[controle](/doc/guide/basics.controller). Basicamente eles pré e pós processam a requisição +do usuário manuseada por uma [ação](/doc/guide/basics.controller#action). +Dada a classe do filtro `XyzClass`, pertencente a extensão `xyz`, podemos utiliza-la +sobrescrevendo o método [CController::filters], na classe de nosso controle. + +~~~ +[php] +class TestController extends CController +{ + public function filters() + { + return array( + array( + 'ext.xyz.XyzClass', + 'property1'=>'value1', + 'property2'=>'value2', + ), + // outros filtros + ); + } +} +~~~ + +No exemplo acima, podemos utilizar no primeiro elemento do +vetor os operadores `+` e `-`, para limitar as ações onde o filtro será aplicado. +Para mais detalhes, veja a documentação da classe [CController]. + +Controle +-------- + +Um [controle](/doc/guide/basics.controller), fornece um conjunto de ações que podem +ser requisitadas pelos usuários. Para utilizar um extensão de um controle, precisamos +configurar a propriedade [CWebApplication::controllerMap] na +[configuração da aplicação](/doc/guide/basics.application#application-configuration): + +~~~ +[php] +return array( + 'controllerMap'=>array( + 'xyz'=>array( + 'class'=>'ext.xyz.XyzClass', + 'property1'=>'value1', + 'property2'=>'value2', + ), + // outros controles + ), +); +~~~ + +Dessa forma, uma ação `a` no controle pode ser acessada pela +[rota](/doc/guide/basics.controller#route) `xyz/a`. + + +Validador +--------- + +Um validador é utilizado principalmente na classe de um [modelo](/doc/guide/basics.model) +(que estenda de [CFormModel] ou [CActiveRecord]). Dada a classe de um validador +chamada `XyzClass`, pertencente a extensão `xyz`, podemos utiliza-la sobrescrevendo +o método [CModel::rules] na classe de nosso modelo: + +~~~ +[php] +class MyModel extends CActiveRecord // ou CFormModel +{ + public function rules() + { + return array( + array( + 'attr1, attr2', + 'ext.xyz.XyzClass', + 'property1'=>'value1', + 'property2'=>'value2', + ), + // outras regras de validação + ); + } +} +~~~ + +Comando de Console +------------------ + +Uma extensão do tipo [comando de console](/doc/guide/topics.console), normalmente +é utilizada para adicionar comandos à ferramenta `yiic`. Dado um comando de console +`XyzClass`, pertencente à extensão `xyz`, podemos utiliza-lo o adicionando +nas configurações da aplicação de console: + +~~~ +[php] +return array( + 'commandMap'=>array( + 'xyz'=>array( + 'class'=>'ext.xyz.XyzClass', + 'property1'=>'value1', + 'property2'=>'value2', + ), + // outros comandos + ), +); +~~~ + +Dessa forma, podemos utilizar o comando `xyz` na ferramenta `yiic`. + +> Note|Nota: Uma aplicação de console normalmente utiliza um arquivo de configuração +diferente do utilizado pela aplicação web. Se uma aplicação foi criada utilizando o +comando `yiic webapp`, o arquivo de configurações para o console estará em `protected/config/console.php`, +enquanto o arquivo de configuração para a aplicação web estará em `protected/config/main.php`. + +Módulo +------ + +Para utilizar módulos, por favor, veja a seção sobre [módulos](/doc/guide/basics.module#using-module). + +Componente Genérico +------------------- + +Para utilizar um [componente](/doc/guide/basics.component), primeiro precisamos +incluir seu arquivo de classe, utilizando: + +~~~ +Yii::import('ext.xyz.XyzClass'); +~~~ + +Feito isso, podemos criar uma instância dessa classe, configurar suas propriedades e +chamar seus métodos. Podemos também estendê-lo para criar novas classes. + +
$Id: extension.use.txt 1299 2009-08-07 00:25:55Z qiang.xue $
diff --git a/docs/guide/ru/basics.component.txt b/docs/guide/ru/basics.component.txt index 8bb0deda21..c87444ef6f 100644 --- a/docs/guide/ru/basics.component.txt +++ b/docs/guide/ru/basics.component.txt @@ -1,4 +1,4 @@ -Компонент +Компонент ========= Yii-приложения состоят из компонентов–объектов, созданных согласно спецификациям. Компонент (component) - это экземпляр класса [CComponent] или производного от него. @@ -20,17 +20,17 @@ $component->enableCaching=true; // устанавливаем значение Более гибкий вариант - определить методы, считывающие (getter) и записывающие (setter) это свойство, например: -~~~ -[php] -public function getTextWidth() -{ - return $this->_textWidth; -} - -public function setTextWidth($value) -{ - $this->_textWidth=$value; -} +~~~ +[php] +public function getTextWidth() +{ + return $this->_textWidth; +} + +public function setTextWidth($value) +{ + $this->_textWidth=$value; +} ~~~ В приведенном коде определено свойство `textWidth` (имя нечувствительно к регистру), доступное для записи. @@ -59,20 +59,20 @@ public function setTextWidth($value) Подобно именам свойств, заданных через методы чтения и записи, имена событий не чувствительны к регистру. Следующий код задает событие `onClicked`: -~~~ -[php] -public function onClicked($event) -{ - $this->raiseEvent('onClicked', $event); -} -~~~ +~~~ +[php] +public function onClicked($event) +{ + $this->raiseEvent('onClicked', $event); +} +~~~ где `$event` - это экземпляр класса [CEvent] или производного от него, представляющего параметр события. К событию можно подключить обработчик, как показано ниже: -~~~ -[php] -$component->onClicked=$callback; +~~~ +[php] +$component->onClicked=$callback; ~~~ где `$callback` - это корректный callback-вызов PHP (см. @@ -81,12 +81,12 @@ PHP-функцию call_user_func). Это может быть либо глоб Обработчик события должен быть определен следующим образом: -~~~ -[php] -function methodName($event) -{ - ...... -} +~~~ +[php] +function methodName($event) +{ + ...... +} ~~~ где `$event` - это параметр, описывающий событие (происходит из вызова `raiseEvent()`). @@ -102,9 +102,9 @@ function methodName($event) Если в обработчике необходимо предотвратить вызов последующих обработчиков, необходимо установить [$event->handled|CEvent::handled] в `true`. - -Поведение компонента ------------------- + +Поведение компонента +------------------ Начиная с версии 1.0.2, к компоненту была добавлена поддержка [примесей (mixin)](http://ru.wikipedia.org/wiki/Mixin) и теперь к компоненту можно прикрепить одно или несколько поведений. *Поведение* - это объект, чьи методы могут быть "унаследованы" @@ -114,48 +114,48 @@ function methodName($event) Поведение классов должно реализовывать интерфейс [IBehavior]. Большинство поведений могут быть созданы путем расширения базового класса [CBehavior]. В случае, если поведение необходимо прикрепить к [модели](/doc/guide/basics.model), его можно создать на основе класса [CModelBehavior] или класса [CActiveRecordBehavior], который реализует дополнительные, -специфические для модели возможности. +специфические для модели возможности. Чтобы воспользоваться поведением, его необходимо прикрепить к компоненту путем вызова метода поведения -[attach()|IBehavior::attach]. Далее мы вызываем метод поведения через компонент: - -~~~ -[php] -// $name уникально идентифицирует поведения в компоненте -$behavior->attach($name,$component); -// test() является методом $behavior -$component->test(); -~~~ +[attach()|IBehavior::attach]. Далее мы вызываем метод поведения через компонент: + +~~~ +[php] +// $name уникально идентифицирует поведения в компоненте +$component->attachBehavior($name,$behavior); +// test() является методом $behavior +$component->test(); +~~~ К прикрепленному поведению можно обращаться, как к обычному свойству компонента. Например, если поведение с именем `tree` прикреплено к компоненту, мы можем получить ссылку на этот объект поведения следующим образом: - -~~~ -[php] -$behavior=$component->tree; -// эквивалентно выражению: -// $behavior=$component->asa('tree'); -~~~ + +~~~ +[php] +$behavior=$component->tree; +// эквивалентно выражению: +// $behavior=$component->asa('tree'); +~~~ Поведение можно временно деактивировать таким образом, чтобы его методы были недоступны через компонент. -Например: - -~~~ -[php] -$component->disableBehavior($name); -// выражение ниже приведет к вызову исключения -$component->test(); -$component->enableBehavior($name); -// здесь все будет работать нормально -$component->test(); -~~~ +Например: + +~~~ +[php] +$component->disableBehavior($name); +// выражение ниже приведет к вызову исключения +$component->test(); +$component->enableBehavior($name); +// здесь все будет работать нормально +$component->test(); +~~~ В случае, когда два поведения, прикрепленные к одному компоненту, имеют методы с одинаковыми именами, преимущество будет иметь метод поведения, которое было прикреплено раньше. - + Использование поведений совместно с [событиями](#component-event) дает дополнительные возможности. Поведение, прикрепленное к компоненту, может присваивать некоторые свои методы событиям компонента. -В этом случае, поведение получает возможность следить или менять нормальный ход выполнения компонента. - -
$Id: basics.component.txt 683 2009-02-16 05:20:17Z qiang.xue $
\ No newline at end of file +В этом случае, поведение получает возможность следить или менять нормальный ход выполнения компонента. + +
$Id: basics.component.txt 1328 2009-08-15 18:45:51Z qiang.xue $
diff --git a/docs/guide/ru/basics.controller.txt b/docs/guide/ru/basics.controller.txt index 4c7fbb5938..667b1c7f6a 100644 --- a/docs/guide/ru/basics.controller.txt +++ b/docs/guide/ru/basics.controller.txt @@ -1,4 +1,4 @@ -Контроллер +Контроллер ========== `Контроллер (controller)` — это экземпляр класса [CController] или производного от него. Контроллер создается приложением в случае, когда пользователь его запрашивает. @@ -26,7 +26,7 @@ class SiteController extends CController Маршрут ------- Контроллеры и действия опознаются по их идентификаторам. -Идентификатор контроллера — это запись формата `path/to/ xyz`, соответствующая +Идентификатор контроллера — это запись формата `path/to/xyz`, соответствующая файлу класса контроллера `protected/controllers/path/to/XyzController.php`, где `xyz` следует заменить реальным названием класса (например, `post` соответствует `protected/controllers/PostController.php`). Идентификатор действия - это название @@ -221,4 +221,4 @@ class PostController extends CController *кроме* `edit` и `create`. Если операторы `'+'` и `'-'` не указаны, фильтр будет применен ко всем действиям. -
$Id: basics.controller.txt 1263 2009-07-21 19:22:00Z qiang.xue $
\ No newline at end of file +
$Id: basics.controller.txt 1263 2009-07-21 19:22:00Z qiang.xue $
diff --git a/docs/guide/ru/basics.namespace.txt b/docs/guide/ru/basics.namespace.txt index e71141f1ba..d90c137cea 100644 --- a/docs/guide/ru/basics.namespace.txt +++ b/docs/guide/ru/basics.namespace.txt @@ -4,14 +4,14 @@ Псевдонимы пути широко используются в Yii. Псевдоним ассоциируется с директорией или путем к файлу. При его указании используется точечный синтаксис, схожий с широко используемым форматом пространств -имен: +имен: ~~~ RootAlias.path.to.target -~~~ +~~~ -где `RootAlias` - псевдоним существующей директории. Путем вызова метода [YiiBase::setPathOfAlias()] -мы можем определить новые псевдонимы путей. Для удобства следующие системные псевдонимы уже предопределены: +где `RootAlias` - псевдоним существующей директории. Путем вызова метода [YiiBase::setPathOfAlias()] +мы можем определить новые псевдонимы путей. Для удобства следующие системные псевдонимы уже предопределены: - `system`: соответствует директории фреймворка; - `application`: соответствует [базовой директории приложения](/doc/guide/basics.application#application-base-directory); @@ -21,35 +21,35 @@ RootAlias.path.to.target Кроме того, в случае, если приложение использует [модули](/doc/guide/basics.module), системный псевдоним предопределяется для каждого идентификатора модуля и соответствует пути к этому модулю. Эта возможность доступна, начиная с версии 1.0.3. Используя [YiiBase::getPathOfAlias()], псевдоним можно преобразовать в соответствующий путь. -Например, `system.web.CController` будет преобразован как `yii/framework/web/CController`. +Например, `system.web.CController` будет преобразован как `yii/framework/web/CController`. Используя псевдонимы, очень удобно импортировать описания классов. -К примеру, при необходимости импортировать описание класса [CController] можно вызвать: +К примеру, при необходимости импортировать описание класса [CController] можно вызвать: -~~~ -[php] -Yii::import('system.web.CController'); -~~~ +~~~ +[php] +Yii::import('system.web.CController'); +~~~ Использование метода [import|YiiBase::import] более эффективно, чем `include` и `require`, поскольку описание импортируемого класса не будет включено до первого обращения. Импорт одного и того же пространства имён также происходит намного быстрее, чем при использовании `include_once` и -`require_once`. +`require_once`. > Tip|Подсказка: Если мы ссылаемся на класс фреймворка, то нет необходимости импортировать или включать их. -Все системные классы Yii уже импортированы заранее. +Все системные классы Yii уже импортированы заранее. Можно использовать следующий синтаксис для того, чтобы импортировать целую директорию, а файлы классов, содержащиеся в директории, будут подключены автоматически при необходимости. -~~~ -[php] -Yii::import('system.web.*'); -~~~ +~~~ +[php] +Yii::import('system.web.*'); +~~~ Помимо [import|YiiBase::import], псевдонимы также используются во многих других местах, где есть ссылки на классы. Например, псевдоним может быть передан методу [Yii::createComponent()] для создания экземпляра соответствующего -класса, даже если этот класс не был предварительно включен. +класса, даже если этот класс не был предварительно включен. Не путайте псевдонимы пути с пространствами имен. Пространства имен служат для логической группировки имен классов, чтобы их можно было отличить от других, даже если их имена совпадают, а @@ -60,6 +60,6 @@ Yii::import('system.web.*'); экземпляры классов с одинаковыми именами, но различными описаниями. По этой причине все названия классов Yii-фреймворка имеют префикс 'C' (означающий 'class'), чтобы их можно было отличить от пользовательских классов. Для пользовательских классов рекомендуется использовать другие префиксы, -сохранив префикс 'C' зарезервированным для Yii-фреймворка. +сохранив префикс 'C' зарезервированным для Yii-фреймворка. -
$Id: basics.namespace.txt 1299 2009-08-07 00:25:55Z qiang.xue $
\ No newline at end of file +
$Id: basics.namespace.txt 1310 2009-08-08 16:03:46Z qiang.xue $
\ No newline at end of file diff --git a/docs/guide/ru/basics.view.txt b/docs/guide/ru/basics.view.txt index 338db51fbc..450b7bd251 100644 --- a/docs/guide/ru/basics.view.txt +++ b/docs/guide/ru/basics.view.txt @@ -1,5 +1,5 @@ -Представление -============= +Представление +============= Представление — это PHP-скрипт, состоящий преимущественно из элементов пользовательского интерфейса. Он может включать выражения PHP, однако рекомендуется, чтобы эти выражения не изменяли данные и оставались относительно простыми. @@ -12,43 +12,43 @@ Чтобы отрендерить представления необходимо вызвать метод [CController::render()], указав имя представления. При этом метод попытается обнаружить соответствующий файл представления в директории `protected/views/ControllerID`. - + Внутри скрипта представления экземпляр контроллера доступен через `$this`. -Таким образом, мы можем обратиться к свойству контроллера из кода представления: `$this->propertyName`. +Таким образом, мы можем обратиться к свойству контроллера из кода представления: `$this->propertyName`. Кроме того, мы можем использовать следующий способ для передачи данных представлению: - -~~~ -[php] -$this->render('edit', array( - 'var1'=>$value1, - 'var2'=>$value2, -)); -~~~ + +~~~ +[php] +$this->render('edit', array( + 'var1'=>$value1, + 'var2'=>$value2, +)); +~~~ В приведенном коде метод [render()|CController::render] извлечет второй параметр -массив - в переменные. -Как результат, в коде скрипта представления можно обращаться к локальным переменным `$var1` and `$var2`. +Как результат, в коде скрипта представления можно обращаться к локальным переменным `$var1` and `$var2`. Макет ---------- Макет (layout) - это специальное представление для декорирования других представлений. Макет обычно содержит части пользовательского интерфейса, часто используемые другими представлениями. Например, макет может содержать верхнюю и нижнюю части страницы, заключая между ними содержание другого представления. - -~~~ -[php] -......здесь верхняя часть...... - -......здесь нижняя...... -~~~ - + +~~~ +[php] +......здесь верхняя часть...... + +......здесь нижняя...... +~~~ + Здесь `$content` хранит результаты рендеринга представления основного содержания. - + Макет применяется неявно при вызове метода [render()|CController::render]. По умолчанию, в качестве макета используется представление `protected/views/layouts/main.php`. Это можно изменить путем установки значений [CWebApplication::layout] или [CController::layout]. -Для рендеринга представления без применения макета необходимо вызвать [renderPartial()|CController::renderPartial]. - +Для рендеринга представления без применения макета необходимо вызвать [renderPartial()|CController::renderPartial]. + Виджет ---------- @@ -57,72 +57,72 @@ $this->render('edit', array( Виджеты обычно встраивают в скрипт представления для генерации некоторой комплексной самодостаточной части пользовательского интерфейса. К примеру, виджет календаря может быть использован для рендеринга комплексного интерфейса календаря. Виджеты служат цели повторного использования кода пользовательского интерфейса. - -Для использования виджета необходимо выполнить в коде: - -~~~ -[php] -beginWidget('path.to.WidgetClass'); ?> -...некое содержимое, которое может быть использовано виджетом... -endWidget(); ?> -~~~ -или +Для использования виджета необходимо выполнить в коде: + +~~~ +[php] +beginWidget('path.to.WidgetClass'); ?> +...некое содержимое, которое может быть использовано виджетом... +endWidget(); ?> +~~~ + +или -~~~ -[php] -widget('path.to.WidgetClass'); ?> -~~~ +~~~ +[php] +widget('path.to.WidgetClass'); ?> +~~~ -В последнем варианте для использования виджета не требуется дополнительного содержимого. +В последнем варианте для использования виджета не требуется дополнительного содержимого. В случае, если поведение виджета необходимо изменить, можно их поднастроить. Это делается путем установки значений свойств при вызове [CBaseController::beginWidget] или [CBaseController::widget]. -Например, при использовании виджета [CMaskedTextField] можно указать используемую маску, +Например, при использовании виджета [CMaskedTextField] можно указать используемую маску, передав массив значений свойств, как показано ниже, где ключи массива являются названиями свойств, -а значения - требуемыми начальными значениями соответствующих свойств виджета: - -~~~ -[php] -widget('CMaskedTextField',array( - 'mask'=>'99/99/9999' -)); -?> -~~~ - +а значения - требуемыми начальными значениями соответствующих свойств виджета: + +~~~ +[php] +widget('CMaskedTextField',array( + 'mask'=>'99/99/9999' +)); +?> +~~~ + Чтобы создать новый виджет необходимо расширить класс [CWidget] и перегрузить его методы [init()|CWidget::init] и [run()|CWidget::run]: - -~~~ -[php] -class MyWidget extends CWidget -{ - public function init() - { - // этот метод будет вызван методом CController::beginWidget() - } - - public function run() - { - // этот метод будет вызван методом CController::endWidget() - } -} -~~~ - -Как и контроллер, у виджета может быть собственное представление. + +~~~ +[php] +class MyWidget extends CWidget +{ + public function init() + { + // этот метод будет вызван методом CController::beginWidget() + } + + public function run() + { + // этот метод будет вызван методом CController::endWidget() + } +} +~~~ + +Как и у контроллера, у виджета может быть собственное представление. По умолчанию, файлы представлений виджета находятся в поддиректории -`views` директории, содержащей файл класса виджета. Эти представления можно рендерить +`views` директории, содержащей файл класса виджета. Эти представления можно рендерить при помощи вызова [CWidget::render()], точно также как и в случае с контроллером. -Единственная разница состоит в том, что для представления виджета не используются макеты. - +Единственная разница состоит в том, что для представления виджета не используются макеты. + Системные представления ------------------------ Системные представления (system view) относятся к представлениям, используемым Yii для отображения ошибок и информации лога. Например, когда пользователь запрашивает несуществующий контроллер или действие, Yii сгенерирует исключение, раскрывающее суть ошибки. Такое исключение будет отображено с помощью системного представления. - + Именование системных представлений подчиняется некоторым правилам. Имена типа `errorXXX` относятся к представлениям, служащим для отображения [CHttpException] с кодом ошибки `XXX`. @@ -130,6 +130,6 @@ class MyWidget extends CWidget будет использовано представление `error404`. Yii предоставляет стандартный набор системных представлений, расположенных в `framework/views`. -Их можно видоизменить путем создания файлов представлений с теми же названиям в директории `protected/views/system`. +Их можно видоизменить путем создания файлов представлений с теми же названиям в директории `protected/views/system`.
$Id: basics.view.txt 416 2008-12-28 05:28:11Z qiang.xue $
diff --git a/docs/guide/ru/caching.overview.txt b/docs/guide/ru/caching.overview.txt index 11c477fef0..a3a491f9b9 100644 --- a/docs/guide/ru/caching.overview.txt +++ b/docs/guide/ru/caching.overview.txt @@ -89,4 +89,4 @@ memcache для PHP и использует память как среду хр Поэтому не используйте кэш как постоянное хранилище данных (например, не используйте кэш для хранения данных сессий). -
$Id: caching.overview.txt 1084 2009-06-02 17:35:38Z qiang.xue $
\ No newline at end of file +
$Id: caching.overview.txt 1309 2009-08-08 12:37:23Z qiang.xue $
\ No newline at end of file diff --git a/docs/guide/ru/database.ar.txt b/docs/guide/ru/database.ar.txt index c850d95464..b45df01d18 100644 --- a/docs/guide/ru/database.ar.txt +++ b/docs/guide/ru/database.ar.txt @@ -454,7 +454,12 @@ $post->save(); - [afterConstruct|CActiveRecord::afterConstruct]: метод вызывается для каждого экземпляра AR, созданного с использованием оператора `new`; - - [afterFind|CActiveRecord::afterFind]: метод вызывается для каждого экземпляра AR, созданного в результате выполнения запроса. + - [beforeFind|CActiveRecord::beforeFind]: метод вызывается перед тем, как + finder AR выполнит запрос (например, `find()`, `findAll()`). Данный метод + доступен с версии 1.0.9. + + - [afterFind|CActiveRecord::afterFind]: метод вызывается для каждого экземпляра AR, + созданного в результате выполнения запроса. Использование транзакций с AR ------------------------- @@ -610,4 +615,4 @@ $contents=Content::model()->findAll(); Заметим, что именованная группа условий по умолчанию применяется только к `SELECT` запросам. Она игнорируется в `INSERT`, `UPDATE` и `DELETE` запросах. -
$Id: database.ar.txt 1167 2009-06-23 02:56:45Z qiang.xue $
+
$Id: database.ar.txt 1391 2009-09-04 19:46:04Z qiang.xue $
diff --git a/docs/guide/ru/database.arr.txt b/docs/guide/ru/database.arr.txt index 12f4f97409..e98d62bddb 100644 --- a/docs/guide/ru/database.arr.txt +++ b/docs/guide/ru/database.arr.txt @@ -283,7 +283,7 @@ class User extends CActiveRecord } ~~~ -Теперь, если бы обратимся к `$author->posts`, то получим все посты автора, упорядоченные по времени создания по убыванию. +Теперь, если мы обратимся к `$author->posts`, то получим все посты автора, упорядоченные по времени создания по убыванию. Также каждый экземпляр поста содержит свои уже подгруженные категории. > Info|Информация: Когда поле с одинаковым именем присутствует в нескольких объединяемых таблицах, их @@ -442,4 +442,4 @@ class User extends CActiveRecord должны описываться в методе [CActiveRecord::scopes], поэтому они не могут быть параметризованы. -
$Id: database.arr.txt 1248 2009-07-15 19:40:44Z qiang.xue $
\ No newline at end of file +
$Id: database.arr.txt 1248 2009-07-15 19:40:44Z qiang.xue $
diff --git a/docs/guide/ru/extension.create.txt b/docs/guide/ru/extension.create.txt index ecc54bf741..45988f14ef 100644 --- a/docs/guide/ru/extension.create.txt +++ b/docs/guide/ru/extension.create.txt @@ -1,4 +1,4 @@ -Создание расширений +Создание расширений =================== Поскольку создание расширений подразумевает их использование сторонними разработчиками, @@ -29,6 +29,39 @@ Если необходимо принудительно создавать компонент сразу после создания экземпляра приложения, то нужно добавить этого идентификатор компонента в свойство [CApplication::preload]. +Поведение +--------- + +Для того, чтобы создать поведение необходимо реализовать интерфейс [IBehavior]. +Для удобства в Yii имеется класс [CBehavior], реализующий этот интерфейс и +предоставляющий некоторые общие методы. Наследуемые классы могут реализовать +дополнительные методы, которые будут доступны в компонентах, к которым прикреплено +поведение. + +При разработке поведений для [CModel] и [CActiveRecord] можно наследовать +[CModelBehavior] и, соответственно, [CActiveRecordBehavior]. Эти базовые классы +предоставляют дополнительные возможности, специально созданные для [CModel] и [CActiveRecord]. +К примеру, класс [CActiveRecordBehavior] реализует набор методов для обработки +событий жизненного цикла ActiveRecord. Наследуемый класс, таким образом, может +перекрыть эти методы и выполнить код, участвующий в жизненном цикле AR. + +Следующий код демонстрирует пример поведения ActiveRecord. Если это поведение +назначено объекту AR и вызван метод `save()`, атрибутам `create_time` и +`update_time` будет автоматически выставлено текущее время. + +[code] +class TimestampBehavior extends CActiveRecordBehavior +{ + public function beforeSave($event) + { + if($this->owner->isNewRecord) + $this->owner->create_time=time(); + else + $this->owner->update_time=time(); + } +} +[/code] + Виджет ------ @@ -186,4 +219,4 @@ class MyCommand extends CConsoleCommand -
$Id: extension.create.txt 749 2009-02-26 02:11:31Z qiang.xue $
\ No newline at end of file +
$Id: extension.create.txt 1392 2009-09-04 20:39:11Z qiang.xue $
diff --git a/docs/guide/ru/extension.overview.txt b/docs/guide/ru/extension.overview.txt index 83201538a4..72648b80e1 100644 --- a/docs/guide/ru/extension.overview.txt +++ b/docs/guide/ru/extension.overview.txt @@ -1,4 +1,4 @@ -Обзор +Обзор ======== Дописывание Yii путем расширения - стандартная практика в процессе разработки. Например, @@ -6,21 +6,22 @@ [CController]; для написания виджета - класса [CWidget] или класса уже существующего виджета. Если дописанный код оформлен для использования сторонними разработчиками, мы называем его *расширением (extension)*. -Как правило, каждое расширение служит только одной цели. Используя терминологию, принятую в Yii, +Как правило, каждое расширение служит только для одной цели. Используя терминологию, принятую в Yii, расширения можно классифицировать следующим образом: - * [компонент приложения](/doc/guide/basics.application#application-component); - * [виджет](/doc/guide/basics.view#widget); - * [контроллер](/doc/guide/basics.controller); - * [действие](/doc/guide/basics.controller#action); - * [фильтр](/doc/guide/basics.controller#filter); - * [команда консоли](/doc/guide/topics.console); + * [компонент приложения](/doc/guide/ru/basics.application#application-component); + * [поведение](/doc/guide/ru/basics.component#component-behavior); + * [виджет](/doc/guide/ru/basics.view#widget); + * [контроллер](/doc/guide/ru/basics.controller); + * [действие](/doc/guide/ru/basics.controller#action); + * [фильтр](/doc/guide/ru/basics.controller#filter); + * [команда консоли](/doc/guide/ru/topics.console); * валидатор: компонент, наследующий класс [CValidator]; * помощник: класс, содержащий только статические методы, схожий с глобальной функцией, использующей имя класса в качестве пространства имен; - * [модуль](/doc/guide/basics.module): самодостаточная программная единица, состоящая из [моделей](/doc/guide/basics.model), [действий](/doc/guide/basics.view), [контроллеров](/doc/guide/basics.controller) и необходимых компонентов. Модуль во многом схож с [приложением](/doc/guide/basics.application). + * [модуль](/doc/guide/ru/basics.module): самодостаточная программная единица, состоящая из [моделей](/doc/guide/ru/basics.model), [действий](/doc/guide/ru/basics.view), [контроллеров](/doc/guide/ru/basics.controller) и необходимых компонентов. Модуль во многом схож с [приложением](/doc/guide/ru/basics.application). Основное отличие состоит в том, что модули входят в состав приложения. Например, у нас может быть модуль, реализующий функционал управления пользователями. Впрочем, расширение может и не соответствовать ни одной из перечисленных категорий. Yii изначально был спроектирован таким образом, чтобы любую его часть можно было изменить и дополнить для любых нужд. -
$Id: extension.overview.txt 759 2009-02-26 21:23:53Z qiang.xue $
\ No newline at end of file +
$Id: extension.overview.txt 1392 2009-09-04 20:39:11Z qiang.xue $
diff --git a/docs/guide/ru/extension.use.txt b/docs/guide/ru/extension.use.txt index d30e1e1e9b..3884bba505 100644 --- a/docs/guide/ru/extension.use.txt +++ b/docs/guide/ru/extension.use.txt @@ -51,6 +51,68 @@ return array( `Yii::app()->xyz`. Компонент будет создан отложенно (т.е. в момент первого обращения), если, конечно, мы не укажем его в свойстве `preload`. +Поведение +--------- + +[Поведение](/doc/guide/ru/basics.component#component-behavior) может быть +использовано в любом компоненте. Делается это в два шага: присоединение +к компоненту и вызов метода поведения из компонента. К примеру: + +~~~ +[php] +// $name соответствует уникальному поведению компонента +$component->attachBehavior($name,$behavior); +// test() является методом $behavior +$component->test(); +~~~ + +Чаще всего поведение присоединяется к компоненту с использованием конфигурации, а +не вызовом метода `attachBehavior`. К примеру, чтобы присоединить поведение к +[компоненту приложения](/doc/guide/ru/basics.application#application-component), +мы можем использовать следующую +[конфигурацию](/doc/guide/ru/basics.application#application-configuration): + +~~~ +[php] +return array( + 'components'=>array( + 'db'=>array( + 'class'=>'CDbConnection', + 'behaviors'=>array( + 'xyz'=>array( + 'class'=>'ext.xyz.XyzBehavior', + 'property1'=>'value1', + 'property2'=>'value2', + ), + ), + ), + //.... + ), +); +~~~ + +Приведённый выше код присоединяет поведение `xyz` к компоненту приложения `db`. +Это возможно так как [CApplicationComponent] определяет свойство `behaviors`. +При инициализации компонент присоединит перечисленные в нём поведения. + +Для классов [CController], [CFormModel] и [CActiveModel], которые необходимо расширять, +присоединение поведений присходит при помощи переопределения метода `behaviors()`. +К примеру: + +~~~ +[php] +public function behaviors() +{ + return array( + 'xyz'=>array( + 'class'=>'ext.xyz.XyzBehavior', + 'property1'=>'value1', + 'property2'=>'value2', + ), + ); +} +~~~ + Виджет ------ @@ -232,4 +294,4 @@ Yii::import('ext.xyz.XyzClass'); вызывать его методы. Кроме того, можно его расширить для создания дочерних классов. -
$Id: extension.use.txt 1299 2009-08-07 00:25:55Z qiang.xue $
\ No newline at end of file +
$Id: extension.use.txt 1392 2009-09-04 20:39:11Z qiang.xue $
diff --git a/docs/guide/ru/topics.url.txt b/docs/guide/ru/topics.url.txt index a339cca893..d5ad7dbd38 100644 --- a/docs/guide/ru/topics.url.txt +++ b/docs/guide/ru/topics.url.txt @@ -117,10 +117,13 @@ array( <ParamName:ParamPattern> ~~~ -где `ParamName` соответствует имени GET-параметра, а опциональный `ParamPattern` соответствует -регулярному выражению, которое используется для проверки соответствия значению GET-параметра. -В момент создания URL маркеры будут заменены на соответствующие значения параметров, а в момент обработки -адреса URL соответствующие GET-параметрам будут присвоены результаты обработки. +где `ParamName` соответствует имени GET-параметра, а необязательный +`ParamPattern` — регулярному выражению, которое используется для проверки +соответствия значению GET-параметра. Если `ParamPattern` не указан, то +параметр должен соответствовать любым символам, кроме слэша `/`. В момент +создания URL маркеры будут заменены на соответствующие значения параметров, +а в момент обработки URL соответствующие GET-параметрам будут +присвоены результаты обработки. Для наглядности приведем несколько примеров. Предположим, что наш набор правил состоит из трех правил: @@ -228,4 +231,4 @@ RewriteRule . index.php Для этого нужно просто настроить компонент [urlManager|CWebApplication::urlManager] путем назначения свойству [urlSuffix|CUrlManager::urlSuffix] любого желаемого окончания. -
$Id: topics.url.txt 1273 2009-07-22 21:32:23Z qiang.xue $
\ No newline at end of file +
$Id: topics.url.txt 1342 2009-08-17 14:55:58Z qiang.xue $
diff --git a/docs/guide/zh_cn/topics.security.txt b/docs/guide/zh_cn/topics.security.txt new file mode 100644 index 0000000000..b1e57a0c04 --- /dev/null +++ b/docs/guide/zh_cn/topics.security.txt @@ -0,0 +1,108 @@ +安全措施 (Security) +======== + +跨站脚本攻击的防范 +------------------------------- +跨站脚本攻击(简称 XSS),即web应用从用户收集用户数据。 +攻击者常常向易受攻击的web应用注入JavaScript,VBScript,ActiveX,HTML或 Flash来迷惑访问者以收集访问者的信息。 +举个例子,一个未经良好设计的论坛系统可能不经检查就显示用户所输入的内容。 +攻击者可以在帖子内容中注入一段恶意的JavaScript代码。 +这样,当其他访客在阅读这个帖子的时候,这些JavaScript代码就可以在访客的电脑上运行了。 + +一个防范XSS攻击的最重要的措施之一就是:在显示用户输入的内容之前进行内容检查。 +比如,你可以对内容中的HTML进行转义处理。但是在某些情况下这种方法就不可取了,因为这种方法禁用了所有的HTML标签。 + +Yii集成了[HTMLPurifier](http://htmlpurifier.org/)并且为开发者提供了一个很有用的组件[CHtmlPurifier], +这个组件封装了[HTMLPurifier](http://htmlpurifier.org/)类。它可以将通过有效的审查、安全和白名单功能来把所审核的内容中的所有的恶意代码清除掉,并且确保过滤之后的内容过滤符合标准。 + +[CHtmlPurifier]组件可以作为一个[widget](/doc/guide/basics.view#widget)或者[filter](/doc/guide/basics.controller#filter)来使用。 +当作为一个widget来使用的时候,[CHtmlPurifier]可以对在视图中显示的内容进行安全过滤。 +以下是代码示例: + +~~~ +[php] +beginWidget('CHtmlPurifier'); ?> +//...这里显示用户输入的内容... +endWidget(); ?> +~~~ + + +跨站请求伪造攻击的防范 +------------------------------------- + +跨站请求伪造(简称CSRF)攻击,即攻击者在用户浏览器在访问恶意网站的时候,让用户的浏览器向一个受信任的网站发起攻击者指定的请求。 +举个例子,一个恶意网站有一个图片,这个图片的`src`地址指向一个银行网站: + `http://bank.example/withdraw?transfer=10000&to=someone`。 +如果用户在登陆银行的网站之后访问了这个恶意网页,那么用户的浏览器会向银行网站发送一个指令,这个指令的内容可能是“向攻击者的帐号转账10000元”。 +跨站攻击方式利用用户信任的某个特定网站,而CSRF攻击正相反,它利用用户在某个网站中的特定用户身份。 + +要防范CSRF攻击,必须谨记一条:`GET`请求只允许检索数据而不能修改服务器上的任何数据。 +而`POST`请求应当含有一些可以被服务器识别的随机数值,用来保证表单数据的来源和运行结果发送的去向是相同的。 + +Yii实现了一个CSRF防范机制,用来帮助防范基于`POST`的攻击。 +这个机制的核心就是在cookie中设定一个随机数据,然后把它同表单提交的`POST`数据中的相应值进行比较。 + +默认情况下,CSRF防范是禁用的。如果你要启用它,可以编辑[应用配置](/doc/guide/basics.application#application-configuration) +中的组件中的[CHttpRequest]部分。 + +代码示例: + +~~~ +[php] +return array( + 'components'=>array( + 'request'=>array( + 'enableCsrfValidation'=>true, + ), + ), +); +~~~ + +要显示一个表单,请使用[CHtml::form]而不要自己写HTML代码。因为[CHtml::form]可以自动地在表单中嵌入一个隐藏项,这个隐藏项储存着验证所需的随机数据,这些数据可在表单提交的时候发送到服务器进行验证。 + + +Cookie攻击的防范 +------------------------ +保护cookie免受攻击是非常重要的。因为session ID通常存储在Cookie中。 +如果攻击者窃取到了一个有效的session ID,他就可以使用这个session ID对应的session信息。 + +这里有几条防范对策: + +* 您可以使用SSL来产生一个安全通道,并且只通过HTTPS连接来传送验证cookie。这样攻击者是无法解密所传送的cookie的。 +* 设置cookie的过期时间,对所有的cookie和seesion令牌也这样做。这样可以减少被攻击的机会。 +* 防范跨站代码攻击,因为它可以在用户的浏览器触发任意代码,这些代码可能会泄露用户的cookie。 +* 在cookie有变动的时候验证cookie的内容。 + +Yii实现了一个cookie验证机制,可以防止cookie被修改。启用之后可以对cookie的值进行HMAC检查。 + +Cookie验证在默认情况下是禁用的。如果你要启用它,可以编辑[应用配置](/doc/guide/basics.application#application-configuration) +中的组件中的[CHttpRequest]部分。 + +代码示例: + +~~~ +[php] +return array( + 'components'=>array( + 'request'=>array( + 'enableCookieValidation'=>true, + ), + ), +); +~~~ + +一定要使用经过Yii验证过的cookie数据。使用Yii内置的[cookies|CHttpRequest::cookies]组件来进行cookie操作,不要使用`$_COOKIES`。 + +~~~ +[php] +// 检索一个名为$name的cookie值 +$cookie=Yii::app()->request->cookies[$name]; +$value=$cookie->value; +...... +// 设置一个cookie +$cookie=new CHttpCookie($name,$value); +Yii::app()->request->cookies[$name]=$cookie; +~~~ + + +
$Id: topics.security.txt 1173 2009-09-03 16:46:23Z i@imdong.net $
\ No newline at end of file diff --git a/framework/messages/bg/yii.php b/framework/messages/bg/yii.php index 60997aa2fe..7dd711460f 100644 --- a/framework/messages/bg/yii.php +++ b/framework/messages/bg/yii.php @@ -16,198 +16,198 @@ * @version $Id: $ */ return array ( - '"{path}" is not a valid directory.' => '"{path}" не е валидна директория', - '< Previous' => '< Предишно', - '<< First' => '<< Първо', - 'Active Record requires a "db" CDbConnection application component.' => 'Active Record изисква "db" CDbConnection application компонент', - 'Active record "{class}" has an invalid configuration for relation "{relation}". It must specify the relation type, the related active record class and the foreign key.' => 'Active record "{class}" има невалидна конфигурация за релацията "{relation}". Тя трябва да оказва типа на релацията, active record за който се откася и ключа', - 'Active record "{class}" is trying to select an invalid column "{column}". Note, the column must exist in the table or be an expression with alias.' => 'Active record "{class}" се опитва да избере невалидна колона "{column}". Тя трябва да съществува в таблицата', - 'Alias "{alias}" is invalid. Make sure it points to an existing directory or file.' => 'Псевдонима "{alias}" не съществува. Провете дали води до съществуваща директория или файл.', - 'Application base path "{path}" is not a valid directory.' => 'Базовата директория на приложението "{path}" не е валидна директория.', - 'Application runtime path "{path}" is not valid. Please make sure it is a directory writable by the Web server process.' => 'Работната директория на приложението "{path}" не е валидна. Моля проверете дали има права за четене и запис от нея.', - 'Authorization item "{item}" has already been assigned to user "{user}".' => 'Елемента за оторизация "{item}", вече е назначен към потребителя "{user}".', - 'CApcCache requires PHP apc extension to be loaded.' => 'CApcCache изисква да бъде заредено PHP apc разширението.', - 'CAssetManager.basePath "{path}" is invalid. Please make sure the directory exists and is writable by the Web server process.' => 'CAssetManager.basePath "{path}" не е валидна директория. Моля, проверете дали съществува и дали има права за писане във нея.', - 'CCacheHttpSession.cacheID is invalid. Please make sure "{id}" refers to a valid cache application component.' => 'CCaptchaValidator.action "{id}" е невалидна. Моля, уверете се че "{id}" сочи към валиден cache application компонент.', - 'CCaptchaValidator.action "{id}" is invalid. Unable to find such an action in the current controller.' => 'CCaptchaValidator.action "{id}" не е валидна. Моля, уверете се че води към ID на CDbConnection application компонент.', - 'CDbAuthManager.connectionID "{id}" is invalid. Please make sure it refers to the ID of a CDbConnection application component.' => 'CDbAuthManager.connectionID "{id}" е невалидна. Моля, уверете се че води към ID на CDbConnection application компонент.', - 'CDbCache.connectionID "{id}" is invalid. Please make sure it refers to the ID of a CDbConnection application component.' => 'CDbCache.connectionID "{id}" е невалидна. Моля, уверете се че води към ID на CDbConnection application компонент.', - 'CDbCacheDependency.sql cannot be empty.' => 'CDbCacheDependency.sql не може да бъде празен', - 'CDbCommand failed to execute the SQL statement: {error}' => 'CDbCommand не можа да изпълни SQL заявката: {error}', - 'CDbCommand failed to prepare the SQL statement: {error}' => 'CDbCommand не можа да приготви SQL заявката: {error}', - 'CDbConnection does not support reading schema for {driver} database.' => 'CDbConnection не поддържа схема за четена на {driver} база от данни.', - 'CDbConnection failed to open the DB connection: {error}' => 'CDbConnection не успя да осъществи връзка с базата данни', - 'CDbConnection is inactive and cannot perform any DB operations.' => 'CDbConnection е неактивен и не може да изпълнява операции с базата от данни', - 'CDbConnection.connectionString cannot be empty.' => 'CDbConnection.connectionString не може да бъде празен', - 'CDbDataReader cannot rewind. It is a forward-only reader.' => 'CDbDataReader не може да връща назад.', - 'CDbHttpSession.connectionID "{id}" is invalid. Please make sure it refers to the ID of a CDbConnection application component.' => 'DbHttpSession.connectionID "{id}" е невалидна. Моля, уверете се че сочи към ID на CDbConnection application компоненета.', - 'CDbLogRoute requires database table "{table}" to store log messages.' => 'CDbLogRoute изисква таблицата "{table}", за да съхранява съобщенията от дневника.', - 'CDbLogRoute.connectionID "{id}" does not point to a valid CDbConnection application component.' => 'CDbLogRoute.connectionID "{id}" не води към валиден CDbConnection application компонент.', - 'CDbMessageSource.connectionID is invalid. Please make sure "{id}" refers to a valid database application component.' => 'CDbMessageSource.connectionID е невалидна. Моля, проверете дали "{id}" води към валиден компонент на приложението за работа с бази от данни.', - 'CDbTransaction is inactive and cannot perform commit or roll back operations.' => 'CDbTransaction не е активно и не може да изпълнява операции.', - 'CDirectoryCacheDependency.directory cannot be empty.' => 'CDirectoryCacheDependency.directory не може да бъде празно.', - 'CFileCacheDependency.fileName cannot be empty.' => 'CFileCacheDependency.fileName не може да бъде празно.', - 'CFileLogRoute.logPath "{path}" does not point to a valid directory. Make sure the directory exists and is writable by the Web server process.' => 'CFileLogRoute.logPath "{path}" не сочи към валидна директория. Моля, проверете дали съществува и дали има права за писане във нея.', - 'CFilterChain can only take objects implementing the IFilter interface.' => 'CFilterChain може да взима единствено обенти, имплементиращи интерфейса IFilter.', - 'CFlexWidget.baseUrl cannot be empty.' => 'CFlexWidget.baseUrl не може да бъде празно.', - 'CFlexWidget.name cannot be empty.' => 'CFlexWidget.name не може да бъде празно', - 'CGlobalStateCacheDependency.stateName cannot be empty.' => 'CGlobalStateCacheDependency.stateName не може да бъде празно', - 'CHttpCookieCollection can only hold CHttpCookie objects.' => 'CHttpCookieCollection не може да съдържа CHttpCookie обект', - 'CHttpRequest is unable to determine the entry script URL.' => 'CHttpRequest не може да определи URL на началния скрипт.', - 'CHttpRequest is unable to determine the path info of the request.' => 'CHttpRequest не може да намери информация за пътя на заявката.', - 'CHttpRequest is unable to determine the request URI.' => 'CHttpRequest не може да намери поискания URL', - 'CHttpSession.cookieMode can only be "none", "allow" or "only".' => 'CHttpSession.cookieMode може да бъде само "none", "allow" или "only".', - 'CHttpSession.gcProbability "{value}" is invalid. It must be an integer between 0 and 100.' => 'CHttpSession.gcProbability "{value}" не е валидно. То трябва да е цяло число между 0 и 100.', - 'CHttpSession.savePath "{path}" is not a valid directory.' => 'CHttpSession.savePath "{path}" е невалидна директория.', - 'CMemCache requires PHP memcache extension to be loaded.' => 'CMemCache изисква да бъде заредено PHP memcache допълнение', - 'CMemCache server configuration must be an array.' => 'Сърварната конфигурация на CMemCache трябва да бъде масив.', - 'CMemCache server configuration must have "host" value.' => 'Сърварната конфигурация на CMemCache трябва да има стойност "host".', - 'CMultiFileUpload.name is required.' => 'Изисква се CMultiFileUpload.name', - 'CProfileLogRoute found a mismatching code block "{token}". Make sure the calls to Yii::beginProfile() and Yii::endProfile() be properly nested.' => 'CProfileLogRoute намери несъответсващ блок от код "{token}". Моля, проверете обръщането към Yii::beginProfile() и Yii::endProfile().', - 'CProfileLogRoute.report "{report}" is invalid. Valid values include "summary" and "callstack".' => 'CProfileLogRoute.report "{report}" е невалиден. Валидните стойности включват "summary" и "callstack".', - 'CSecurityManager requires PHP mcrypt extension to be loaded in order to use data encryption feature.' => 'CSecurityManager изисква наличието на PHP допълнението mcrypt, за да може да изпозлвате функциите за криптиране.', - 'CSecurityManager.encryptionKey cannot be empty.' => 'CSecurityManager.encryptionKey не може да е празно.', - 'CSecurityManager.validation must be either "MD5" or "SHA1".' => 'CSecurityManager.validation трябва да бъде или "MD5" или "SHA1"(препоръчително).', - 'CSecurityManager.validationKey cannot be empty.' => 'CSecurityManager.validationKey не може да бъде празно.', - 'CTypedList<{type}> can only hold objects of {type} class.' => 'CTypedList<{type}> може да съдържа само обекти от класа {type}. ', - 'CUrlManager.UrlFormat must be either "path" or "get".' => 'CUrlManager.UrlFormat трябва да бъде или "path" или "get".', - 'CXCache requires PHP XCache extension to be loaded.' => 'CXCache изисква да се зареди PHP допълнението XCache.', - 'Cache table "{tableName}" does not exist.' => 'Таблицата за кеширане "{tableName}" не съществува.', - 'Cannot add "{child}" as a child of "{name}". A loop has been detected.' => 'Грешка при добавянето на "{child}", като производен на "{name}". Получава се цикъл', - 'Cannot add "{child}" as a child of "{parent}". A loop has been detected.' => 'Грешка при добавянето на "{child}", като производен на "{parent}". Получава се цикъл.', - 'Cannot add "{name}" as a child of itself.' => 'Не може да добави "{name}", като производен на себе си.', - 'Cannot add an item of type "{child}" to an item of type "{parent}".' => 'Не може да добави елемент от тип "{child}" към елемент от тип "{parent}".', - 'Either "{parent}" or "{child}" does not exist.' => 'Не съществува "{parent}" или "{child}".', - 'Error: Table "{table}" does not have a primary key.' => 'Грешка: Таблицата "{table}" няма първичен ключ.', - 'Error: Table "{table}" has a composite primary key which is not supported by crud command.' => 'Грешка: Таблицата "{table}" има сложен първичен ключ, който не се поддържа от crud командадата.', - 'Event "{class}.{event}" is attached with an invalid handler "{handler}".' => 'Събитието "{class}.{event}" е с невалиден прикачен handler "{handler}".', - 'Event "{class}.{event}" is not defined.' => 'Събитието "{class}.{event}" не е дефинирано', - 'Failed to write the uploaded file "{file}" to disk.' => 'Грешка при записването на файла "{file}" на диска.', - 'File upload was stopped by extension.' => 'Качването на файла е спряно от допълнението.', - 'Filter "{filter}" is invalid. Controller "{class}" does have the filter method "filter{filter}".' => 'Filter "{filter}" е невалиден. Контролера "{class}" няма филтър метод "filter{filter}".', - 'Get a new code' => 'Генерирай нов код', - 'Go to page: ' => 'Отиди на страница', - 'Invalid MO file revision: {revision}.' => 'Невалидна MO файл revision: {revision}.', - 'Invalid MO file: {file} (magic: {magic}).' => 'Невалиден MO файл: {file} (magic: {magic}).', - 'Invalid enumerable value "{value}". Please make sure it is among ({enum}).' => 'Невалидна стойност "{value}". Моля, проверете дали е сред ({enum}).', - 'Last >>' => 'Последна', - 'List data must be an array or an object implementing Traversable.' => 'Списъка с данни трябва да бъде масив или обект имплементиращ Traversable.', - 'List index "{index}" is out of bound.' => 'Индекса на списъка "{index}" е извън границите.', - 'Login Required' => 'Моля, идентифицирайте се преди да продължите.', - 'Map data must be an array or an object implementing Traversable.' => 'Асоциативния масив трябва да бъде масив или обект имплементиращ Traversable.', - 'Missing the temporary folder to store the uploaded file "{file}".' => 'Временната папка, за съхраниение на качения файл "{file}" липсва.', - 'Next >' => 'Напред', - 'No columns are being updated for table "{table}".' => 'Не бяха обновени полетата на таблица "{table}".', - 'No counter columns are being updated for table "{table}".' => 'Не бяха обновени полетата на таблица "{table}".', - 'Object configuration must be an array containing a "class" element.' => 'Конфигурацията на обекта, трябва да бъде масив съдържащ "class" елементи.', - 'Please fix the following input errors:' => 'Моля поправете следните грешки, за да продължите нататък:', - 'Property "{class}.{property}" is not defined.' => 'Свойството "{class}.{property}" не е дефинирано.', - 'Property "{class}.{property}" is read only.' => 'Свойството "{class}.{property}" е само за четене.', - 'Queue data must be an array or an object implementing Traversable.' => 'Опашката от данни трябва да е масив или обект имплементиращ Traversable.', - 'Relation "{name}" is not defined in active record class "{class}".' => 'Релацията "{name}" не е дефинирана в active record класа "{class}".', - 'Stack data must be an array or an object implementing Traversable.' => 'Стековите данни трябва да бъдат масив или обект имплементиращ Traversable', - 'Table "{table}" does not have a column named "{column}".' => 'Таблицата "{table}" няма колона с име "{column}".', - 'Table "{table}" does not have a primary key defined.' => 'Таблицата "{table}" няма определен първичен ключ.', - 'The "filter" property must be specified with a valid callback.' => 'Свойството "filter" трябва да бъде определено с валиден callback.', - 'The "pattern" property must be specified with a valid regular expression.' => 'Свойството "pattern" трябва да бъде зададено с коректен регулярен израз.', - 'The "view" property is required.' => 'Изисква се стойност за свойството "view".', - 'The CSRF token could not be verified.' => 'CSRF знака не може да бъде проверен', - 'The URL pattern "{pattern}" for route "{route}" is not a valid regular expression.' => 'URL шаблона "{pattern}" за пътя "{route}" не е валиден регулярен израз.', - 'The active record cannot be deleted because it is new.' => 'Active record не може да бъде изтрит, защото е нов.', - 'The active record cannot be inserted to database because it is not new.' => 'Active record не може да бъде вмъкнат в базата от данни, защото не е нов', - 'The active record cannot be updated because it is new.' => 'Active record не може да бъде обновен, защото е нов.', - 'The asset "{asset}" to be published does not exist.' => '"{asset}" за публикуване не съществува.', - 'The column "{column}" is not a foreign key in table "{table}".' => 'Полето "{column}" не е ключ в таблицата "{table}".', - 'The command path "{path}" is not a valid directory.' => 'Командния път "{path}", не е валидна директория.', - 'The controller path "{path}" is not a valid directory.' => 'Пътят на контролера "{path}", не е валидна директория.', - 'The file "{file}" cannot be uploaded. Only files with these extensions are allowed: {extensions}.' => 'Файлът "{file}" не може да бъде качен. Разрешени са само файлове със следните разширения: {extensions}.', - 'The file "{file}" is too large. Its size cannot exceed {limit} bytes.' => 'Файлът "{file}" е прекалено голям. Големината му не може да надвишава {limit} байта.', - 'The file "{file}" is too small. Its size cannot be smaller than {limit} bytes.' => 'Файлът "{file}" е прекалено малък. Минималния размер е {limit} байта.', - 'The file "{file}" was only partially uploaded.' => 'Файлът "{file}" беше качен частично.', - 'The first element in a filter configuration must be the filter class.' => 'Първия елемент в конфигурацията на филтъра трябва да бъде класа филтър.', - 'The item "{name}" does not exist.' => 'Елемента "{name}" не съществува.', - 'The item "{parent}" already has a child "{child}".' => 'Елемента "{parent}" вече има производен "{child}".', - 'The layout path "{path}" is not a valid directory.' => 'Пътя към layout "{path}" не е валидна директория.', - 'The list is read only.' => 'Списъка е само за четене.', - 'The map is read only.' => 'Асоциативния масив е само за четене.', - 'The pattern for 12 hour format must be "h" or "hh".' => 'Шаблона за 12 часовия формат трябва да е "h" или "hh".', - 'The pattern for 24 hour format must be "H" or "HH".' => 'Шаблона за 24 часовия формат трябва да е "H" или "HH".', - 'The pattern for AM/PM marker must be "a".' => 'Шаблона за AM/PM мармера трябва да е "a".', - 'The pattern for day in month must be "F".' => 'Шаблона за дни в месеца трябва да е "F".', - 'The pattern for day in year must be "D", "DD" or "DDD".' => 'Шаблона за дни в годината трябва да е "D", "DD" или "DDD".', - 'The pattern for day of the month must be "d" or "dd".' => 'Шаблона за дни от месеца трябва да е "d" или "dd".', - 'The pattern for day of the week must be "E", "EE", "EEE", "EEEE" or "EEEEE".' => 'Шаблона за ден от седмицата, трябва да е "E", "EE", "EEE", "EEEE" или "EEEEE".', - 'The pattern for era must be "G", "GG", "GGG", "GGGG" or "GGGGG".' => 'Шаблона за ера трябва да е "G", "GG", "GGG", "GGGG" или "GGGGG".', - 'The pattern for hour in AM/PM must be "K" or "KK".' => 'Шаблона за часовете AM/PM трябва да е "K" или "KK".', - 'The pattern for hour in day must be "k" or "kk".' => 'Шаблона за часове в деня трябва да е "k" или "kk".', - 'The pattern for minutes must be "m" or "mm".' => 'Шаблона за минути трябва да е "m" или "mm".', - 'The pattern for month must be "M", "MM", "MMM", or "MMMM".' => 'Шаблона за месец трябва да е "M", "MM", "MMM", или "MMMM".', - 'The pattern for seconds must be "s" or "ss".' => 'Шаблона за секунда трябва да е "s" или "ss".', - 'The pattern for time zone must be "z" or "v".' => 'Шаблона на часовия пояс трябва да е "z" или "v".', - 'The pattern for week in month must be "W".' => 'Шаблона за седмица в месеца трябва да е "W".', - 'The pattern for week in year must be "w".' => 'Шаблона за седмица в годината трябва да е "w".', - 'The queue is empty.' => 'Опашката е празна.', - 'The relation "{relation}" in active record class "{class}" is not specified correctly: the join table "{joinTable}" given in the foreign key cannot be found in the database.' => 'Реалцията "{relation}" в active record класа "{class}" не е зададен коректно: таблицата "{joinTable}" задаваща ключа не може да бъде намерена в базата от данни.', - 'The relation "{relation}" in active record class "{class}" is specified with an incomplete foreign key. The foreign key must consist of columns referencing both joining tables.' => 'Релацията "{relation}" в active record класа "{class}" е с невалидно зададен ключ. Ключа трябва да се състой от полета засягащи и двете таблици.', - 'The relation "{relation}" in active record class "{class}" is specified with an invalid foreign key "{key}". The foreign key does not point to either joining table.' => 'Релацията "{relation}" в active record класа "{class}" е с невалидно зададен ключ "{key}". Ключа не води до която и да е от таблиците.', - 'The relation "{relation}" in active record class "{class}" is specified with an invalid foreign key. The format of the foreign key must be "joinTable(fk1,fk2,...)".' => 'Релацията "{relation}" в active record класа "{class}" е с невалидно зададен клюя. Формата на ключа трябва да е "joinTable(fk1,fk2,...)"', - 'The requested controller "{controller}" does not exist.' => 'Поискания контролер "{controller}" не е намерен.', - 'The requested view "{name}" is not found.' => 'Поискания изглед "{name}" не е намерено.', - 'The stack is empty.' => 'Стека е празен', - 'The system is unable to find the requested action "{action}".' => 'Системата не може да намери действието "{action}"', - 'The system view path "{path}" is not a valid directory.' => 'Пътя към системния изглед "{path}" не е валидна директория.', - 'The table "{table}" for active record class "{class}" cannot be found in the database.' => 'Таблицата "{table}" за active record класа "{class}" не може да бъде намерена в базата данни.', - 'The value for the primary key "{key}" is not supplied when querying the table "{table}".' => 'Стойноста на първичния ключа "{key}" не се поддържа при заявки към таблицата "{table}".', - 'The verification code is incorrect.' => 'Кода за валидация е грешен', - 'The view path "{path}" is not a valid directory.' => 'Пътят до view файла "{path}" е невалидна ', - 'Theme directory "{directory}" does not exist.' => 'Директорията на темата "{directory}" не съществува', - 'This content requires the Adobe Flash Player.' => 'Съдържанието изисква Adobe Flash Player.', - 'Unable to add an item whose name is the same as an existing item.' => 'Грешка при добавянето на обект, чието име е същото като името на съществуващ обект', - 'Unable to change the item name. The name "{name}" is already used by another item.' => 'Грешка при смяната на името. Името "{name}" вече се използва.', - 'Unable to create application state file "{file}". Make sure the directory containing the file exists and is writable by the Web server process.' => 'Грешка при създаването на application state файл "{file}". Проверете дали директорията, която съдържа файла съществува и дали има съответните права над нея.', - 'Unable to find the decorator view "{view}".' => 'Грешка при търсенето на "{view}".', - 'Unable to lock file "{file}" for reading.' => 'Не може да намери файла "{file}" за четене', - 'Unable to lock file "{file}" for writing.' => 'Не може да намери файла "{file}" за запис', - 'Unable to read file "{file}".' => 'Грешка при четенето на "{file}"', - 'Unable to replay the action "{object}.{method}". The method does not exist.' => 'Грешка при повторението на действието "{object}.{method}". Метода не съществува.', - 'Unable to write file "{file}".' => 'Грешка при писането на файла "{file}"', - 'Unknown authorization item "{name}".' => 'Неизвестен елемент за оторизация "{name}"', - 'Unrecognized locale "{locale}".' => 'Неразпознат "{locale}". ', - 'View file "{file}" does not exist.' => 'View файла "{file}" не съществува', - 'Yii application can only be created once.' => 'Yii приложението може да бъде стартирано само веднъж', - 'You are not authorized to perform this action.' => 'Вие не сте оторизиран за да изпълните това действие', - 'Your request is not valid.' => 'Вашата заявка е невалидна', - '{attribute} "{value}" has already been taken.' => '{attribute} "{value}" вече съществува', - '{attribute} cannot be blank.' => 'Полето {attribute} не може да бъде празно', - '{attribute} is invalid.' => 'Грешка в {attribute}', - '{attribute} is not a valid URL.' => '{attribute} е невалиден URL', - '{attribute} is not a valid email address.' => '{attribute} е невалиден email адрес', - '{attribute} is not in the list.' => '{attribute} не е в списъка', - '{attribute} is of the wrong length (should be {length} characters).' => '{attribute} е с грешна дължина(трябва да е {length} символа)', - '{attribute} is too big (maximum is {max}).' => '{attribute} е прекалено голям (максимума е {max})', - '{attribute} is too long (maximum is {max} characters).' => '{attribute} трябва да бъде максимум {max} символа', - '{attribute} is too short (minimum is {min} characters).' => ' {attribute} трябва да бъде минимум {min} символа', - '{attribute} is too small (minimum is {min}).' => ' {attribute} e прекалено малак (минимума е {min}). ', - '{attribute} must be a number.' => '{attribute} трябва да е число', - '{attribute} must be an integer.' => '{attribute} трябва да бъде integer', - '{attribute} must be repeated exactly.' => 'Моля, повторете {attribute} точно!', - '{attribute} must be {type}.' => '{attribute} трябва да бъде от тип {type}', - '{className} does not support add() functionality.' => '{className} не поддържа свойството add()', - '{className} does not support delete() functionality.' => '{className} не поддържа свойството delete()', - '{className} does not support flush() functionality.' => '{className} не поддържа свойството flush()', - '{className} does not support get() functionality.' => '{className} не поддържа свойството get()', - '{className} does not support set() functionality.' => '{className} не поддържа свойството set()', - '{class} does not have a method named "{name}".' => '{class} няма метод "{name}".', - '{class} does not have attribute "{attribute}".' => '{class} няма свойство "{attribute}"', - '{class} does not have attribute "{name}".' => '{class} няма свойсвто "{name}"', - '{class} does not have relation "{name}".' => '{class} няма релация "{name}". ', - '{class} does not support fetching all table names.' => '{class} не поддържа fetching на виски имена на таблици.', - '{class} has an invalid validation rule. The rule must specify attributes to be validated and the validator name.' => '{class} има невалидно правило за валидация. Правилото трябва да указва атрибута, който трябва да се валидира и името на валидатора.', - '{class} must specify "model" and "attribute" or "name" property values.' => '{class} трябва да указва "model" и "attribute" или "name" стойности.', - '{class}.allowAutoLogin must be set true in order to use cookie-based authentication.' => '{class}.allowAutoLogin трябва да бъде true, за да се използва оторизация базирана на бисквитки.', - '{class}::authenticate() must be implemented.' => '{class}::authenticate() трябва да бъде имплементиран', - '{controller} cannot find the requested view "{view}".' => 'Контролера {controller} не може да намери поисканото view "{view}"', - '{controller} contains improperly nested widget tags in its view "{view}". A {widget} widget does not have an endWidget() call.' => '{controller} съдържа неправилно поставени widget тагове в неговия "{view}" файл. {widget} widget няма извикан endWidget().', - '{controller} has an extra endWidget({id}) call in its view.' => '{controller} има допълнителен endWidget({id}) извикан в негото view.', - '{widget} cannot find the view "{view}".' => '{widget} не може да намери view файла "{view}"', + '"{path}" is not a valid directory.' => '', + '< Previous' => '', + '<< First' => '', + 'Active Record requires a "db" CDbConnection application component.' => '', + 'Active record "{class}" has an invalid configuration for relation "{relation}". It must specify the relation type, the related active record class and the foreign key.' => '', + 'Active record "{class}" is trying to select an invalid column "{column}". Note, the column must exist in the table or be an expression with alias.' => '', + 'Alias "{alias}" is invalid. Make sure it points to an existing directory or file.' => '', + 'Application base path "{path}" is not a valid directory.' => '', + 'Application runtime path "{path}" is not valid. Please make sure it is a directory writable by the Web server process.' => '', + 'Authorization item "{item}" has already been assigned to user "{user}".' => '', + 'CApcCache requires PHP apc extension to be loaded.' => '', + 'CAssetManager.basePath "{path}" is invalid. Please make sure the directory exists and is writable by the Web server process.' => '', + 'CCacheHttpSession.cacheID is invalid. Please make sure "{id}" refers to a valid cache application component.' => '', + 'CCaptchaValidator.action "{id}" is invalid. Unable to find such an action in the current controller.' => '', + 'CDbAuthManager.connectionID "{id}" is invalid. Please make sure it refers to the ID of a CDbConnection application component.' => '', + 'CDbCache.connectionID "{id}" is invalid. Please make sure it refers to the ID of a CDbConnection application component.' => '', + 'CDbCacheDependency.sql cannot be empty.' => '', + 'CDbCommand failed to execute the SQL statement: {error}' => '', + 'CDbCommand failed to prepare the SQL statement: {error}' => '', + 'CDbConnection does not support reading schema for {driver} database.' => '', + 'CDbConnection failed to open the DB connection: {error}' => '', + 'CDbConnection is inactive and cannot perform any DB operations.' => '', + 'CDbConnection.connectionString cannot be empty.' => '', + 'CDbDataReader cannot rewind. It is a forward-only reader.' => '', + 'CDbHttpSession.connectionID "{id}" is invalid. Please make sure it refers to the ID of a CDbConnection application component.' => '', + 'CDbLogRoute requires database table "{table}" to store log messages.' => '', + 'CDbLogRoute.connectionID "{id}" does not point to a valid CDbConnection application component.' => '', + 'CDbMessageSource.connectionID is invalid. Please make sure "{id}" refers to a valid database application component.' => '', + 'CDbTransaction is inactive and cannot perform commit or roll back operations.' => '', + 'CDirectoryCacheDependency.directory cannot be empty.' => '', + 'CFileCacheDependency.fileName cannot be empty.' => '', + 'CFileLogRoute.logPath "{path}" does not point to a valid directory. Make sure the directory exists and is writable by the Web server process.' => '', + 'CFilterChain can only take objects implementing the IFilter interface.' => '', + 'CFlexWidget.baseUrl cannot be empty.' => '', + 'CFlexWidget.name cannot be empty.' => '', + 'CGlobalStateCacheDependency.stateName cannot be empty.' => '', + 'CHttpCookieCollection can only hold CHttpCookie objects.' => '', + 'CHttpRequest is unable to determine the entry script URL.' => '', + 'CHttpRequest is unable to determine the path info of the request.' => '', + 'CHttpRequest is unable to determine the request URI.' => '', + 'CHttpSession.cookieMode can only be "none", "allow" or "only".' => '', + 'CHttpSession.gcProbability "{value}" is invalid. It must be an integer between 0 and 100.' => '', + 'CHttpSession.savePath "{path}" is not a valid directory.' => '', + 'CMemCache requires PHP memcache extension to be loaded.' => '', + 'CMemCache server configuration must be an array.' => '', + 'CMemCache server configuration must have "host" value.' => '', + 'CMultiFileUpload.name is required.' => '', + 'CProfileLogRoute found a mismatching code block "{token}". Make sure the calls to Yii::beginProfile() and Yii::endProfile() be properly nested.' => '', + 'CProfileLogRoute.report "{report}" is invalid. Valid values include "summary" and "callstack".' => '', + 'CSecurityManager requires PHP mcrypt extension to be loaded in order to use data encryption feature.' => '', + 'CSecurityManager.encryptionKey cannot be empty.' => '', + 'CSecurityManager.validation must be either "MD5" or "SHA1".' => '', + 'CSecurityManager.validationKey cannot be empty.' => '', + 'CTypedList<{type}> can only hold objects of {type} class.' => '', + 'CUrlManager.UrlFormat must be either "path" or "get".' => '', + 'CXCache requires PHP XCache extension to be loaded.' => '', + 'Cache table "{tableName}" does not exist.' => '', + 'Cannot add "{child}" as a child of "{name}". A loop has been detected.' => '', + 'Cannot add "{child}" as a child of "{parent}". A loop has been detected.' => '', + 'Cannot add "{name}" as a child of itself.' => '', + 'Cannot add an item of type "{child}" to an item of type "{parent}".' => '', + 'Either "{parent}" or "{child}" does not exist.' => '', + 'Error: Table "{table}" does not have a primary key.' => '', + 'Error: Table "{table}" has a composite primary key which is not supported by crud command.' => '', + 'Event "{class}.{event}" is attached with an invalid handler "{handler}".' => '', + 'Event "{class}.{event}" is not defined.' => '', + 'Failed to write the uploaded file "{file}" to disk.' => '', + 'File upload was stopped by extension.' => '', + 'Filter "{filter}" is invalid. Controller "{class}" does have the filter method "filter{filter}".' => '', + 'Get a new code' => '', + 'Go to page: ' => '', + 'Invalid MO file revision: {revision}.' => '', + 'Invalid MO file: {file} (magic: {magic}).' => '', + 'Invalid enumerable value "{value}". Please make sure it is among ({enum}).' => '', + 'Last >>' => '', + 'List data must be an array or an object implementing Traversable.' => '', + 'List index "{index}" is out of bound.' => '', + 'Login Required' => '', + 'Map data must be an array or an object implementing Traversable.' => '', + 'Missing the temporary folder to store the uploaded file "{file}".' => '', + 'Next >' => '', + 'No columns are being updated for table "{table}".' => '', + 'No counter columns are being updated for table "{table}".' => '', + 'Object configuration must be an array containing a "class" element.' => '', + 'Please fix the following input errors:' => '', + 'Property "{class}.{property}" is not defined.' => '', + 'Property "{class}.{property}" is read only.' => '', + 'Queue data must be an array or an object implementing Traversable.' => '', + 'Relation "{name}" is not defined in active record class "{class}".' => '', + 'Stack data must be an array or an object implementing Traversable.' => '', + 'Table "{table}" does not have a column named "{column}".' => '', + 'Table "{table}" does not have a primary key defined.' => '', + 'The "filter" property must be specified with a valid callback.' => '', + 'The "pattern" property must be specified with a valid regular expression.' => '', + 'The "view" property is required.' => '', + 'The CSRF token could not be verified.' => '', + 'The URL pattern "{pattern}" for route "{route}" is not a valid regular expression.' => '', + 'The active record cannot be deleted because it is new.' => '', + 'The active record cannot be inserted to database because it is not new.' => '', + 'The active record cannot be updated because it is new.' => '', + 'The asset "{asset}" to be published does not exist.' => '', + 'The column "{column}" is not a foreign key in table "{table}".' => '', + 'The command path "{path}" is not a valid directory.' => '', + 'The controller path "{path}" is not a valid directory.' => '', + 'The file "{file}" cannot be uploaded. Only files with these extensions are allowed: {extensions}.' => '', + 'The file "{file}" is too large. Its size cannot exceed {limit} bytes.' => '', + 'The file "{file}" is too small. Its size cannot be smaller than {limit} bytes.' => '', + 'The file "{file}" was only partially uploaded.' => '', + 'The first element in a filter configuration must be the filter class.' => '', + 'The item "{name}" does not exist.' => '', + 'The item "{parent}" already has a child "{child}".' => '', + 'The layout path "{path}" is not a valid directory.' => '', + 'The list is read only.' => '', + 'The map is read only.' => '', + 'The pattern for 12 hour format must be "h" or "hh".' => '', + 'The pattern for 24 hour format must be "H" or "HH".' => '', + 'The pattern for AM/PM marker must be "a".' => '', + 'The pattern for day in month must be "F".' => '', + 'The pattern for day in year must be "D", "DD" or "DDD".' => '', + 'The pattern for day of the month must be "d" or "dd".' => '', + 'The pattern for day of the week must be "E", "EE", "EEE", "EEEE" or "EEEEE".' => '', + 'The pattern for era must be "G", "GG", "GGG", "GGGG" or "GGGGG".' => '', + 'The pattern for hour in AM/PM must be "K" or "KK".' => '', + 'The pattern for hour in day must be "k" or "kk".' => '', + 'The pattern for minutes must be "m" or "mm".' => '', + 'The pattern for month must be "M", "MM", "MMM", or "MMMM".' => '', + 'The pattern for seconds must be "s" or "ss".' => '', + 'The pattern for time zone must be "z" or "v".' => '', + 'The pattern for week in month must be "W".' => '', + 'The pattern for week in year must be "w".' => '', + 'The queue is empty.' => '', + 'The relation "{relation}" in active record class "{class}" is not specified correctly: the join table "{joinTable}" given in the foreign key cannot be found in the database.' => '', + 'The relation "{relation}" in active record class "{class}" is specified with an incomplete foreign key. The foreign key must consist of columns referencing both joining tables.' => '', + 'The relation "{relation}" in active record class "{class}" is specified with an invalid foreign key "{key}". The foreign key does not point to either joining table.' => '', + 'The relation "{relation}" in active record class "{class}" is specified with an invalid foreign key. The format of the foreign key must be "joinTable(fk1,fk2,...)".' => '', + 'The requested controller "{controller}" does not exist.' => '', + 'The requested view "{name}" is not found.' => '', + 'The stack is empty.' => '', + 'The system is unable to find the requested action "{action}".' => '', + 'The system view path "{path}" is not a valid directory.' => '', + 'The table "{table}" for active record class "{class}" cannot be found in the database.' => '', + 'The value for the primary key "{key}" is not supplied when querying the table "{table}".' => '', + 'The verification code is incorrect.' => '', + 'The view path "{path}" is not a valid directory.' => '', + 'Theme directory "{directory}" does not exist.' => '', + 'This content requires the Adobe Flash Player.' => '', + 'Unable to add an item whose name is the same as an existing item.' => '', + 'Unable to change the item name. The name "{name}" is already used by another item.' => '', + 'Unable to create application state file "{file}". Make sure the directory containing the file exists and is writable by the Web server process.' => '', + 'Unable to find the decorator view "{view}".' => '', + 'Unable to lock file "{file}" for reading.' => '', + 'Unable to lock file "{file}" for writing.' => '', + 'Unable to read file "{file}".' => '', + 'Unable to replay the action "{object}.{method}". The method does not exist.' => '', + 'Unable to write file "{file}".' => '', + 'Unknown authorization item "{name}".' => '', + 'Unrecognized locale "{locale}".' => '', + 'View file "{file}" does not exist.' => '', + 'Yii application can only be created once.' => '', + 'You are not authorized to perform this action.' => '', + 'Your request is not valid.' => '', + '{attribute} "{value}" has already been taken.' => '', + '{attribute} cannot be blank.' => '', + '{attribute} is invalid.' => '', + '{attribute} is not a valid URL.' => '', + '{attribute} is not a valid email address.' => '', + '{attribute} is not in the list.' => '', + '{attribute} is of the wrong length (should be {length} characters).' => '', + '{attribute} is too big (maximum is {max}).' => '', + '{attribute} is too long (maximum is {max} characters).' => '', + '{attribute} is too short (minimum is {min} characters).' => '', + '{attribute} is too small (minimum is {min}).' => '', + '{attribute} must be a number.' => '', + '{attribute} must be an integer.' => '', + '{attribute} must be repeated exactly.' => '', + '{attribute} must be {type}.' => '', + '{className} does not support add() functionality.' => '', + '{className} does not support delete() functionality.' => '', + '{className} does not support flush() functionality.' => '', + '{className} does not support get() functionality.' => '', + '{className} does not support set() functionality.' => '', + '{class} does not have a method named "{name}".' => '', + '{class} does not have attribute "{attribute}".' => '', + '{class} does not have attribute "{name}".' => '', + '{class} does not have relation "{name}".' => '', + '{class} does not support fetching all table names.' => '', + '{class} has an invalid validation rule. The rule must specify attributes to be validated and the validator name.' => '', + '{class} must specify "model" and "attribute" or "name" property values.' => '', + '{class}.allowAutoLogin must be set true in order to use cookie-based authentication.' => '', + '{class}::authenticate() must be implemented.' => '', + '{controller} cannot find the requested view "{view}".' => '', + '{controller} contains improperly nested widget tags in its view "{view}". A {widget} widget does not have an endWidget() call.' => '', + '{controller} has an extra endWidget({id}) call in its view.' => '', + '{widget} cannot find the view "{view}".' => '', ); diff --git a/framework/messages/de/yii.php b/framework/messages/de/yii.php index 77c1d58070..4bba31b9fd 100644 --- a/framework/messages/de/yii.php +++ b/framework/messages/de/yii.php @@ -118,7 +118,7 @@ 'Queue data must be an array or an object implementing Traversable.' => 'Queue-Daten müssen ein Array sein oder ein Objekt, das das Interface Traversable implementiert.', 'Relation "{name}" is not defined in active record class "{class}".' => 'Relation "{name}" ist in der ActiveRecord-Klasse "{class}" nicht definiert.', 'Stack data must be an array or an object implementing Traversable.' => 'Stack-Daten müssen ein Array sein oder ein Objekt, das das Interface Traversable implementiert.', - 'Table "{table}" does not have a column named "{column}".' => 'Tabelle "{table}" hat kein Feld namens "{column"}.', + 'Table "{table}" does not have a column named "{column}".' => 'Tabelle "{table}" hat kein Feld namens "{column}".', 'The "filter" property must be specified with a valid callback.' => 'Für "filter" muss ein gültiger Callback angegeben werden.', 'The "pattern" property must be specified with a valid regular expression.' => 'Für "pattern" muss ein gültiger Regulärer Ausdruck angegeben werden.', 'The CSRF token could not be verified.' => 'Der CSRF-Token konnte nicht verifiziert werden.', diff --git a/framework/messages/es/yii.php b/framework/messages/es/yii.php index 91cc785fdd..9e1efe0c2d 100644 --- a/framework/messages/es/yii.php +++ b/framework/messages/es/yii.php @@ -208,7 +208,7 @@ '{attribute} is not in the list.' => '{attribute} no se encuentra en la lista.', '{attribute} is of the wrong length (should be {length} characters).' => '{attribute} tiene un largo incorrecto (debe ser de {length} caracteres)', '{attribute} is too big (maximum is {max}).' => '{attribute} es muy grande (el máximo es {max}).', - '{attribute} is too long (maximum is {max} characters).' => '{attribute} es muy largo (el máximo es de {min} caracteres)', + '{attribute} is too long (maximum is {max} characters).' => '{attribute} es muy largo (el máximo es de {max} caracteres)', '{attribute} is too short (minimum is {min} characters).' => '{attribute} es muy corto (el mínimo es de {min} caracteres)', '{attribute} is too small (minimum is {min}).' => '{attribute} es muy chico (el mínimo es {min}).', '{attribute} must be a number.' => '{attribute} debe ser un número.', diff --git a/framework/messages/ru/yii.php b/framework/messages/ru/yii.php index 794a1662a5..d1cc6c41ec 100644 --- a/framework/messages/ru/yii.php +++ b/framework/messages/ru/yii.php @@ -22,193 +22,192 @@ 'Last >>' => 'Последняя >>', 'Next >' => 'Следующая >', 'The asset "{asset}" to be published does not exist.' => 'Необходимый для отображения asset "{asset}" не существует.', - 'The module path "{path}" is not a valid directory.' => 'Путь модуля "{path}" не является правильной директорией.', + 'The module path "{path}" is not a valid directory.' => 'Путь модуля "{path}" не является директорией.', 'Unable to count records with composite primary keys. Please explicitly specify the SELECT option in the query criteria.' => 'Невозможно посчитать записи с составными основными ключами. Явно укажите опции для SELECT в критерии запроса.', 'Unable to resolve the request "{route}".' => 'Невозможно обработать запрос "{route}".', - '{class} does not have a method named "{name}".' => '{class} не содержит метода "{name}".', - '{class} does not have attribute "{attribute}".' => '{class} не содержит атрибута "{attribute}".', - '{class} does not have relation "{name}".' => '{class} не содержит отношения "{name}".', - '{class} does not support fetching all table names.' => '{class} не поддерживает выборку имён всех таблиц.', - '"{path}" is not a valid directory.' => '"{path}" не является правильной директорией.', + '{class} does not have a method named "{name}".' => 'Класс {class} не содержит метода "{name}".', + '{class} does not have attribute "{attribute}".' => 'Класс {class} не содержит атрибута "{attribute}".', + '{class} does not have relation "{name}".' => 'Класс {class} не содержит отношения "{name}".', + '{class} does not support fetching all table names.' => 'Класс {class} не поддерживает выборку имён всех таблиц.', + '"{path}" is not a valid directory.' => 'Путь "{path}" не является правильной директорией.', 'Active Record requires a "db" CDbConnection application component.' => 'ActiveRecord требует компонент приложения "db" CDbConnection.', - 'Active record "{class}" has an invalid configuration for relation "{relation}". It must specify the relation type, the related active record class and the foreign key.' => 'Отношение "{relation}" класса Active record "{class}" сконфигурировано не верно. Вы дожны указать тип отношения, связанный отношением класс active record и внешний ключ.', + 'Active record "{class}" has an invalid configuration for relation "{relation}". It must specify the relation type, the related active record class and the foreign key.' => 'Отношение "{relation}" класса Active record "{class}" сконфигурировано не верно. Вы должны указать тип отношения, связанный отношением класс active record и внешний ключ.', 'Active record "{class}" is trying to select an invalid column "{column}". Note, the column must exist in the table or be an expression with alias.' => 'ActiveRecord "{class}" пытается выбрать недопустимый столбец "{column}". Примечание: столбец должен существовать в таблице или являться выражением с алиасом.', 'Alias "{alias}" is invalid. Make sure it points to an existing directory or file.' => 'Неправильный алиас "{alias}". Убедитесь, что он указывает на существующую директорию или файл.', - 'Application base path "{path}" is not a valid directory.' => '', - 'Application runtime path "{path}" is not valid. Please make sure it is a directory writable by the Web server process.' => '', - 'Authorization item "{item}" has already been assigned to user "{user}".' => '', + 'Application base path "{path}" is not a valid directory.' => 'Базовый (base) путь приложения "{path}" не является директорией.', + 'Application runtime path "{path}" is not valid. Please make sure it is a directory writable by the Web server process.' => 'Рабочий (runtime) путь приложения "{path}" задан неверно. Удостоверьтесь, что директория доступна для записи пользователю, под которым запущен веб-сервер.', + 'Authorization item "{item}" has already been assigned to user "{user}".' => 'Элемент (item) авторизации "{item}" уже назначен пользователю "{user}".', 'CApcCache requires PHP apc extension to be loaded.' => 'CApcCache требует загруженного расширения PHP APC.', - 'CAssetManager.basePath "{path}" is invalid. Please make sure the directory exists and is writable by the Web server process.' => 'CAssetManager.basePath "{path}" не верен. Убедитесь, что директория существует и доступна для записи пользователю, под которым запущен веб-сервер.', - 'CCacheHttpSession.cacheID is invalid. Please make sure "{id}" refers to a valid cache application component.' => '', - 'CCaptchaValidator.action "{id}" is invalid. Unable to find such an action in the current controller.' => '', - 'CDbAuthManager.connectionID "{id}" is invalid. Please make sure it refers to the ID of a CDbConnection application component.' => '', - 'CDbCache.connectionID "{id}" is invalid. Please make sure it refers to the ID of a CDbConnection application component.' => '', - 'CDbCacheDependency.sql cannot be empty.' => '', - 'CDbCommand failed to execute the SQL statement: {error}' => '', - 'CDbCommand failed to prepare the SQL statement: {error}' => '', - 'CDbConnection does not support reading schema for {driver} database.' => '', - 'CDbConnection failed to open the DB connection: {error}' => '', - 'CDbConnection is inactive and cannot perform any DB operations.' => '', - 'CDbConnection.connectionString cannot be empty.' => '', - 'CDbDataReader cannot rewind. It is a forward-only reader.' => '', - 'CDbHttpSession.connectionID "{id}" is invalid. Please make sure it refers to the ID of a CDbConnection application component.' => '', - 'CDbLogRoute requires database table "{table}" to store log messages.' => '', - 'CDbLogRoute.connectionID "{id}" does not point to a valid CDbConnection application component.' => '', - 'CDbMessageSource.connectionID is invalid. Please make sure "{id}" refers to a valid database application component.' => '', - 'CDbTransaction is inactive and cannot perform commit or roll back operations.' => '', - 'CDirectoryCacheDependency.directory cannot be empty.' => '', - 'CFileCacheDependency.fileName cannot be empty.' => '', - 'CFileLogRoute.logPath "{path}" does not point to a valid directory. Make sure the directory exists and is writable by the Web server process.' => '', - 'CFilterChain can only take objects implementing the IFilter interface.' => '', - 'CFlexWidget.baseUrl cannot be empty.' => 'CFlexWidget.baseUrl не должно быть пустым.', - 'CFlexWidget.name cannot be empty.' => 'CFlexWidget.name не должно быть пустым.', - 'CGlobalStateCacheDependency.stateName cannot be empty.' => 'CGlobalStateCacheDependency.stateName не должно быть пустым.', - 'CHttpCookieCollection can only hold CHttpCookie objects.' => 'CHttpCookieCollection должно содержать только объекты типа CHttpCookie.', - 'CHttpRequest is unable to determine the entry script URL.' => '', - 'CHttpRequest is unable to determine the path info of the request.' => '', - 'CHttpRequest is unable to determine the request URI.' => '', - 'CHttpSession.cookieMode can only be "none", "allow" or "only".' => 'CHttpSession.cookieMode должно иметь значения "none", "allow" или "only".', - 'CHttpSession.gcProbability "{value}" is invalid. It must be an integer between 0 and 100.' => '', - 'CHttpSession.savePath "{path}" is not a valid directory.' => '', - 'CMemCache requires PHP memcache extension to be loaded.' => 'CMemCache требует расширения PHP memcache.', + 'CAssetManager.basePath "{path}" is invalid. Please make sure the directory exists and is writable by the Web server process.' => 'Путь CAssetManager.basePath "{path}" задан неверно. Удостоверьтесь, что директория существует и доступна для записи пользователю, под которым запущен веб-сервер.', + 'CCacheHttpSession.cacheID is invalid. Please make sure "{id}" refers to a valid cache application component.' => 'Идентификатор CCacheHttpSession.cacheID задан неверно. Удостоверьтесь, что "{id}" соответствует существующему компоненту кэша приложения.', + 'CCaptchaValidator.action "{id}" is invalid. Unable to find such an action in the current controller.' => 'Действие CCaptchaValidator.action "{id}" задано неверно: действия не найдено в текущем контроллере.', + 'CDbAuthManager.connectionID "{id}" is invalid. Please make sure it refers to the ID of a CDbConnection application component.' => 'Идентификатор CDbAuthManager.connectionID "{id}" задан неверно. Удостоверьтесь, что он соответствует идентификатору (ID) компонента CDbConnection вашего приложения.', + 'CDbCache.connectionID "{id}" is invalid. Please make sure it refers to the ID of a CDbConnection application component.' => 'Идентификатор CDbCache.connectionID "{id}" задан неверно. Удостоверьтесь, что он соответствует идентификатору (ID) компонента CDbConnection вашего приложения.', + 'CDbCacheDependency.sql cannot be empty.' => 'Файл CDbCacheDependency.sql должен содержать какие-либо запросы.', + 'CDbCommand failed to execute the SQL statement: {error}' => 'CDbCommand не удалось исполнить SQL-запрос: {error}', + 'CDbCommand failed to prepare the SQL statement: {error}' => 'CDbCommand не удалось подготовить SQL-запрос: {error}', + 'CDbConnection does not support reading schema for {driver} database.' => 'CDbConnection не поддерживает чтения из базы данных {driver}.', + 'CDbConnection failed to open the DB connection: {error}' => 'CDbConnection не удалось открыть соединение с базой данных: {error}', + 'CDbConnection is inactive and cannot perform any DB operations.' => 'Соединение CDbConnection не активно, операции над базой данных невозможны.', + 'CDbConnection.connectionString cannot be empty.' => 'Параметр CDbConnection.connectionString должен быть заполнен.', + 'CDbDataReader cannot rewind. It is a forward-only reader.' => 'Компонент CDbDataReader не поддерживает обратное чтение. Этот компонент только для чтения в прямом направлении.', + 'CDbHttpSession.connectionID "{id}" is invalid. Please make sure it refers to the ID of a CDbConnection application component.' => 'Идентификатор CDbHttpSession.connectionID "{id}" задан неверно. Удостоверьтесь, что он соответствует идентификатору (ID) компонента CDbConnection вашего приложения.', + 'CDbLogRoute requires database table "{table}" to store log messages.' => 'Компоненту CDbLogRoute требуется доступ к таблице "{table}" для хранения журнала событий.', + 'CDbLogRoute.connectionID "{id}" does not point to a valid CDbConnection application component.' => 'Идентификатор CDbLogRoute.connectionID "{id}" указывает на неверный компонент CDbConnection вашего приложения.', + 'CDbMessageSource.connectionID is invalid. Please make sure "{id}" refers to a valid database application component.' => 'CDbMessageSource.connectionID указан неверно. Удостоверьтесь, что "{id}" указывает на правильный компонент для работы с базой данных вашего приложения.', + 'CDbTransaction is inactive and cannot perform commit or roll back operations.' => 'Компонент CDbTransaction не активен, операции фиксации (commit) и отката (roll back) не могут быть совершены.', + 'CDirectoryCacheDependency.directory cannot be empty.' => 'Параметр CDirectoryCacheDependency.directory должен быть заполнен.', + 'CFileCacheDependency.fileName cannot be empty.' => 'Параметр CFileCacheDependency.fileName должен быть заполнен.', + 'CFileLogRoute.logPath "{path}" does not point to a valid directory. Make sure the directory exists and is writable by the Web server process.' => 'Путь CFileLogRoute.logPath "{path}" задан неверно. Удостоверьтесь, что директория существует и доступна для записи пользователю, под которым запущен веб-сервер.', + 'CFilterChain can only take objects implementing the IFilter interface.' => 'CFilterChain может содержать только объекты реализующие интерфейс IFilter.', + 'CFlexWidget.baseUrl cannot be empty.' => 'Параметр CFlexWidget.baseUrl должен быть заполнен.', + 'CFlexWidget.name cannot be empty.' => 'Параметр CFlexWidget.name должен быть заполнен.', + 'CGlobalStateCacheDependency.stateName cannot be empty.' => 'Параметр CGlobalStateCacheDependency.stateName должен быть заполнен.', + 'CHttpCookieCollection can only hold CHttpCookie objects.' => 'CHttpCookieCollection может содержать только объекты типа CHttpCookie.', + 'CHttpRequest is unable to determine the entry script URL.' => 'Компоненту CHttpRequest не удалось определить URL входного скрипта.', + 'CHttpRequest is unable to determine the path info of the request.' => 'Компоненту CHttpRequest не удалось определить информацию о пути, содержащуюся в запросе.', + 'CHttpRequest is unable to determine the request URI.' => 'Компоненту CHttpRequest не удалось определить URI запроса.', + 'CHttpSession.cookieMode can only be "none", "allow" or "only".' => 'Параметр CHttpSession.cookieMode может принимать только значения "none", "allow" или "only".', + 'CHttpSession.gcProbability "{value}" is invalid. It must be an integer between 0 and 100.' => 'Значение параметра CHttpSession.gcProbability "{value}" задано неверно. Необходимо указать число от 0 до 100.', + 'CHttpSession.savePath "{path}" is not a valid directory.' => 'Путь CHttpSession.savePath "{path}" не является директорией.', + 'CMemCache requires PHP memcache extension to be loaded.' => 'Компонент CMemCache требует расширения PHP memcache.', 'CMemCache server configuration must be an array.' => 'Конфигурация сервера CMemCache должна быть массивом.', 'CMemCache server configuration must have "host" value.' => 'Конфигурация сервера CMemCache должна содержать значение "host".', - 'CMultiFileUpload.name is required.' => 'CMultiFileUpload.name должно быть заполнено.', - 'CProfileLogRoute found a mismatching code block "{token}". Make sure the calls to Yii::beginProfile() and Yii::endProfile() be properly nested.' => '', - 'CProfileLogRoute.report "{report}" is invalid. Valid values include "summary" and "callstack".' => '', - 'CSecurityManager requires PHP mcrypt extension to be loaded in order to use data encryption feature.' => '', - 'CSecurityManager.encryptionKey cannot be empty.' => 'CSecurityManager.encryptionKey не должно быть пустым.', - 'CSecurityManager.validation must be either "MD5" or "SHA1".' => 'CSecurityManager.validation должно иметь значения "MD5" или "SHA1".', - 'CSecurityManager.validationKey cannot be empty.' => 'CSecurityManager.validationKey не должно быть пустым.', - 'CTypedList<{type}> can only hold objects of {type} class.' => '', - 'CUrlManager.UrlFormat must be either "path" or "get".' => '', - 'CXCache requires PHP XCache extension to be loaded.' => '', - 'Cache table "{tableName}" does not exist.' => '', - 'Cannot add "{child}" as a child of "{name}". A loop has been detected.' => '', - 'Cannot add "{child}" as a child of "{parent}". A loop has been detected.' => '', - 'Cannot add "{name}" as a child of itself.' => '', - 'Cannot add an item of type "{child}" to an item of type "{parent}".' => '', - 'Either "{parent}" or "{child}" does not exist.' => '', - 'Error: Table "{table}" does not have a primary key.' => '', - 'Error: Table "{table}" has a composite primary key which is not supported by crud command.' => '', - 'Event "{class}.{event}" is attached with an invalid handler "{handler}".' => '', - 'Event "{class}.{event}" is not defined.' => '', + 'CMultiFileUpload.name is required.' => 'Необходимо указать параметр CMultiFileUpload.name.', + 'CProfileLogRoute found a mismatching code block "{token}". Make sure the calls to Yii::beginProfile() and Yii::endProfile() be properly nested.' => 'Компонент CProfileLogRoute обнаружил неверный код "{token}". Удостоверьтесь, что вложенность вызовов Yii::beginProfile() и Yii::endProfile() соблюдается.', + 'CProfileLogRoute.report "{report}" is invalid. Valid values include "summary" and "callstack".' => 'Параметр CProfileLogRoute.report "{report}" задан неверно. Поддерживаются значения "summary" и "callstack".', + 'CSecurityManager requires PHP mcrypt extension to be loaded in order to use data encryption feature.' => 'Для использования возможности шифрования данных компоненту CSecurityManager требуется PHP-расширение mcrypt.', + 'CSecurityManager.encryptionKey cannot be empty.' => 'Параметр CSecurityManager.encryptionKey должен быть заполнен.', + 'CSecurityManager.validation must be either "MD5" or "SHA1".' => 'Параметр CSecurityManager.validation может принимать только значения "MD5" или "SHA1".', + 'CSecurityManager.validationKey cannot be empty.' => 'Параметр CSecurityManager.validationKey должен быть заполнен.', + 'CTypedList<{type}> can only hold objects of {type} class.' => 'CTypedList<{type}> может содержать только объекты класса {type}.', + 'CUrlManager.UrlFormat must be either "path" or "get".' => 'Параметр CUrlManager.UrlFormat может принимать только значения "path" или "get".', + 'CXCache requires PHP XCache extension to be loaded.' => 'Для работы компонента CXCache необходимо PHP-расширение XCache.', + 'Cache table "{tableName}" does not exist.' => 'Таблица для кэша "{tableName}" не существует.', + 'Cannot add "{child}" as a child of "{name}". A loop has been detected.' => 'Добавление элемента "{child}" в качестве потомка "{name}" невозможно, обнаружен бесконечный цикл.', + 'Cannot add "{child}" as a child of "{parent}". A loop has been detected.' => 'Добавление элемента "{child}" в качестве потомка "{parent} невозможно, обнаружен бесконечный цикл.', + 'Cannot add "{name}" as a child of itself.' => 'Элемент "{name}" не может стать потомком для самого себя.', + 'Cannot add an item of type "{child}" to an item of type "{parent}".' => 'Нельзя добавить элемент типа "{child}" к элементу типа "{parent}".', + 'Either "{parent}" or "{child}" does not exist.' => 'Либо "{parent}", либо "{child}" не существует.', + 'Error: Table "{table}" does not have a primary key.' => 'Ошибка: В таблице "{table}" отсутствует первичный ключ.', + 'Error: Table "{table}" has a composite primary key which is not supported by crud command.' => 'Ошибка: Таблица "{table}" содержит составной первичный ключ, работа с которым не поддерживается командами CRUD.', + 'Event "{class}.{event}" is attached with an invalid handler "{handler}".' => 'Событие "{class}.{event}" привязано неверным обработчиком "{handler}".', + 'Event "{class}.{event}" is not defined.' => 'Событие "{class}.{event}" не определено.', 'Failed to write the uploaded file "{file}" to disk.' => 'Не удалось записать загруженный файл "{file}" на диск.', - 'File upload was stopped by extension.' => '', - 'Filter "{filter}" is invalid. Controller "{class}" does have the filter method "filter{filter}".' => '', + 'File upload was stopped by extension.' => 'Загрузка файла прервана расширением.', + 'Filter "{filter}" is invalid. Controller "{class}" does have the filter method "filter{filter}".' => 'Фильтр "{filter}" указан неверно. В коде контроллер "{class}" метод фильтра "filter{filter}" не определен.', 'Get a new code' => 'Получить новый код', - 'Invalid MO file revision: {revision}.' => '', - 'Invalid MO file: {file} (magic: {magic}).' => '', - 'Invalid enumerable value "{value}". Please make sure it is among ({enum}).' => '', - 'List data must be an array or an object implementing Traversable.' => '', - 'List index "{index}" is out of bound.' => '', + 'Invalid MO file revision: {revision}.' => 'Не поддерживаемая версия MO файла: {revision}.', + 'Invalid MO file: {file} (magic: {magic}).' => 'Ошибка в MO файле: {file} (магия: {magic}).', + 'Invalid enumerable value "{value}". Please make sure it is among ({enum}).' => 'Неверно задано и значение "{value}". Поддерживаются следующие значение ({enum}).', + 'List data must be an array or an object implementing Traversable.' => 'Список должен быть представлен массивом или объектом, реализующим интерфейс Traversable.', + 'List index "{index}" is out of bound.' => 'Значение списка "{index}" выходит за его пределы.', 'Login Required' => 'Необходима авторизация', - 'Map data must be an array or an object implementing Traversable.' => '', - 'Missing the temporary folder to store the uploaded file "{file}".' => '', - 'No columns are being updated for table "{table}".' => '', - 'No counter columns are being updated for table "{table}".' => '', - 'Object configuration must be an array containing a "class" element.' => '', - 'Please fix the following input errors:' => '', - 'Property "{class}.{property}" is not defined.' => '', - 'Property "{class}.{property}" is read only.' => '', - 'Queue data must be an array or an object implementing Traversable.' => '', - 'Relation "{name}" is not defined in active record class "{class}".' => '', - 'Stack data must be an array or an object implementing Traversable.' => '', - 'Table "{table}" does not have a column named "{column}".' => '', - 'Table "{table}" does not have a primary key defined.' => '', - 'The "filter" property must be specified with a valid callback.' => '', - 'The "pattern" property must be specified with a valid regular expression.' => '', - 'The CSRF token could not be verified.' => '', - 'The URL pattern "{pattern}" for route "{route}" is not a valid regular expression.' => '', - 'The active record cannot be deleted because it is new.' => '', - 'The active record cannot be inserted to database because it is not new.' => '', - 'The active record cannot be updated because it is new.' => '', - 'The column "{column}" is not a foreign key in table "{table}".' => '', - 'The command path "{path}" is not a valid directory.' => '', - 'The controller path "{path}" is not a valid directory.' => '', - 'The file "{file}" cannot be uploaded. Only files with these extensions are allowed: {extensions}.' => '', - 'The file "{file}" is too large. Its size cannot exceed {limit} bytes.' => '', - 'The file "{file}" is too small. Its size cannot be smaller than {limit} bytes.' => '', - 'The file "{file}" was only partially uploaded.' => '', - 'The first element in a filter configuration must be the filter class.' => '', - 'The item "{name}" does not exist.' => '', - 'The item "{parent}" already has a child "{child}".' => '', - 'The layout path "{path}" is not a valid directory.' => '', - 'The list is read only.' => '', - 'The map is read only.' => '', - 'The pattern for 12 hour format must be "h" or "hh".' => '', - 'The pattern for 24 hour format must be "H" or "HH".' => '', - 'The pattern for AM/PM marker must be "a".' => '', - 'The pattern for day in month must be "F".' => '', - 'The pattern for day in year must be "D", "DD" or "DDD".' => '', - 'The pattern for day of the month must be "d" or "dd".' => '', - 'The pattern for day of the week must be "E", "EE", "EEE", "EEEE" or "EEEEE".' => '', - 'The pattern for era must be "G", "GG", "GGG", "GGGG" or "GGGGG".' => '', - 'The pattern for hour in AM/PM must be "K" or "KK".' => '', - 'The pattern for hour in day must be "k" or "kk".' => '', - 'The pattern for minutes must be "m" or "mm".' => '', - 'The pattern for month must be "M", "MM", "MMM", or "MMMM".' => '', - 'The pattern for seconds must be "s" or "ss".' => '', - 'The pattern for time zone must be "z" or "v".' => '', - 'The pattern for week in month must be "W".' => '', - 'The pattern for week in year must be "w".' => '', + 'Map data must be an array or an object implementing Traversable.' => 'Карта должна быть представлена массивом или объектом, реализующим интерфейс Traversable.', + 'Missing the temporary folder to store the uploaded file "{file}".' => 'Не найдена временна директория для хранения загруженного файла "{file}".', + 'No columns are being updated for table "{table}".' => 'Нет столбцов подлежащих обновлению в таблице "{table}".', + 'No counter columns are being updated for table "{table}".' => 'Нет столбцов-счетчиков подлежащих обновлению в таблице "{table}".', + 'Object configuration must be an array containing a "class" element.' => 'Конфигурация объекта должна быть представлена массивом, содержащим элемент "class".', + 'Please fix the following input errors:' => 'Необходимо исправить следующие ошибки:', + 'Property "{class}.{property}" is not defined.' => 'Не определено свойство "{class}.{property}".', + 'Property "{class}.{property}" is read only.' => 'Свойство "{class}.{property}" доступно только для чтения.', + 'Queue data must be an array or an object implementing Traversable.' => 'Запрос должен быть представлен массивом или объектом, реализующим интерфейс Traversable.', + 'Relation "{name}" is not defined in active record class "{class}".' => 'Отношение "{name}" не было определено в active record классе "{class}".', + 'Stack data must be an array or an object implementing Traversable.' => 'Стек должен быть представлен массивом или объектом, реализующим интерфейс Traversable.', + 'Table "{table}" does not have a column named "{column}".' => 'Таблица "{table}" не содержит столбца "{column}".', + 'Table "{table}" does not have a primary key defined.' => 'Первичный ключ для таблицы "{table}" не определен.', + 'The "filter" property must be specified with a valid callback.' => 'Свойство "filter" должно быть определено правильным обратным вызовом (callback).', + 'The "pattern" property must be specified with a valid regular expression.' => 'Свойство "pattern" должно быть определено правильным регулярным выражением.', + 'The CSRF token could not be verified.' => 'Невозможно определить CSRF.', + 'The URL pattern "{pattern}" for route "{route}" is not a valid regular expression.' => 'URL-шаблон "{pattern}" для пути "{route}" не является верным регулярным выражением.', + 'The active record cannot be deleted because it is new.' => 'Невозможно удалить запись active record из-за того, что она новая.', + 'The active record cannot be inserted to database because it is not new.' => 'Невозможно добавить запись active record в базу данных из-за того, что она не новая.', + 'The active record cannot be updated because it is new.' => 'Невозможно обновить запись active record из-за того, что она новая.', + 'The column "{column}" is not a foreign key in table "{table}".' => 'Столбец "{column}" не является внешним ключом таблицы "{table}".', + 'The command path "{path}" is not a valid directory.' => 'Командный путь "{path}" не является директорией.', + 'The controller path "{path}" is not a valid directory.' => 'Путь к контроллерам "{path}" не является директорией.', + 'The file "{file}" cannot be uploaded. Only files with these extensions are allowed: {extensions}.' => 'Файл "{file}" не может быть загружен. Разрешена загрузка файлов только со следующими расширениями: {extensions}.', + 'The file "{file}" is too large. Its size cannot exceed {limit} bytes.' => 'Размер файла "{file}" слишком велик, он не должен превышать {limit} байт.', + 'The file "{file}" is too small. Its size cannot be smaller than {limit} bytes.' => 'Размер файла "{file}" слишком мал, он не должен быть менее {limit} байт.', + 'The file "{file}" was only partially uploaded.' => 'Файл "{file}" был загружен не полностью.', + 'The first element in a filter configuration must be the filter class.' => 'Первым элементом в конфигурации фильтра должен быть его класс.', + 'The item "{name}" does not exist.' => 'Элемента "{name}" не существует.', + 'The item "{parent}" already has a child "{child}".' => 'Элемент "{parent}" уже имеет потомка "{child}".', + 'The layout path "{path}" is not a valid directory.' => 'Путь к шаблонам "{path}" не является директорией.', + 'The list is read only.' => 'Список предназначен только для чтения.', + 'The map is read only.' => 'Карта предназначена только для чтения.', + 'The pattern for 12 hour format must be "h" or "hh".' => 'Шаблон для 12-ти часового формата времени: "h", либо "hh".', + 'The pattern for 24 hour format must be "H" or "HH".' => 'Шаблон для 12-ти часового формата времени: "H", либо "HH".', + 'The pattern for AM/PM marker must be "a".' => 'Шаблон маркера AM/PM: "a".', + 'The pattern for day in month must be "F".' => 'Шаблон для дня месяца: "F".', + 'The pattern for day in year must be "D", "DD" or "DDD".' => 'Шаблон для дня в году: "D", "DD", либо "DDD".', + 'The pattern for day of the month must be "d" or "dd".' => 'Шаблон для дня месяца: "d", либо "dd".', + 'The pattern for day of the week must be "E", "EE", "EEE", "EEEE" or "EEEEE".' => 'Шаблон для дня недели:"E", "EE", "EEE", "EEEE", либо "EEEEE".', + 'The pattern for era must be "G", "GG", "GGG", "GGGG" or "GGGGG".' => 'Шаблон для эры: "G", "GG", "GGG", "GGGG", либо "GGGGG".', + 'The pattern for hour in AM/PM must be "K" or "KK".' => 'Шаблон для часа в формате AM/PM: "K", либо "KK".', + 'The pattern for hour in day must be "k" or "kk".' => 'Шаблон для часа в дне: "k", либо "kk".', + 'The pattern for minutes must be "m" or "mm".' => 'Шаблон для минут: "m", либо "mm".', + 'The pattern for month must be "M", "MM", "MMM", or "MMMM".' => 'Шаблон имени месяца: "M", "MM", "MMM", либо "MMMM".', + 'The pattern for seconds must be "s" or "ss".' => 'Шаблон для секунд: "s", либо "ss".', + 'The pattern for time zone must be "z" or "v".' => 'Шаблон для временной зоны: "z", либо "v".', + 'The pattern for week in month must be "W".' => 'Шаблон недели в месяце: "W".', + 'The pattern for week in year must be "w".' => 'Шаблон недели в году: "w".', 'The queue is empty.' => 'Очередь пуста.', - 'The relation "{relation}" in active record class "{class}" is not specified correctly: the join table "{joinTable}" given in the foreign key cannot be found in the database.' => '', - 'The relation "{relation}" in active record class "{class}" is specified with an incomplete foreign key. The foreign key must consist of columns referencing both joining tables.' => '', - 'The relation "{relation}" in active record class "{class}" is specified with an invalid foreign key "{key}". The foreign key does not point to either joining table.' => '', - 'The relation "{relation}" in active record class "{class}" is specified with an invalid foreign key. The format of the foreign key must be "joinTable(fk1,fk2,...)".' => '', - 'The requested view "{name}" is not found.' => 'Запрошенное представление "{view}" не найдено.', - 'The stack is empty.' => 'Стэк пуст.', - 'The system is unable to find the requested action "{action}".' => '', - 'The system view path "{path}" is not a valid directory.' => '', - 'The table "{table}" for active record class "{class}" cannot be found in the database.' => '', - 'The value for the primary key "{key}" is not supplied when querying the table "{table}".' => '', + 'The relation "{relation}" in active record class "{class}" is not specified correctly: the join table "{joinTable}" given in the foreign key cannot be found in the database.' => 'Отношение "{relation}", определенное в записи active record класса "{class}" ошибочно: в базе данных нет включаемой таблицы "{joinTable}", упомянутой во внешнем ключе.', + 'The relation "{relation}" in active record class "{class}" is specified with an incomplete foreign key. The foreign key must consist of columns referencing both joining tables.' => 'Отношение "{relation}", определенное в записи active record класса "{class}", определено неполным внешним ключом. Внешний ключ должен состоять из столбцов, относящихся к обоим объединяемым таблицам.', + 'The relation "{relation}" in active record class "{class}" is specified with an invalid foreign key "{key}". The foreign key does not point to either joining table.' => 'Отношение "{relation}", определенное в записи active record класса "{class}", определено неверным внешним ключом "{key}". Внешний ключ не указывает ни на одну из объединяемых таблиц.', + 'The relation "{relation}" in active record class "{class}" is specified with an invalid foreign key. The format of the foreign key must be "joinTable(fk1,fk2,...)".' => 'Отношение "{relation}", определенное в записи active record класса "{class}", определено неверным внешним ключом. Формат внешнего ключа должен быть таким: "joinTable(fk1,fk2,...)".', + 'The requested view "{name}" is not found.' => 'Запрошенное представление (view) "{view}" не найдено.', + 'The stack is empty.' => 'Стек приложения пуст.', + 'The system is unable to find the requested action "{action}".' => 'Системе не удалось найти запрашиваемое действие "{action}".', + 'The system view path "{path}" is not a valid directory.' => 'Путь к представлениям (view) "{path}" не является директорией.', + 'The table "{table}" for active record class "{class}" cannot be found in the database.' => 'Таблица "{table}", упомянутая в записи active record класса "{class}", не найдена в базе данных.', + 'The value for the primary key "{key}" is not supplied when querying the table "{table}".' => 'При обращении к таблице "{table}" не указано значение первичного ключа "{key}".', 'The verification code is incorrect.' => 'Неправильный код проверки.', - 'The view path "{path}" is not a valid directory.' => 'Неправильный путь представления "{path}".', - 'Theme directory "{directory}" does not exist.' => 'Директория темы "{directory}" не существует.', - 'This content requires the Adobe Flash Player.' => '', - 'Unable to add an item whose name is the same as an existing item.' => 'Невозможно добавить элемент с уже существующим именем.', - 'Unable to change the item name. The name "{name}" is already used by another item.' => '', - 'Unable to create application state file "{file}". Make sure the directory containing the file exists and is writable by the Web server process.' => '', + 'The view path "{path}" is not a valid directory.' => 'Неправильный путь представления: "{path}".', + 'Theme directory "{directory}" does not exist.' => 'Директории темы (theme) "{directory}" не существует.', + 'This content requires the Adobe Flash Player.' => 'Требуется наличие Adobe Flash Player.', + 'Unable to add an item whose name is the same as an existing item.' => 'Невозможно добавить элемент, заданное имя уже используется.', + 'Unable to change the item name. The name "{name}" is already used by another item.' => 'Невозможно сменить имя элемента. Другой элемент уже использует имя "{name}".', + 'Unable to create application state file "{file}". Make sure the directory containing the file exists and is writable by the Web server process.' => 'Не удалось создать файл состояния приложения "{file}". Удостоверьтесь, что директория существует и доступна для записи пользователю, под которым запущен веб-сервер.', 'Unable to lock file "{file}" for reading.' => 'Невозможно заблокировать файл "{file}" для чтения.', 'Unable to lock file "{file}" for writing.' => 'Невозможно заблокировать файл "{file}" для записи.', - 'Unable to read file "{file}".' => 'Невозможно прочитать файл "{file}".', - 'Unable to replay the action "{object}.{method}". The method does not exist.' => '', + 'Unable to read file "{file}".' => 'Невозможно прочесть файл "{file}".', + 'Unable to replay the action "{object}.{method}". The method does not exist.' => 'Невозможно произвести действие "{object}.{method}". Указанного метода не существует.', 'Unable to write file "{file}".' => 'Невозможно записать в файл "{file}".', - 'Unknown authorization item "{name}".' => '', - //TODO: нет ли синонима «локаль»? + 'Unknown authorization item "{name}".' => 'Неизвестный элемент авторизации "{name}".', 'Unrecognized locale "{locale}".' => 'Неизвестная локаль "{locale}".', - 'View file "{file}" does not exist.' => 'Файл представления "{file}" не существует.', + 'View file "{file}" does not exist.' => 'Файл представления (view) "{file}" не существует.', 'Yii application can only be created once.' => 'Приложение Yii может быть создано только один раз.', - 'You are not authorized to perform this action.' => 'Вам неразрешено выполнять данное действие.', - 'Your request is not valid.' => 'Ваш запрос неправильный.', - '{attribute} "{value}" has already been taken.' => '{attribute} "{value}" уже занят.', - '{attribute} cannot be blank.' => '{attribute} не должен быть пустым.', - '{attribute} is invalid.' => '{attribute} не верен.', - '{attribute} is not a valid URL.' => '{attribute} не является правильным URL.', - '{attribute} is not a valid email address.' => '{attribute} не является правильным E-Mail адресом.', - '{attribute} is not in the list.' => '{attribute} не находится в списке.', - '{attribute} is of the wrong length (should be {length} characters).' => '{attribut} неверной длинны (Должен быть {length} симв.).', - '{attribute} is too big (maximum is {max}).' => '{attribute} слишком большой (Максимум: {max}).', - '{attribute} is too long (maximum is {max} characters).' => '{attribute} слишком длинный (Максимум: {max} симв.).', - '{attribute} is too short (minimum is {min} characters).' => '{attribute} слишком короткий (Минимум: {min} симв.).', - '{attribute} is too small (minimum is {min}).' => '{attribute} слишком мал (Минимум: {min}).', - '{attribute} must be a number.' => '{attribute} должен быть числом.', - '{attribute} must be an integer.' => '{attribute} должен быть целым числом.', - '{attribute} must be repeated exactly.' => '', - '{attribute} must be {type}.' => '{attribute} должен быть {type}.', - '{className} does not support add() functionality.' => '{className} не поддерживает add() функциональность.', - '{className} does not support delete() functionality.' => '{className} не поддерживает delete() функциональность.', - '{className} does not support flush() functionality.' => '{className} не поддерживает flush() функциональность.', - '{className} does not support get() functionality.' => '{className} не поддерживает get() функциональность.', - '{className} does not support set() functionality.' => '{className} не поддерживает set() функциональность.', - '{class} does not have attribute "{name}".' => '{class} не имеет атрибут "{name}".', - '{class} has an invalid validation rule. The rule must specify attributes to be validated and the validator name.' => '', - '{class} must specify "model" and "attribute" or "name" property values.' => '', - '{class}.allowAutoLogin must be set true in order to use cookie-based authentication.' => '', - '{class}::authenticate() must be implemented.' => 'Определите метод {class}::authenticate().', - '{controller} cannot find the requested view "{view}".' => '{controller} не может найти представление "{view}".', - '{controller} contains improperly nested widget tags in its view "{view}". A {widget} widget does not have an endWidget() call.' => '', - '{controller} has an extra endWidget({id}) call in its view.' => '', - '{widget} cannot find the view "{view}".' => '{widget} не может найти представление "{view}".', + 'You are not authorized to perform this action.' => 'У вас недостаточно прав для выполнения указанного действия.', + 'Your request is not valid.' => 'Обнаружена ошибка в вашем запросе.', + '{attribute} "{value}" has already been taken.' => 'Атрибут {attribute} "{value}" уже занят.', + '{attribute} cannot be blank.' => 'Атрибут {attribute} не должен быть пустым.', + '{attribute} is invalid.' => 'Атрибут {attribute} не верен.', + '{attribute} is not a valid URL.' => 'Атрибут {attribute} не является правильным URL.', + '{attribute} is not a valid email address.' => 'Атрибут {attribute} не является правильным E-Mail адресом.', + '{attribute} is not in the list.' => 'Атрибут {attribute} отсутствует в списке.', + '{attribute} is of the wrong length (should be {length} characters).' => 'Атрибут {attribut} неверной длины (Должен быть {length} симв.).', + '{attribute} is too big (maximum is {max}).' => 'Атрибут {attribute} слишком велик (Максимум: {max}).', + '{attribute} is too long (maximum is {max} characters).' => 'Атрибут {attribute} слишком длинный (Максимум: {max} симв.).', + '{attribute} is too short (minimum is {min} characters).' => 'Атрибут {attribute} слишком короткий (Минимум: {min} симв.).', + '{attribute} is too small (minimum is {min}).' => 'Атрибут {attribute} слишком мал (Минимум: {min}).', + '{attribute} must be a number.' => 'Атрибут {attribute} должен быть числом.', + '{attribute} must be an integer.' => 'Атрибут {attribute} должен быть целым числом.', + '{attribute} must be repeated exactly.' => 'Атрибут {attribute} должен быть повторен в точности.', + '{attribute} must be {type}.' => 'Атрибут {attribute} должен быть {type}.', + '{className} does not support add() functionality.' => 'Класс {className} не поддерживает функционал add().', + '{className} does not support delete() functionality.' => 'Класс {className} не поддерживает функционал delete() .', + '{className} does not support flush() functionality.' => 'Класс {className} не поддерживает функционал flush().', + '{className} does not support get() functionality.' => 'Класс {className} не поддерживает функционал get().', + '{className} does not support set() functionality.' => 'Класс {className} не поддерживает функционал set().', + '{class} does not have attribute "{name}".' => 'Класс {class} не имеет атрибута "{name}".', + '{class} has an invalid validation rule. The rule must specify attributes to be validated and the validator name.' => 'Класс {class} содержит неверное правило проверки (validation rule). Правило должно иметь имя и включать элементы для проверки.', + '{class} must specify "model" and "attribute" or "name" property values.' => 'В классе {class} должны быть определены значения свойств "model" и "attribute", либо "name".', + '{class}.allowAutoLogin must be set true in order to use cookie-based authentication.' => 'Для использования авторизации, построенной на cookie, свойство {class}.allowAutoLogin должно принять значение "true".', + '{class}::authenticate() must be implemented.' => 'Требуется определить метод {class}::authenticate().', + '{controller} cannot find the requested view "{view}".' => 'Контроллер {controller} не может найти представление (view) "{view}".', + '{controller} contains improperly nested widget tags in its view "{view}". A {widget} widget does not have an endWidget() call.' => 'Контроллер {controller} содержит в своем представлении (view) "{view}" тэги виджетов с неправильной вложенностью. В виджете (widget) {widget} не используется вызов endWidget().', + '{controller} has an extra endWidget({id}) call in its view.' => 'В представлении (view) контроллера {controller} обнаружен лишний вызов endWidget({id}).', + '{widget} cannot find the view "{view}".' => 'Виджет {widget} не может найти представление (view) "{view}".', );