diff --git a/apps/advanced/backend/views/layouts/main.php b/apps/advanced/backend/views/layouts/main.php
index cb41c08..0a1bf13 100644
--- a/apps/advanced/backend/views/layouts/main.php
+++ b/apps/advanced/backend/views/layouts/main.php
@@ -37,7 +37,11 @@ AppAsset::register($this);
 			if (Yii::$app->user->isGuest) {
 				$menuItems[] = ['label' => 'Login', 'url' => ['/site/login']];
 			} else {
-				$menuItems[] = ['label' => 'Logout (' . Yii::$app->user->identity->username .')' , 'url' => ['/site/logout']];
+				$menuItems[] = [
+					'label' => 'Logout (' . Yii::$app->user->identity->username . ')',
+					'url' => ['/site/logout'],
+					'linkOptions' => ['data-method' => 'post']
+				];
 			}
 			echo Nav::widget([
 				'options' => ['class' => 'navbar-nav navbar-right'],
diff --git a/apps/advanced/common/mail/layouts/html.php b/apps/advanced/common/mail/layouts/html.php
index 2e6b615..8e2707d 100644
--- a/apps/advanced/common/mail/layouts/html.php
+++ b/apps/advanced/common/mail/layouts/html.php
@@ -1,10 +1,9 @@
 <?php
 use yii\helpers\Html;
-use yii\mail\BaseMessage;
 
 /**
  * @var \yii\web\View $this
- * @var BaseMessage $content
+ * @var \yii\mail\BaseMessage $content
  */
 ?>
 <?php $this->beginPage() ?>
diff --git a/apps/advanced/common/tests/_helpers/FixtureHelper.php b/apps/advanced/common/tests/_helpers/FixtureHelper.php
index 00c3a17..507b60c 100644
--- a/apps/advanced/common/tests/_helpers/FixtureHelper.php
+++ b/apps/advanced/common/tests/_helpers/FixtureHelper.php
@@ -32,7 +32,7 @@ class FixtureHelper extends Module
 	 * to use in acceptance and functional tests.
 	 * @param array $settings
 	 */
-	public function _beforeSuite($settings = array())
+	public function _beforeSuite($settings = [])
 	{
 		$this->loadFixtures();
 	}
@@ -54,5 +54,4 @@ class FixtureHelper extends Module
 			],
 		];
 	}
-
 }
diff --git a/apps/advanced/common/tests/_pages/LoginPage.php b/apps/advanced/common/tests/_pages/LoginPage.php
index af95ea3..5fdf3bc 100644
--- a/apps/advanced/common/tests/_pages/LoginPage.php
+++ b/apps/advanced/common/tests/_pages/LoginPage.php
@@ -18,5 +18,4 @@ class LoginPage extends BasePage
 		$this->guy->fillField('input[name="LoginForm[password]"]', $password);
 		$this->guy->click('login-button');
 	}
-
 }
diff --git a/apps/advanced/common/tests/unit/models/LoginFormTest.php b/apps/advanced/common/tests/unit/models/LoginFormTest.php
index 2ececd6..9ca277d 100644
--- a/apps/advanced/common/tests/unit/models/LoginFormTest.php
+++ b/apps/advanced/common/tests/unit/models/LoginFormTest.php
@@ -25,7 +25,7 @@ class LoginFormTest extends TestCase
 		$model->username = 'some_username';
 		$model->password = 'some_password';
 
-		$this->specify('user should not be able to login, when there is no identity' , function () use ($model) {
+		$this->specify('user should not be able to login, when there is no identity', function () use ($model) {
 			expect('model should not login user', $model->login())->false();
 			expect('user should not be logged in', Yii::$app->user->isGuest)->true();
 		});
@@ -52,7 +52,7 @@ class LoginFormTest extends TestCase
 		$model->username = 'demo';
 		$model->password = 'demo';
 
-		$this->specify('user should be able to login with correct credentials', function() use ($model) {
+		$this->specify('user should be able to login with correct credentials', function () use ($model) {
 			expect('model should login user', $model->login())->true();
 			expect('error message should not be set', $model->errors)->hasntKey('password');
 			expect('user should be logged in', Yii::$app->user->isGuest)->false();
@@ -61,9 +61,8 @@ class LoginFormTest extends TestCase
 
 	private function mockUser($user)
 	{
-		$loginForm = $this->getMock('common\models\LoginForm',['getUser']);
+		$loginForm = $this->getMock('common\models\LoginForm', ['getUser']);
 		$loginForm->expects($this->any())->method('getUser')->will($this->returnValue($user));
 		return $loginForm;
 	}
-
 }
diff --git a/apps/advanced/composer.json b/apps/advanced/composer.json
index 53e926f..7744971 100644
--- a/apps/advanced/composer.json
+++ b/apps/advanced/composer.json
@@ -1,7 +1,7 @@
 {
 	"name": "yiisoft/yii2-app-advanced",
 	"description": "Yii 2 Advanced Application Template",
-	"keywords": ["yii", "framework", "advanced", "application template"],
+	"keywords": ["yii2", "framework", "advanced", "application template"],
 	"homepage": "http://www.yiiframework.com/",
 	"type": "project",
 	"license": "BSD-3-Clause",
diff --git a/apps/advanced/frontend/tests/_pages/SignupPage.php b/apps/advanced/frontend/tests/_pages/SignupPage.php
index ba4a9cb..0281ac9 100644
--- a/apps/advanced/frontend/tests/_pages/SignupPage.php
+++ b/apps/advanced/frontend/tests/_pages/SignupPage.php
@@ -20,5 +20,4 @@ class SignupPage extends BasePage
 		}
 		$this->guy->click('signup-button');
 	}
-
 }
diff --git a/apps/advanced/frontend/tests/acceptance/SignupCest.php b/apps/advanced/frontend/tests/acceptance/SignupCest.php
index a166f34..268ff6b 100644
--- a/apps/advanced/frontend/tests/acceptance/SignupCest.php
+++ b/apps/advanced/frontend/tests/acceptance/SignupCest.php
@@ -79,5 +79,4 @@ class SignupCest
 		$I->expectTo('see that user logged in');
 		$I->see('Logout (tester)');
 	}
-
 }
diff --git a/apps/advanced/frontend/tests/functional/SignupCest.php b/apps/advanced/frontend/tests/functional/SignupCest.php
index cfef787..0409d23 100644
--- a/apps/advanced/frontend/tests/functional/SignupCest.php
+++ b/apps/advanced/frontend/tests/functional/SignupCest.php
@@ -79,5 +79,4 @@ class SignupCest
 		$I->expectTo('see that user logged in');
 		$I->see('Logout (tester)');
 	}
-
 }
diff --git a/apps/advanced/frontend/tests/unit/models/ContactFormTest.php b/apps/advanced/frontend/tests/unit/models/ContactFormTest.php
index 23e6288..a754672 100644
--- a/apps/advanced/frontend/tests/unit/models/ContactFormTest.php
+++ b/apps/advanced/frontend/tests/unit/models/ContactFormTest.php
@@ -42,7 +42,7 @@ class ContactFormTest extends TestCase
 			expect('email file should exist', file_exists($this->getMessageFile()))->true();
 		});
 
-		$this->specify('message should contain correct data', function () use($model) {
+		$this->specify('message should contain correct data', function () use ($model) {
 			$emailMessage = file_get_contents($this->getMessageFile());
 
 			expect('email should contain user name', $emailMessage)->contains($model->name);
@@ -56,5 +56,4 @@ class ContactFormTest extends TestCase
 	{
 		return Yii::getAlias(Yii::$app->mail->fileTransportPath) . '/testing_message.eml';
 	}
-
 }
diff --git a/apps/advanced/frontend/tests/unit/models/PasswordResetRequestFormTest.php b/apps/advanced/frontend/tests/unit/models/PasswordResetRequestFormTest.php
index b736039..7591ff3 100644
--- a/apps/advanced/frontend/tests/unit/models/PasswordResetRequestFormTest.php
+++ b/apps/advanced/frontend/tests/unit/models/PasswordResetRequestFormTest.php
@@ -28,14 +28,14 @@ class PasswordResetRequestFormTest extends DbTestCase
 
 	public function testSendEmailWrongUser()
 	{
-		$this->specify('no user with such email, message should not be send', function() {
+		$this->specify('no user with such email, message should not be send', function () {
 			$model = new PasswordResetRequestForm();
 			$model->email = 'not-existing-email@example.com';
 			
 			expect('email not send', $model->sendEmail())->false();
 		});
 
-		$this->specify('user is not active, message should not be send', function() {
+		$this->specify('user is not active, message should not be send', function () {
 			$model = new PasswordResetRequestForm();
 			$model->email = $this->user[1]['email'];
 			
@@ -52,8 +52,8 @@ class PasswordResetRequestFormTest extends DbTestCase
 		expect('email sent', $model->sendEmail())->true();
 		expect('user has valid token', $user->password_reset_token)->notNull();
 			
-		$this->specify('message has correct format', function() use ($model) {
-			expect('message file exists',  file_exists($this->getMessageFile()))->true();
+		$this->specify('message has correct format', function () use ($model) {
+			expect('message file exists', file_exists($this->getMessageFile()))->true();
 
 			$message = file_get_contents($this->getMessageFile());
 			expect('message "from" is correct', $message)->contains(Yii::$app->params['supportEmail']);
@@ -75,5 +75,4 @@ class PasswordResetRequestFormTest extends DbTestCase
 	{
 		return Yii::getAlias(Yii::$app->mail->fileTransportPath) . '/testing_message.eml';
 	}
-
 }
diff --git a/apps/advanced/frontend/tests/unit/models/ResetPasswordFormTest.php b/apps/advanced/frontend/tests/unit/models/ResetPasswordFormTest.php
index 763683f..b00c2ac 100644
--- a/apps/advanced/frontend/tests/unit/models/ResetPasswordFormTest.php
+++ b/apps/advanced/frontend/tests/unit/models/ResetPasswordFormTest.php
@@ -13,13 +13,13 @@ class ResetPasswordFormTest extends DbTestCase
 
 	public function testResetPassword()
 	{
-		$this->specify('wrong reset token', function() {
-			$this->setExpectedException('\Exception','Wrong password reset token.');
+		$this->specify('wrong reset token', function () {
+			$this->setExpectedException('\Exception', 'Wrong password reset token.');
 			new ResetPasswordForm('notexistingtoken_1391882543');
 		});
 
-		$this->specify('not correct token', function() {
-			$this->setExpectedException('yii\base\InvalidParamException','Password reset token cannot be blank.');
+		$this->specify('not correct token', function () {
+			$this->setExpectedException('yii\base\InvalidParamException', 'Password reset token cannot be blank.');
 			new ResetPasswordForm('');
 		});
 	}
@@ -33,5 +33,4 @@ class ResetPasswordFormTest extends DbTestCase
 			],
 		];
 	}
-
 }
diff --git a/apps/advanced/frontend/tests/unit/models/SignupFormTest.php b/apps/advanced/frontend/tests/unit/models/SignupFormTest.php
index 5176baa..359a02c 100644
--- a/apps/advanced/frontend/tests/unit/models/SignupFormTest.php
+++ b/apps/advanced/frontend/tests/unit/models/SignupFormTest.php
@@ -12,7 +12,7 @@ class SignupFormTest extends DbTestCase
 
 	public function testCorrectSignup()
 	{
-		$model = $this->getMock('frontend\models\SignupForm',['validate']);
+		$model = $this->getMock('frontend\models\SignupForm', ['validate']);
 		$model->expects($this->once())->method('validate')->will($this->returnValue(true));
 
 		$model->username = 'some_username';
@@ -28,7 +28,7 @@ class SignupFormTest extends DbTestCase
 
 	public function testNotCorrectSignup()
 	{
-		$model = $this->getMock('frontend\models\SignupForm',['validate']);
+		$model = $this->getMock('frontend\models\SignupForm', ['validate']);
 		$model->expects($this->once())->method('validate')->will($this->returnValue(false));
 
 		expect('user should not be created', $model->signup())->null();
@@ -43,5 +43,4 @@ class SignupFormTest extends DbTestCase
 			],
 		];
 	}
-
 }
diff --git a/apps/advanced/frontend/views/layouts/main.php b/apps/advanced/frontend/views/layouts/main.php
index be8d70d..6e3ae8c 100644
--- a/apps/advanced/frontend/views/layouts/main.php
+++ b/apps/advanced/frontend/views/layouts/main.php
@@ -41,7 +41,11 @@ AppAsset::register($this);
 				$menuItems[] = ['label' => 'Signup', 'url' => ['/site/signup']];
 				$menuItems[] = ['label' => 'Login', 'url' => ['/site/login']];
 			} else {
-				$menuItems[] = ['label' => 'Logout (' . Yii::$app->user->identity->username .')' , 'url' => ['/site/logout']];
+				$menuItems[] = [
+					'label' => 'Logout (' . Yii::$app->user->identity->username . ')',
+					'url' => ['/site/logout'],
+					'linkOptions' => ['data-method' => 'post']
+				];
 			}
 			echo Nav::widget([
 				'options' => ['class' => 'navbar-nav navbar-right'],
diff --git a/apps/basic/composer.json b/apps/basic/composer.json
index 9990ef7..726a7ea 100644
--- a/apps/basic/composer.json
+++ b/apps/basic/composer.json
@@ -1,7 +1,7 @@
 {
 	"name": "yiisoft/yii2-app-basic",
 	"description": "Yii 2 Basic Application Template",
-	"keywords": ["yii", "framework", "basic", "application template"],
+	"keywords": ["yii2", "framework", "basic", "application template"],
 	"homepage": "http://www.yiiframework.com/",
 	"type": "project",
 	"license": "BSD-3-Clause",
diff --git a/apps/basic/mail/layouts/html.php b/apps/basic/mail/layouts/html.php
index 2e6b615..8e2707d 100644
--- a/apps/basic/mail/layouts/html.php
+++ b/apps/basic/mail/layouts/html.php
@@ -1,10 +1,9 @@
 <?php
 use yii\helpers\Html;
-use yii\mail\BaseMessage;
 
 /**
  * @var \yii\web\View $this
- * @var BaseMessage $content
+ * @var \yii\mail\BaseMessage $content
  */
 ?>
 <?php $this->beginPage() ?>
diff --git a/apps/benchmark/composer.json b/apps/benchmark/composer.json
index d980f9a..c8ed589 100644
--- a/apps/benchmark/composer.json
+++ b/apps/benchmark/composer.json
@@ -1,7 +1,7 @@
 {
 	"name": "yiisoft/yii2-app-benchmark",
 	"description": "Yii 2 Benchmark Application",
-	"keywords": ["yii", "framework", "benchmark", "application"],
+	"keywords": ["yii2", "framework", "benchmark", "application"],
 	"homepage": "http://www.yiiframework.com/",
 	"type": "project",
 	"license": "BSD-3-Clause",
diff --git a/build/controllers/ClassmapController.php b/build/controllers/ClassmapController.php
index 706435a..5fd4e5f 100644
--- a/build/controllers/ClassmapController.php
+++ b/build/controllers/ClassmapController.php
@@ -52,7 +52,7 @@ class ClassmapController extends Controller
 		$files = FileHelper::findFiles($root, $options);
 		$map = [];
 		foreach ($files as $file) {
-			if (($pos = strpos($file, $root)) !== 0) {
+			if (strpos($file, $root) !== 0) {
 				die("Something wrong: $file\n");
 			}
 			$path = str_replace('\\', '/', substr($file, strlen($root)));
diff --git a/composer.json b/composer.json
index d01de32..2466074 100644
--- a/composer.json
+++ b/composer.json
@@ -1,7 +1,7 @@
 {
 	"name": "yiisoft/yii2-dev",
 	"description": "Yii PHP Framework Version 2 - Development Package",
-	"keywords": ["yii", "framework"],
+	"keywords": ["yii2", "framework"],
 	"homepage": "http://www.yiiframework.com/",
 	"type": "yii2-extension",
 	"license": "BSD-3-Clause",
@@ -74,6 +74,7 @@
 		"lib-pcre": "*",
 		"yiisoft/yii2-composer": "*",
 		"yiisoft/jquery": "~2.0 | ~1.10",
+		"yiisoft/jquery-pjax": "*",
 		"ezyang/htmlpurifier": "4.6.*",
 		"cebe/markdown": "0.9.*"
 	},
diff --git a/docs/guide/assets.md b/docs/guide/assets.md
index 17c6797..ca3b07c 100644
--- a/docs/guide/assets.md
+++ b/docs/guide/assets.md
@@ -81,18 +81,26 @@ following way:
 ```php
 class LanguageAsset extends AssetBundle
 {
-    public $sourcePath = '@app/assets/language';
-    public $js = [
-    ];
-
-    public function init()
-    {
-        $this->js[] = 'language-' . Yii::$app->language . '.js';
-        parent::init();
-    }
+	public $language;
+	public $sourcePath = '@app/assets/language';
+	public $js = [
+	];
+
+	public function registerAssetFiles($view)
+	{
+		$language = $this->language ? $this->language : Yii::$app->language;
+		$this->js[] = 'language-' . $language . '.js';
+		parent::registerAssetFiles($view);
+	}
 }
 ```
 
+In order to set language use the following code when registering an asset bundle in a view:
+
+```php
+LanguageAsset::register($this)->language = $language;
+```
+
 
 Registering asset bundle
 ------------------------
@@ -114,6 +122,10 @@ To register an asset inside of a widget, the view instance is available as `$thi
 AppAsset::register($this->view);
 ```
 
+> Note: If there is a need to modify third party asset bundles it is recommended to create your own bundles depending
+  on third party ones and use CSS and JavaScript features to modify behavior instead of editing files directly or
+  copying them over.
+
 
 Overriding asset bundles
 ------------------------
diff --git a/docs/guide/controller.md b/docs/guide/controller.md
index 074a316..eec7a89 100644
--- a/docs/guide/controller.md
+++ b/docs/guide/controller.md
@@ -81,13 +81,16 @@ Routes
 ------
 
 Each controller action has a corresponding internal route. In our example above `actionIndex` has `site/index` route
-and `actionTest` has `site/test` route. In this route `site` is referred to as controller ID while `test` is referred to
-as action ID.
+and `actionTest` has `site/test` route. In this route `site` is referred to as controller ID while `test` is action ID.
 
 By default you can access specific controller and action using the `http://example.com/?r=controller/action` URL. This
-behavior is fully customizable. For details refer to [URL Management](url.md).
+behavior is fully customizable. For more details please refer to [URL Management](url.md).
 
-If controller is located inside a module its action internal route will be `module/controller/action`.
+If a controller is located inside a module, the route of its actions will be in the format of `module/controller/action`.
+
+A controller can be located under a subdirectory of the controller directory of an application or module. The route
+will be prefixed with the corresponding directory names. For example, you may have a `UserController` under `controllers/admin`.
+The route of its `actionIndex` would be `admin/user/index`, and `admin/user` would be the controller ID.
 
 In case module, controller or action specified isn't found Yii will return "not found" page and HTTP status code 404.
 
diff --git a/docs/guide/module-debug.md b/docs/guide/module-debug.md
index 91da33a..916101c 100644
--- a/docs/guide/module-debug.md
+++ b/docs/guide/module-debug.md
@@ -110,7 +110,7 @@ class ViewsPanel extends Panel
 	{
 		parent::init();
 		Event::on(View::className(), View::EVENT_BEFORE_RENDER, function (ViewEvent $event) {
-			$this->_viewFiles[] = $event->viewFile;
+			$this->_viewFiles[] = $event->sender->getViewFile();
 		});
 	}
 
diff --git a/docs/guide/theming.md b/docs/guide/theming.md
index e627f7c..037e70c 100644
--- a/docs/guide/theming.md
+++ b/docs/guide/theming.md
@@ -1,7 +1,12 @@
 Theming
 =======
 
-TBD
+A theme is a directory of view and layout files. Each file of the theme overrides corresponding file of an application
+when rendered. A single application may use multiple themes and each may provide totally different experience. At any
+time only one theme can be active.
+
+> Note: Themes usually do not meant to be redistributed since views are too application specific. If you want to
+  redistribute customized look and feel consider CSS and JavaScript files in form of [asset bundles](assets.md) instead.
 
 Configuring current theme
 -------------------------
@@ -18,4 +23,27 @@ be in your application config file:
 		],
 	],
 ],
-```
\ No newline at end of file
+```
+
+In the above `pathMap` defines where to look for view files while `baseUrl` defines base URL for resources referenced
+from these files. For example, if `pathMap` is `['/web/views' => '/web/themes/basic']`,  then the themed version
+for a view file `/web/views/site/index.php` will be `/web/themes/basic/site/index.php`.
+
+Using multiple paths
+--------------------
+
+It is possible to map a single path to multiple paths. For example,
+
+```php
+'pathMap' => [
+	'/web/views' => [
+		'/web/themes/christmas',
+		'/web/themes/basic',
+	],
+]
+```
+
+In this case, the view will be searched in `/web/themes/christmas/site/index.php` then if it's not found it will check
+`/web/themes/basic/site/index.php`. If there's no view there as well application view will be used.
+
+This ability is especially useful if you want to temporary or conditionally override some views.
diff --git a/docs/guide/upgrade-from-v1.md b/docs/guide/upgrade-from-v1.md
index 92dc868..612eeab 100644
--- a/docs/guide/upgrade-from-v1.md
+++ b/docs/guide/upgrade-from-v1.md
@@ -329,9 +329,9 @@ public function behaviors()
             'class' => 'yii\web\AccessControl',
             'rules' => [
                 ['allow' => true, 'actions' => ['admin'], 'roles' => ['@']],
-            ),
-        ),
-    );
+            ],
+        ],
+    ];
 }
 ```
 
diff --git a/extensions/apidoc/composer.json b/extensions/apidoc/composer.json
index 276ceb1..6c0c5ce 100644
--- a/extensions/apidoc/composer.json
+++ b/extensions/apidoc/composer.json
@@ -1,7 +1,7 @@
 {
 	"name": "yiisoft/yii2-apidoc",
 	"description": "API Documentation generator for the Yii framework 2.0",
-	"keywords": ["yii", "phpdoc", "apidoc", "api", "documentation"],
+	"keywords": ["yii2", "phpdoc", "apidoc", "api", "documentation"],
 	"type": "yii2-extension",
 	"license": "BSD-3-Clause",
 	"support": {
diff --git a/extensions/apidoc/templates/html/views/eventDetails.php b/extensions/apidoc/templates/html/views/eventDetails.php
index 15a6751..46fc5bd 100644
--- a/extensions/apidoc/templates/html/views/eventDetails.php
+++ b/extensions/apidoc/templates/html/views/eventDetails.php
@@ -18,7 +18,7 @@ ArrayHelper::multisort($events, 'name');
 <h2>Event Details</h2>
 <?php foreach($events as $event): ?>
 	<div class="detailHeader h3" id="<?= $event->name.'-detail' ?>">
-		<?php echo $event->name; ?>
+		<?= $event->name ?>
 		<span class="detailHeaderTag small">
 		event
 		<?php if(!empty($event->since)): ?>
diff --git a/extensions/apidoc/templates/html/views/eventSummary.php b/extensions/apidoc/templates/html/views/eventSummary.php
index 1b716b1..99a003e 100644
--- a/extensions/apidoc/templates/html/views/eventSummary.php
+++ b/extensions/apidoc/templates/html/views/eventSummary.php
@@ -36,11 +36,11 @@ ArrayHelper::multisort($events, 'name');
 	<td>
 		<?= ApiMarkdown::process($event->shortDescription, $event->definedBy, true) ?>
 		<?php if(!empty($event->since)): ?>
-			(available since version <?php echo $event->since; ?>)
+			(available since version <?= $event->since ?>)
 		<?php endif; ?>
 	</td>
 	<td><?= $this->context->typeLink($event->definedBy) ?></td>
 </tr>
 <?php endforeach; ?>
 </table>
-</div>
\ No newline at end of file
+</div>
diff --git a/extensions/apidoc/templates/html/views/propertyDetails.php b/extensions/apidoc/templates/html/views/propertyDetails.php
index d02cf62..6efe2f4 100644
--- a/extensions/apidoc/templates/html/views/propertyDetails.php
+++ b/extensions/apidoc/templates/html/views/propertyDetails.php
@@ -21,7 +21,7 @@ ArrayHelper::multisort($properties, 'name');
 <?php foreach($properties as $property): ?>
 
 	<div class="detailHeader h3" id="<?= $property->name.'-detail' ?>">
-		<?php echo $property->name; ?>
+		<?= $property->name ?>
 		<span class="detailHeaderTag small">
 			<?= $property->visibility ?>
 			<?php if($property->getIsReadOnly()) echo ' <em>read-only</em> '; ?>
@@ -33,7 +33,7 @@ ArrayHelper::multisort($properties, 'name');
 		</span>
 	</div>
 
-	<div class="signature"><?php echo $this->context->renderPropertySignature($property); ?></div>
+	<div class="signature"><?= $this->context->renderPropertySignature($property) ?></div>
 
 	<?= ApiMarkdown::process($property->description, $type) ?>
 
diff --git a/extensions/authclient/composer.json b/extensions/authclient/composer.json
index 60290cb..81c5aa1 100644
--- a/extensions/authclient/composer.json
+++ b/extensions/authclient/composer.json
@@ -1,7 +1,7 @@
 {
 	"name": "yiisoft/yii2-authclient",
 	"description": "External authentication via OAuth and OpenID for the Yii framework",
-	"keywords": ["yii", "OAuth", "OpenID", "auth"],
+	"keywords": ["yii2", "OAuth", "OpenID", "auth"],
 	"type": "yii2-extension",
 	"license": "BSD-3-Clause",
 	"support": {
diff --git a/extensions/bootstrap/composer.json b/extensions/bootstrap/composer.json
index e2a99df..637a084 100644
--- a/extensions/bootstrap/composer.json
+++ b/extensions/bootstrap/composer.json
@@ -1,7 +1,7 @@
 {
 	"name": "yiisoft/yii2-bootstrap",
 	"description": "The Twitter Bootstrap extension for the Yii framework",
-	"keywords": ["yii", "bootstrap"],
+	"keywords": ["yii2", "bootstrap"],
 	"type": "yii2-extension",
 	"license": "BSD-3-Clause",
 	"support": {
diff --git a/extensions/codeception/composer.json b/extensions/codeception/composer.json
index 0982d8d..fa99992 100644
--- a/extensions/codeception/composer.json
+++ b/extensions/codeception/composer.json
@@ -1,7 +1,7 @@
 {
 	"name": "yiisoft/yii2-codeception",
 	"description": "The Codeception integration for the Yii framework",
-	"keywords": ["yii", "codeception"],
+	"keywords": ["yii2", "codeception"],
 	"type": "yii2-extension",
 	"license": "BSD-3-Clause",
 	"support": {
diff --git a/extensions/composer/composer.json b/extensions/composer/composer.json
index 38f5199..f311581 100644
--- a/extensions/composer/composer.json
+++ b/extensions/composer/composer.json
@@ -1,7 +1,7 @@
 {
 	"name": "yiisoft/yii2-composer",
 	"description": "The composer plugin for Yii extension installer",
-	"keywords": ["yii", "composer", "extension installer"],
+	"keywords": ["yii2", "composer", "extension installer"],
 	"type": "composer-plugin",
 	"license": "BSD-3-Clause",
 	"support": {
diff --git a/extensions/debug/composer.json b/extensions/debug/composer.json
index 84dafd5..3d095b1 100644
--- a/extensions/debug/composer.json
+++ b/extensions/debug/composer.json
@@ -1,7 +1,7 @@
 {
 	"name": "yiisoft/yii2-debug",
 	"description": "The debugger extension for the Yii framework",
-	"keywords": ["yii", "debug", "debugger"],
+	"keywords": ["yii2", "debug", "debugger"],
 	"type": "yii2-extension",
 	"license": "BSD-3-Clause",
 	"support": {
diff --git a/extensions/debug/views/default/panels/config/detail.php b/extensions/debug/views/default/panels/config/detail.php
index 88e96a1..b2cfde1 100644
--- a/extensions/debug/views/default/panels/config/detail.php
+++ b/extensions/debug/views/default/panels/config/detail.php
@@ -1,6 +1,4 @@
 <?php
-use yii\helpers\Html;
-
 /**
  * @var yii\debug\panels\ConfigPanel $panel
  */
diff --git a/extensions/debug/views/default/panels/config/summary.php b/extensions/debug/views/default/panels/config/summary.php
index af72260..bb3a6dd 100644
--- a/extensions/debug/views/default/panels/config/summary.php
+++ b/extensions/debug/views/default/panels/config/summary.php
@@ -1,7 +1,4 @@
 <?php
-
-use yii\helpers\Html;
-
 /**
  * @var yii\debug\panels\ConfigPanel $panel
  */
diff --git a/extensions/debug/views/default/panels/db/summary.php b/extensions/debug/views/default/panels/db/summary.php
index dcf49d8..022f9a7 100644
--- a/extensions/debug/views/default/panels/db/summary.php
+++ b/extensions/debug/views/default/panels/db/summary.php
@@ -1,6 +1,6 @@
 <?php if ($queryCount): ?>
 <div class="yii-debug-toolbar-block">
-	<a href="<?= $panel->getUrl() ?>" title="Executed <?php echo $queryCount; ?> database queries which took <?= $queryTime ?>.">
+	<a href="<?= $panel->getUrl() ?>" title="Executed <?= $queryCount ?> database queries which took <?= $queryTime ?>.">
 		DB <span class="label label-info"><?= $queryCount ?></span> <span class="label"><?= $queryTime ?></span>
 	</a>
 </div>
diff --git a/extensions/elasticsearch/composer.json b/extensions/elasticsearch/composer.json
index 097b102..d38454f 100644
--- a/extensions/elasticsearch/composer.json
+++ b/extensions/elasticsearch/composer.json
@@ -1,7 +1,7 @@
 {
 	"name": "yiisoft/yii2-elasticsearch",
 	"description": "Elasticsearch integration and ActiveRecord for the Yii framework",
-	"keywords": ["yii", "elasticsearch", "active-record", "search", "fulltext"],
+	"keywords": ["yii2", "elasticsearch", "active-record", "search", "fulltext"],
 	"type": "yii2-extension",
 	"license": "BSD-3-Clause",
 	"support": {
diff --git a/extensions/faker/composer.json b/extensions/faker/composer.json
index 5af5319..a8a5bc1 100644
--- a/extensions/faker/composer.json
+++ b/extensions/faker/composer.json
@@ -1,7 +1,7 @@
 {
 	"name": "yiisoft/yii2-faker",
 	"description": "Fixture generator. The Faker integration for the Yii framework.",
-	"keywords": ["yii", "faker", "fixture"],
+	"keywords": ["yii2", "faker", "fixture"],
 	"type": "yii2-extension",
 	"license": "BSD-3-Clause",
 	"support": {
diff --git a/extensions/gii/CHANGELOG.md b/extensions/gii/CHANGELOG.md
index 8a7632d..c67f8f4 100644
--- a/extensions/gii/CHANGELOG.md
+++ b/extensions/gii/CHANGELOG.md
@@ -13,6 +13,8 @@ Yii Framework 2 gii extension Change Log
 - Enh #1897: diff markup is now copy paste friendly (samdark)
 - Enh #2327: better visual representation of changed files, added header and refresh button to diff modal (thiagotalma)
 - Enh #2491: Added support for using the same base class name of search model and data model in Gii (qiangxue)
+- Enh #2595: Browse through all generated files using right and left arrows (thiagotalma)
+- Enh #2633: Keyboard shortcuts to browse through files (thiagotalma)
 
 2.0.0 alpha, December 1, 2013
 -----------------------------
diff --git a/extensions/gii/assets/gii.js b/extensions/gii/assets/gii.js
index c5a70ab..282ce58 100644
--- a/extensions/gii/assets/gii.js
+++ b/extensions/gii/assets/gii.js
@@ -35,10 +35,13 @@ yii.gii = (function ($) {
 	};
 
 	var initPreviewDiffLinks = function () {
-		$('.preview-code, .diff-code, .modal-refresh').on('click', function () {
+		$('.preview-code, .diff-code, .modal-refresh, .modal-previous, .modal-next').on('click', function () {
 			var $modal = $('#preview-modal');
 			var $link = $(this);
-			$modal.find('.modal-refresh').attr('href', $link.prop('href'));
+			$modal.find('.modal-refresh').attr('href', $link.attr('href'));
+			if ($link.hasClass('preview-code') || $link.hasClass('diff-code')) {
+				$modal.data('action', ($link.hasClass('preview-code') ? 'preview-code' : 'diff-code'))
+			}
 			$modal.find('.modal-title').text($link.data('title'));
 			$modal.find('.modal-body').html('Loading ...');
 			$modal.modal('show');
@@ -48,6 +51,15 @@ yii.gii = (function ($) {
 				url: $link.prop('href'),
 				data: $('.default-view form').serializeArray(),
 				success: function (data) {
+					if (!$link.hasClass('modal-refresh')) {
+						var filesSelector = 'a.' + $modal.data('action');
+						var $files = $(filesSelector);
+						var index = $files.filter('[href="' + $link.attr('href') + '"]').index(filesSelector);
+						var $prev = $files.eq(index-1);
+						var $next = $files.eq((index+1 == $files.length ? 0 : index+1));
+						$modal.find('.modal-previous').attr('href', $prev.attr('href')).data('title', $prev.data('title'));
+						$modal.find('.modal-next').attr('href', $next.attr('href')).data('title', $next.data('title'));
+					}
 					$modal.find('.modal-body').html(data);
 					$modal.find('.content').css('max-height', ($(window).height() - 200) + 'px');
 				},
@@ -57,6 +69,16 @@ yii.gii = (function ($) {
 			});
 			return false;
 		});
+
+		$('#preview-modal').on('keydown', function(e) {
+			if (e.keyCode === 37) {
+				$('.modal-previous').trigger('click');
+			} else if(e.keyCode === 39) {
+				$('.modal-next').trigger('click');
+			} else if(e.keyCode === 82) {
+				$('.modal-refresh').trigger('click');
+			}
+		});
 	};
 
 	var initConfirmationCheckboxes = function () {
diff --git a/extensions/gii/composer.json b/extensions/gii/composer.json
index dad7f87..11fa779 100644
--- a/extensions/gii/composer.json
+++ b/extensions/gii/composer.json
@@ -1,7 +1,7 @@
 {
 	"name": "yiisoft/yii2-gii",
 	"description": "The Gii extension for the Yii framework",
-	"keywords": ["yii", "gii", "code generator"],
+	"keywords": ["yii2", "gii", "code generator"],
 	"type": "yii2-extension",
 	"license": "BSD-3-Clause",
 	"support": {
diff --git a/extensions/gii/generators/controller/templates/view.php b/extensions/gii/generators/controller/templates/view.php
index 6ef2a87..a458b16 100644
--- a/extensions/gii/generators/controller/templates/view.php
+++ b/extensions/gii/generators/controller/templates/view.php
@@ -18,5 +18,5 @@ echo "<?php\n";
 
 <p>
 	You may change the content of this page by modifying
-	the file <code><?= '<?php' ?> echo __FILE__; ?></code>.
+	the file <code><?= '<?=' ?> __FILE__; ?></code>.
 </p>
diff --git a/extensions/gii/generators/crud/templates/views/create.php b/extensions/gii/generators/crud/templates/views/create.php
index 68d08ba..72a1f8d 100644
--- a/extensions/gii/generators/crud/templates/views/create.php
+++ b/extensions/gii/generators/crud/templates/views/create.php
@@ -26,8 +26,8 @@ $this->params['breadcrumbs'][] = $this->title;
 
 	<h1><?= "<?= " ?>Html::encode($this->title) ?></h1>
 
-	<?= "<?php " ?>echo $this->render('_form', [
+	<?= "<?= " ?>$this->render('_form', [
 		'model' => $model,
-	]); ?>
+	]) ?>
 
 </div>
diff --git a/extensions/gii/generators/crud/templates/views/index.php b/extensions/gii/generators/crud/templates/views/index.php
index a4f5f0d..aadc586 100644
--- a/extensions/gii/generators/crud/templates/views/index.php
+++ b/extensions/gii/generators/crud/templates/views/index.php
@@ -37,7 +37,7 @@ $this->params['breadcrumbs'][] = $this->title;
 	</p>
 
 <?php if ($generator->indexWidgetType === 'grid'): ?>
-	<?= "<?php " ?>echo GridView::widget([
+	<?= "<?= " ?>GridView::widget([
 		'dataProvider' => $dataProvider,
 		'filterModel' => $searchModel,
 		'columns' => [
@@ -69,13 +69,13 @@ if (($tableSchema = $generator->getTableSchema()) === false) {
 		],
 	]); ?>
 <?php else: ?>
-	<?= "<?php " ?>echo ListView::widget([
+	<?= "<?= " ?>ListView::widget([
 		'dataProvider' => $dataProvider,
 		'itemOptions' => ['class' => 'item'],
 		'itemView' => function ($model, $key, $index, $widget) {
 			return Html::a(Html::encode($model-><?= $nameAttribute ?>), ['view', <?= $urlParams ?>]);
 		},
-	]); ?>
+	]) ?>
 <?php endif; ?>
 
 </div>
diff --git a/extensions/gii/generators/crud/templates/views/update.php b/extensions/gii/generators/crud/templates/views/update.php
index 2fbbecf..610b5bb 100644
--- a/extensions/gii/generators/crud/templates/views/update.php
+++ b/extensions/gii/generators/crud/templates/views/update.php
@@ -29,8 +29,8 @@ $this->params['breadcrumbs'][] = 'Update';
 
 	<h1><?= "<?= " ?>Html::encode($this->title) ?></h1>
 
-	<?= "<?php " ?>echo $this->render('_form', [
+	<?= "<?= " ?>$this->render('_form', [
 		'model' => $model,
-	]); ?>
+	]) ?>
 
 </div>
diff --git a/extensions/gii/generators/crud/templates/views/view.php b/extensions/gii/generators/crud/templates/views/view.php
index 989dab5..8ffa728 100644
--- a/extensions/gii/generators/crud/templates/views/view.php
+++ b/extensions/gii/generators/crud/templates/views/view.php
@@ -31,16 +31,16 @@ $this->params['breadcrumbs'][] = $this->title;
 
 	<p>
 		<?= "<?= " ?>Html::a('Update', ['update', <?= $urlParams ?>], ['class' => 'btn btn-primary']) ?>
-		<?= "<?php " ?>echo Html::a('Delete', ['delete', <?= $urlParams ?>], [
+		<?= "<?= " ?>Html::a('Delete', ['delete', <?= $urlParams ?>], [
 			'class' => 'btn btn-danger',
 			'data' => [
 				'confirm' => Yii::t('app', 'Are you sure to delete this item?'),
 				'method' => 'post',
 			],
-		]); ?>
+		]) ?>
 	</p>
 
-	<?= "<?php " ?>echo DetailView::widget([
+	<?= "<?= " ?>DetailView::widget([
 		'model' => $model,
 		'attributes' => [
 <?php
@@ -56,6 +56,6 @@ if (($tableSchema = $generator->getTableSchema()) === false) {
 }
 ?>
 		],
-	]); ?>
+	]) ?>
 
 </div>
diff --git a/extensions/gii/generators/model/Generator.php b/extensions/gii/generators/model/Generator.php
index 538637c..893cd7f 100644
--- a/extensions/gii/generators/model/Generator.php
+++ b/extensions/gii/generators/model/Generator.php
@@ -471,7 +471,7 @@ class Generator extends \yii\gii\Generator
 	 */
 	public function validateTableName()
 	{
-		if (($pos = strpos($this->tableName, '*')) !== false && substr($this->tableName, -1) !== '*') {
+		if (strpos($this->tableName, '*') !== false && substr($this->tableName, -1) !== '*') {
 			$this->addError('tableName', 'Asterisk is only allowed as the last character.');
 			return;
 		}
diff --git a/extensions/gii/views/default/view/files.php b/extensions/gii/views/default/view/files.php
index 947c8f8..fbe5e69 100644
--- a/extensions/gii/views/default/view/files.php
+++ b/extensions/gii/views/default/view/files.php
@@ -81,7 +81,14 @@ use yii\gii\CodeFile;
 			<div class="modal-content">
 				<div class="modal-header">
 					<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
-					<h4><a class="modal-refresh glyphicon glyphicon-refresh" href="#"></a> <span class="modal-title">Modal title</span></h4>
+					<div class="btn-group pull-left">
+						<a class="modal-previous btn btn-xs btn-default" href="#" title="Previous File (Left Arrow)"><span class="glyphicon glyphicon-arrow-left"></span></a>
+						<a class="modal-next btn btn-xs btn-default" href="#" title="Next File (Right Arrow)"><span class="glyphicon glyphicon-arrow-right"></span></a>
+						<a class="modal-refresh btn btn-xs btn-default" href="#" title="Refresh File (R)"><span class="glyphicon glyphicon-refresh"></span></a>
+						&nbsp;
+					</div>
+					<strong class="modal-title pull-left">Modal title</strong>
+					<div class="clearfix"></div>
 				</div>
 				<div class="modal-body">
 					<p>Please wait ...</p>
diff --git a/extensions/imagine/composer.json b/extensions/imagine/composer.json
index e032ff9..84f227c 100644
--- a/extensions/imagine/composer.json
+++ b/extensions/imagine/composer.json
@@ -1,7 +1,7 @@
 {
     "name": "yiisoft/yii2-imagine",
     "description": "The Imagine integration for the Yii framework",
-    "keywords": ["yii", "imagine", "image", "helper"],
+    "keywords": ["yii2", "imagine", "image", "helper"],
     "type": "yii2-extension",
     "license": "BSD-3-Clause",
     "support": {
diff --git a/extensions/jui/assets/jquery.ui.datepicker-i18n.js b/extensions/jui/assets/jquery.ui.datepicker-i18n.js
old mode 100755
new mode 100644
diff --git a/extensions/jui/assets/jquery.ui.effect-all.js b/extensions/jui/assets/jquery.ui.effect-all.js
old mode 100755
new mode 100644
diff --git a/extensions/jui/assets/theme/images/animated-overlay.gif b/extensions/jui/assets/theme/images/animated-overlay.gif
old mode 100755
new mode 100644
Binary files a/extensions/jui/assets/theme/images/animated-overlay.gif and b/extensions/jui/assets/theme/images/animated-overlay.gif differ
diff --git a/extensions/jui/assets/theme/images/ui-bg_flat_0_aaaaaa_40x100.png b/extensions/jui/assets/theme/images/ui-bg_flat_0_aaaaaa_40x100.png
old mode 100755
new mode 100644
Binary files a/extensions/jui/assets/theme/images/ui-bg_flat_0_aaaaaa_40x100.png and b/extensions/jui/assets/theme/images/ui-bg_flat_0_aaaaaa_40x100.png differ
diff --git a/extensions/jui/assets/theme/images/ui-bg_flat_75_ffffff_40x100.png b/extensions/jui/assets/theme/images/ui-bg_flat_75_ffffff_40x100.png
old mode 100755
new mode 100644
Binary files a/extensions/jui/assets/theme/images/ui-bg_flat_75_ffffff_40x100.png and b/extensions/jui/assets/theme/images/ui-bg_flat_75_ffffff_40x100.png differ
diff --git a/extensions/jui/assets/theme/images/ui-bg_glass_55_fbf9ee_1x400.png b/extensions/jui/assets/theme/images/ui-bg_glass_55_fbf9ee_1x400.png
old mode 100755
new mode 100644
Binary files a/extensions/jui/assets/theme/images/ui-bg_glass_55_fbf9ee_1x400.png and b/extensions/jui/assets/theme/images/ui-bg_glass_55_fbf9ee_1x400.png differ
diff --git a/extensions/jui/assets/theme/images/ui-bg_glass_65_ffffff_1x400.png b/extensions/jui/assets/theme/images/ui-bg_glass_65_ffffff_1x400.png
old mode 100755
new mode 100644
Binary files a/extensions/jui/assets/theme/images/ui-bg_glass_65_ffffff_1x400.png and b/extensions/jui/assets/theme/images/ui-bg_glass_65_ffffff_1x400.png differ
diff --git a/extensions/jui/assets/theme/images/ui-bg_glass_75_dadada_1x400.png b/extensions/jui/assets/theme/images/ui-bg_glass_75_dadada_1x400.png
old mode 100755
new mode 100644
Binary files a/extensions/jui/assets/theme/images/ui-bg_glass_75_dadada_1x400.png and b/extensions/jui/assets/theme/images/ui-bg_glass_75_dadada_1x400.png differ
diff --git a/extensions/jui/assets/theme/images/ui-bg_glass_75_e6e6e6_1x400.png b/extensions/jui/assets/theme/images/ui-bg_glass_75_e6e6e6_1x400.png
old mode 100755
new mode 100644
Binary files a/extensions/jui/assets/theme/images/ui-bg_glass_75_e6e6e6_1x400.png and b/extensions/jui/assets/theme/images/ui-bg_glass_75_e6e6e6_1x400.png differ
diff --git a/extensions/jui/assets/theme/images/ui-bg_glass_95_fef1ec_1x400.png b/extensions/jui/assets/theme/images/ui-bg_glass_95_fef1ec_1x400.png
old mode 100755
new mode 100644
Binary files a/extensions/jui/assets/theme/images/ui-bg_glass_95_fef1ec_1x400.png and b/extensions/jui/assets/theme/images/ui-bg_glass_95_fef1ec_1x400.png differ
diff --git a/extensions/jui/assets/theme/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/extensions/jui/assets/theme/images/ui-bg_highlight-soft_75_cccccc_1x100.png
old mode 100755
new mode 100644
Binary files a/extensions/jui/assets/theme/images/ui-bg_highlight-soft_75_cccccc_1x100.png and b/extensions/jui/assets/theme/images/ui-bg_highlight-soft_75_cccccc_1x100.png differ
diff --git a/extensions/jui/assets/theme/images/ui-icons_222222_256x240.png b/extensions/jui/assets/theme/images/ui-icons_222222_256x240.png
old mode 100755
new mode 100644
Binary files a/extensions/jui/assets/theme/images/ui-icons_222222_256x240.png and b/extensions/jui/assets/theme/images/ui-icons_222222_256x240.png differ
diff --git a/extensions/jui/assets/theme/images/ui-icons_2e83ff_256x240.png b/extensions/jui/assets/theme/images/ui-icons_2e83ff_256x240.png
old mode 100755
new mode 100644
Binary files a/extensions/jui/assets/theme/images/ui-icons_2e83ff_256x240.png and b/extensions/jui/assets/theme/images/ui-icons_2e83ff_256x240.png differ
diff --git a/extensions/jui/assets/theme/images/ui-icons_454545_256x240.png b/extensions/jui/assets/theme/images/ui-icons_454545_256x240.png
old mode 100755
new mode 100644
Binary files a/extensions/jui/assets/theme/images/ui-icons_454545_256x240.png and b/extensions/jui/assets/theme/images/ui-icons_454545_256x240.png differ
diff --git a/extensions/jui/assets/theme/images/ui-icons_888888_256x240.png b/extensions/jui/assets/theme/images/ui-icons_888888_256x240.png
old mode 100755
new mode 100644
Binary files a/extensions/jui/assets/theme/images/ui-icons_888888_256x240.png and b/extensions/jui/assets/theme/images/ui-icons_888888_256x240.png differ
diff --git a/extensions/jui/assets/theme/images/ui-icons_cd0a0a_256x240.png b/extensions/jui/assets/theme/images/ui-icons_cd0a0a_256x240.png
old mode 100755
new mode 100644
Binary files a/extensions/jui/assets/theme/images/ui-icons_cd0a0a_256x240.png and b/extensions/jui/assets/theme/images/ui-icons_cd0a0a_256x240.png differ
diff --git a/extensions/jui/assets/theme/jquery.ui.css b/extensions/jui/assets/theme/jquery.ui.css
old mode 100755
new mode 100644
diff --git a/extensions/jui/composer.json b/extensions/jui/composer.json
index 126df39..f129fef 100644
--- a/extensions/jui/composer.json
+++ b/extensions/jui/composer.json
@@ -1,7 +1,7 @@
 {
 	"name": "yiisoft/yii2-jui",
 	"description": "The Jquery UI extension for the Yii framework",
-	"keywords": ["yii", "Jquery UI", "renderer"],
+	"keywords": ["yii2", "Jquery UI", "renderer"],
 	"type": "yii2-extension",
 	"license": "BSD-3-Clause",
 	"support": {
diff --git a/extensions/mongodb/Collection.php b/extensions/mongodb/Collection.php
index 38144bc..6f595f8 100644
--- a/extensions/mongodb/Collection.php
+++ b/extensions/mongodb/Collection.php
@@ -260,7 +260,7 @@ class Collection extends Object
 	}
 
 	/**
-	 * Returns a a single document.
+	 * Returns a single document.
 	 * @param array $condition query condition
 	 * @param array $fields fields to be selected
 	 * @return array|null the single document. Null is returned if the query results in nothing.
@@ -272,6 +272,32 @@ class Collection extends Object
 	}
 
 	/**
+	 * Updates a document and returns it.
+	 * @param array $condition query condition
+	 * @param array $update update criteria
+	 * @param array $fields fields to be returned
+	 * @param array $options list of options in format: optionName => optionValue.
+	 * @return array|null the original document, or the modified document when $options['new'] is set.
+	 * @throws Exception on failure.
+	 * @see http://www.php.net/manual/en/mongocollection.findandmodify.php
+	 */
+	public function findAndModify($condition, $update, $fields = [], $options = [])
+	{
+		$condition = $this->buildCondition($condition);
+		$token = $this->composeLogToken('findAndModify', [$condition, $update, $fields, $options]);
+		Yii::info($token, __METHOD__);
+		try {
+			Yii::beginProfile($token, __METHOD__);
+			$result = $this->mongoCollection->findAndModify($condition, $update, $fields, $options);
+			Yii::endProfile($token, __METHOD__);
+			return $result;
+		} catch (\Exception $e) {
+			Yii::endProfile($token, __METHOD__);
+			throw new Exception($e->getMessage(), (int)$e->getCode(), $e);
+		}
+	}
+
+	/**
 	 * Inserts new data into collection.
 	 * @param array|object $data data to be inserted.
 	 * @param array $options list of options in format: optionName => optionValue.
diff --git a/extensions/mongodb/composer.json b/extensions/mongodb/composer.json
index d69a1a1..6556bd0 100644
--- a/extensions/mongodb/composer.json
+++ b/extensions/mongodb/composer.json
@@ -1,7 +1,7 @@
 {
 	"name": "yiisoft/yii2-mongodb",
 	"description": "MongoDb extension for the Yii framework",
-	"keywords": ["yii", "mongo", "mongodb", "active-record"],
+	"keywords": ["yii2", "mongo", "mongodb", "active-record"],
 	"type": "yii2-extension",
 	"license": "BSD-3-Clause",
 	"support": {
diff --git a/extensions/redis/composer.json b/extensions/redis/composer.json
index 3740013..7561028 100644
--- a/extensions/redis/composer.json
+++ b/extensions/redis/composer.json
@@ -1,7 +1,7 @@
 {
 	"name": "yiisoft/yii2-redis",
 	"description": "Redis Cache, Session and ActiveRecord for the Yii framework",
-	"keywords": ["yii", "redis", "active-record", "cache", "session"],
+	"keywords": ["yii2", "redis", "active-record", "cache", "session"],
 	"type": "yii2-extension",
 	"license": "BSD-3-Clause",
 	"support": {
diff --git a/extensions/smarty/composer.json b/extensions/smarty/composer.json
index 16b48bf..7d32b6d 100644
--- a/extensions/smarty/composer.json
+++ b/extensions/smarty/composer.json
@@ -1,7 +1,7 @@
 {
 	"name": "yiisoft/yii2-smarty",
 	"description": "The Smarty integration for the Yii framework",
-	"keywords": ["yii", "smarty", "renderer"],
+	"keywords": ["yii2", "smarty", "renderer"],
 	"type": "yii2-extension",
 	"license": "BSD-3-Clause",
 	"support": {
diff --git a/extensions/sphinx/composer.json b/extensions/sphinx/composer.json
index 9f31226..db3e928 100644
--- a/extensions/sphinx/composer.json
+++ b/extensions/sphinx/composer.json
@@ -1,7 +1,7 @@
 {
 	"name": "yiisoft/yii2-sphinx",
 	"description": "Sphinx full text search engine extension for the Yii framework",
-	"keywords": ["yii", "sphinx", "active-record", "search", "fulltext"],
+	"keywords": ["yii2", "sphinx", "active-record", "search", "fulltext"],
 	"type": "yii2-extension",
 	"license": "BSD-3-Clause",
 	"support": {
diff --git a/extensions/swiftmailer/Mailer.php b/extensions/swiftmailer/Mailer.php
index 891f2b5..8a87ba2 100644
--- a/extensions/swiftmailer/Mailer.php
+++ b/extensions/swiftmailer/Mailer.php
@@ -19,7 +19,7 @@ use yii\mail\BaseMailer;
  * ~~~
  * 'components' => [
  *     ...
- *     'email' => [
+ *     'mail' => [
  *         'class' => 'yii\swiftmailer\Mailer',
  *         'transport' => [
  *             'class' => 'Swift_SmtpTransport',
diff --git a/extensions/swiftmailer/composer.json b/extensions/swiftmailer/composer.json
index 4c9e831..f248942 100644
--- a/extensions/swiftmailer/composer.json
+++ b/extensions/swiftmailer/composer.json
@@ -1,7 +1,7 @@
 {
 	"name": "yiisoft/yii2-swiftmailer",
 	"description": "The SwiftMailer integration for the Yii framework",
-	"keywords": ["yii", "swift", "swiftmailer", "mail", "email", "mailer"],
+	"keywords": ["yii2", "swift", "swiftmailer", "mail", "email", "mailer"],
 	"type": "yii2-extension",
 	"license": "BSD-3-Clause",
 	"support": {
diff --git a/extensions/twig/composer.json b/extensions/twig/composer.json
index 1638058..ee7b0f8 100644
--- a/extensions/twig/composer.json
+++ b/extensions/twig/composer.json
@@ -1,7 +1,7 @@
 {
 	"name": "yiisoft/yii2-twig",
 	"description": "The Twig integration for the Yii framework",
-	"keywords": ["yii", "twig", "renderer"],
+	"keywords": ["yii2", "twig", "renderer"],
 	"type": "yii2-extension",
 	"license": "BSD-3-Clause",
 	"support": {
diff --git a/framework/BaseYii.php b/framework/BaseYii.php
index 9152afc..c70808e 100644
--- a/framework/BaseYii.php
+++ b/framework/BaseYii.php
@@ -356,7 +356,7 @@ class BaseYii
 			$config = array_merge(static::$objectConfig[$class], $config);
 		}
 
-		if (($n = func_num_args()) > 1) {
+		if (func_num_args() > 1) {
 			/** @var \ReflectionClass $reflection */
 			if (isset($reflections[$class])) {
 				$reflection = $reflections[$class];
diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md
index e705811..06eb826 100644
--- a/framework/CHANGELOG.md
+++ b/framework/CHANGELOG.md
@@ -49,6 +49,9 @@ Yii Framework 2 Change Log
 - Bug #2502: Unclear error message when `$_SERVER['DOCUMENT_ROOT']` is empty (samdark)
 - Bug #2519: MessageSource removed translation messages when event handler was bound to `missingTranslation`-event (cebe)
 - Bug #2527: Source language for `app` message category was always `en` no matter which application `sourceLanguage` was used (samdark)
+- Bug #2559: Going back on browser history breaks GridView filtering with `Pjax` (tonydspaniard)
+- Bug #2607: `yii message` tool wasn't updating `message` table (mitalcoi)
+- Bug #2624: Html::textArea() should respect "name" option. (qiangxue)
 - Bug: Fixed `Call to a member function registerAssetFiles() on a non-object` in case of wrong `sourcePath` for an asset bundle (samdark)
 - Bug: Fixed incorrect event name for `yii\jui\Spinner` (samdark)
 - Bug: Json::encode() did not handle objects that implement JsonSerializable interface correctly (cebe)
@@ -68,6 +71,7 @@ Yii Framework 2 Change Log
 - Enh #1293: Replaced Console::showProgress() with a better approach. See Console::startProgress() for details (cebe)
 - Enh #1406: DB Schema support for Oracle Database (p0larbeer, qiangxue)
 - Enh #1437: Added ListView::viewParams (qiangxue)
+- Enh #1467: Added support for organizing controllers in subdirectories (qiangxue)
 - Enh #1469: ActiveRecord::find() now works with default conditions (default scope) applied by createQuery (cebe)
 - Enh #1476: Add yii\web\Session::handler property (nineinchnick)
 - Enh #1499: Added `ActionColumn::controller` property to support customizing the controller for handling GridView actions (qiangxue)
diff --git a/framework/assets/pjax/LICENSE b/framework/assets/pjax/LICENSE
deleted file mode 100644
index 42c0317..0000000
--- a/framework/assets/pjax/LICENSE
+++ /dev/null
@@ -1,20 +0,0 @@
-Copyright (c) Chris Wanstrath
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-Software), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/framework/assets/pjax/jquery.pjax.js b/framework/assets/pjax/jquery.pjax.js
deleted file mode 100644
index 1934d80..0000000
--- a/framework/assets/pjax/jquery.pjax.js
+++ /dev/null
@@ -1,839 +0,0 @@
-// jquery.pjax.js
-// copyright chris wanstrath
-// https://github.com/defunkt/jquery-pjax
-
-(function($){
-
-// When called on a container with a selector, fetches the href with
-// ajax into the container or with the data-pjax attribute on the link
-// itself.
-//
-// Tries to make sure the back button and ctrl+click work the way
-// you'd expect.
-//
-// Exported as $.fn.pjax
-//
-// Accepts a jQuery ajax options object that may include these
-// pjax specific options:
-//
-//
-// container - Where to stick the response body. Usually a String selector.
-//             $(container).html(xhr.responseBody)
-//             (default: current jquery context)
-//      push - Whether to pushState the URL. Defaults to true (of course).
-//   replace - Want to use replaceState instead? That's cool.
-//
-// For convenience the second parameter can be either the container or
-// the options object.
-//
-// Returns the jQuery object
-	function fnPjax(selector, container, options) {
-		var context = this
-		return this.on('click.pjax', selector, function(event) {
-			var opts = $.extend({}, optionsFor(container, options))
-			if (!opts.container)
-				opts.container = $(this).attr('data-pjax') || context
-			handleClick(event, opts)
-		})
-	}
-
-// Public: pjax on click handler
-//
-// Exported as $.pjax.click.
-//
-// event   - "click" jQuery.Event
-// options - pjax options
-//
-// Examples
-//
-//   $(document).on('click', 'a', $.pjax.click)
-//   // is the same as
-//   $(document).pjax('a')
-//
-//  $(document).on('click', 'a', function(event) {
-//    var container = $(this).closest('[data-pjax-container]')
-//    $.pjax.click(event, container)
-//  })
-//
-// Returns nothing.
-	function handleClick(event, container, options) {
-		options = optionsFor(container, options)
-
-		var link = event.currentTarget
-
-		if (link.tagName.toUpperCase() !== 'A')
-			throw "$.fn.pjax or $.pjax.click requires an anchor element"
-
-		// Middle click, cmd click, and ctrl click should open
-		// links in a new tab as normal.
-		if ( event.which > 1 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey )
-			return
-
-		// Ignore cross origin links
-		if ( location.protocol !== link.protocol || location.hostname !== link.hostname )
-			return
-
-		// Ignore anchors on the same page
-		if (link.hash && link.href.replace(link.hash, '') ===
-			location.href.replace(location.hash, ''))
-			return
-
-		// Ignore empty anchor "foo.html#"
-		if (link.href === location.href + '#')
-			return
-
-		var defaults = {
-			url: link.href,
-			container: $(link).attr('data-pjax'),
-			target: link
-		}
-
-		var opts = $.extend({}, defaults, options)
-		var clickEvent = $.Event('pjax:click')
-		$(link).trigger(clickEvent, [opts])
-
-		if (!clickEvent.isDefaultPrevented()) {
-			pjax(opts)
-			event.preventDefault()
-			$(link).trigger('pjax:clicked', [opts])
-		}
-	}
-
-// Public: pjax on form submit handler
-//
-// Exported as $.pjax.submit
-//
-// event   - "click" jQuery.Event
-// options - pjax options
-//
-// Examples
-//
-//  $(document).on('submit', 'form', function(event) {
-//    var container = $(this).closest('[data-pjax-container]')
-//    $.pjax.submit(event, container)
-//  })
-//
-// Returns nothing.
-	function handleSubmit(event, container, options) {
-		options = optionsFor(container, options)
-
-		var form = event.currentTarget
-
-		if (form.tagName.toUpperCase() !== 'FORM')
-			throw "$.pjax.submit requires a form element"
-
-		var defaults = {
-			type: form.method.toUpperCase(),
-			url: form.action,
-			data: $(form).serializeArray(),
-			container: $(form).attr('data-pjax'),
-			target: form
-		}
-
-		pjax($.extend({}, defaults, options))
-
-		event.preventDefault()
-	}
-
-// Loads a URL with ajax, puts the response body inside a container,
-// then pushState()'s the loaded URL.
-//
-// Works just like $.ajax in that it accepts a jQuery ajax
-// settings object (with keys like url, type, data, etc).
-//
-// Accepts these extra keys:
-//
-// container - Where to stick the response body.
-//             $(container).html(xhr.responseBody)
-//      push - Whether to pushState the URL. Defaults to true (of course).
-//   replace - Want to use replaceState instead? That's cool.
-//
-// Use it just like $.ajax:
-//
-//   var xhr = $.pjax({ url: this.href, container: '#main' })
-//   console.log( xhr.readyState )
-//
-// Returns whatever $.ajax returns.
-	function pjax(options) {
-		options = $.extend(true, {}, $.ajaxSettings, pjax.defaults, options)
-
-		if ($.isFunction(options.url)) {
-			options.url = options.url()
-		}
-
-		var target = options.target
-
-		var hash = parseURL(options.url).hash
-
-		var context = options.context = findContainerFor(options.container)
-
-		// We want the browser to maintain two separate internal caches: one
-		// for pjax'd partial page loads and one for normal page loads.
-		// Without adding this secret parameter, some browsers will often
-		// confuse the two.
-		if (!options.data) options.data = {}
-		options.data._pjax = context.selector
-
-		function fire(type, args) {
-			var event = $.Event(type, { relatedTarget: target })
-			context.trigger(event, args)
-			return !event.isDefaultPrevented()
-		}
-
-		var timeoutTimer
-
-		options.beforeSend = function(xhr, settings) {
-			// No timeout for non-GET requests
-			// Its not safe to request the resource again with a fallback method.
-			if (settings.type !== 'GET') {
-				settings.timeout = 0
-			}
-
-			xhr.setRequestHeader('X-PJAX', 'true')
-			xhr.setRequestHeader('X-PJAX-Container', context.selector)
-
-			if (!fire('pjax:beforeSend', [xhr, settings]))
-				return false
-
-			if (settings.timeout > 0) {
-				timeoutTimer = setTimeout(function() {
-					if (fire('pjax:timeout', [xhr, options]))
-						xhr.abort('timeout')
-				}, settings.timeout)
-
-				// Clear timeout setting so jquerys internal timeout isn't invoked
-				settings.timeout = 0
-			}
-
-			options.requestUrl = parseURL(settings.url).href
-		}
-
-		options.complete = function(xhr, textStatus) {
-			if (timeoutTimer)
-				clearTimeout(timeoutTimer)
-
-			fire('pjax:complete', [xhr, textStatus, options])
-
-			fire('pjax:end', [xhr, options])
-		}
-
-		options.error = function(xhr, textStatus, errorThrown) {
-			var container = extractContainer("", xhr, options)
-
-			var allowed = fire('pjax:error', [xhr, textStatus, errorThrown, options])
-			if (options.type == 'GET' && textStatus !== 'abort' && allowed) {
-				locationReplace(container.url)
-			}
-		}
-
-		options.success = function(data, status, xhr) {
-			// If $.pjax.defaults.version is a function, invoke it first.
-			// Otherwise it can be a static string.
-			var currentVersion = (typeof $.pjax.defaults.version === 'function') ?
-				$.pjax.defaults.version() :
-				$.pjax.defaults.version
-
-			var latestVersion = xhr.getResponseHeader('X-PJAX-Version')
-
-			var container = extractContainer(data, xhr, options)
-
-			// If there is a layout version mismatch, hard load the new url
-			if (currentVersion && latestVersion && currentVersion !== latestVersion) {
-				locationReplace(container.url)
-				return
-			}
-
-			// If the new response is missing a body, hard load the page
-			if (!container.contents) {
-				locationReplace(container.url)
-				return
-			}
-
-			pjax.state = {
-				id: options.id || uniqueId(),
-				url: container.url,
-				title: container.title,
-				container: context.selector,
-				fragment: options.fragment,
-				timeout: options.timeout
-			}
-
-			if (options.push || options.replace) {
-				window.history.replaceState(pjax.state, container.title, container.url)
-			}
-
-			// Clear out any focused controls before inserting new page contents.
-			document.activeElement.blur()
-
-			if (container.title) document.title = container.title
-			context.html(container.contents)
-
-			// FF bug: Won't autofocus fields that are inserted via JS.
-			// This behavior is incorrect. So if theres no current focus, autofocus
-			// the last field.
-			//
-			// http://www.w3.org/html/wg/drafts/html/master/forms.html
-			var autofocusEl = context.find('input[autofocus], textarea[autofocus]').last()[0]
-			if (autofocusEl && document.activeElement !== autofocusEl) {
-				autofocusEl.focus();
-			}
-
-			executeScriptTags(container.scripts)
-
-			// Scroll to top by default
-			if (typeof options.scrollTo === 'number')
-				$(window).scrollTop(options.scrollTo)
-
-			// If the URL has a hash in it, make sure the browser
-			// knows to navigate to the hash.
-			if ( hash !== '' ) {
-				// Avoid using simple hash set here. Will add another history
-				// entry. Replace the url with replaceState and scroll to target
-				// by hand.
-				//
-				//   window.location.hash = hash
-				var url = parseURL(container.url)
-				url.hash = hash
-
-				pjax.state.url = url.href
-				window.history.replaceState(pjax.state, container.title, url.href)
-
-				var target = $(url.hash)
-				if (target.length) $(window).scrollTop(target.offset().top)
-			}
-
-			fire('pjax:success', [data, status, xhr, options])
-		}
-
-
-		// Initialize pjax.state for the initial page load. Assume we're
-		// using the container and options of the link we're loading for the
-		// back button to the initial page. This ensures good back button
-		// behavior.
-		if (!pjax.state) {
-			pjax.state = {
-				id: uniqueId(),
-				url: window.location.href,
-				title: document.title,
-				container: context.selector,
-				fragment: options.fragment,
-				timeout: options.timeout
-			}
-			window.history.replaceState(pjax.state, document.title)
-		}
-
-		// Cancel the current request if we're already pjaxing
-		var xhr = pjax.xhr
-		if ( xhr && xhr.readyState < 4) {
-			xhr.onreadystatechange = $.noop
-			xhr.abort()
-		}
-
-		pjax.options = options
-		var xhr = pjax.xhr = $.ajax(options)
-
-		if (xhr.readyState > 0) {
-			if (options.push && !options.replace) {
-				// Cache current container element before replacing it
-				cachePush(pjax.state.id, context.clone().contents())
-
-				window.history.pushState(null, "", stripPjaxParam(options.requestUrl))
-			}
-
-			fire('pjax:start', [xhr, options])
-			fire('pjax:send', [xhr, options])
-		}
-
-		return pjax.xhr
-	}
-
-// Public: Reload current page with pjax.
-//
-// Returns whatever $.pjax returns.
-	function pjaxReload(container, options) {
-		var defaults = {
-			url: window.location.href,
-			push: false,
-			replace: true,
-			scrollTo: false
-		}
-
-		return pjax($.extend(defaults, optionsFor(container, options)))
-	}
-
-// Internal: Hard replace current state with url.
-//
-// Work for around WebKit
-//   https://bugs.webkit.org/show_bug.cgi?id=93506
-//
-// Returns nothing.
-	function locationReplace(url) {
-		window.history.replaceState(null, "", "#")
-		window.location.replace(url)
-	}
-
-
-	var initialPop = true
-	var initialURL = window.location.href
-	var initialState = window.history.state
-
-// Initialize $.pjax.state if possible
-// Happens when reloading a page and coming forward from a different
-// session history.
-	if (initialState && initialState.container) {
-		pjax.state = initialState
-	}
-
-// Non-webkit browsers don't fire an initial popstate event
-	if ('state' in window.history) {
-		initialPop = false
-	}
-
-// popstate handler takes care of the back and forward buttons
-//
-// You probably shouldn't use pjax on pages with other pushState
-// stuff yet.
-	function onPjaxPopstate(event) {
-		var state = event.state
-
-		if (state && state.container) {
-			// When coming forward from a separate history session, will get an
-			// initial pop with a state we are already at. Skip reloading the current
-			// page.
-			if (initialPop && initialURL == state.url) return
-
-			// If popping back to the same state, just skip.
-			// Could be clicking back from hashchange rather than a pushState.
-			if (pjax.state.id === state.id) return
-
-			var container = $(state.container)
-			if (container.length) {
-				var direction, contents = cacheMapping[state.id]
-
-				if (pjax.state) {
-					// Since state ids always increase, we can deduce the history
-					// direction from the previous state.
-					direction = pjax.state.id < state.id ? 'forward' : 'back'
-
-					// Cache current container before replacement and inform the
-					// cache which direction the history shifted.
-					cachePop(direction, pjax.state.id, container.clone().contents())
-				}
-
-				var popstateEvent = $.Event('pjax:popstate', {
-					state: state,
-					direction: direction
-				})
-				container.trigger(popstateEvent)
-
-				var options = {
-					id: state.id,
-					url: state.url,
-					container: container,
-					push: false,
-					fragment: state.fragment,
-					timeout: state.timeout,
-					scrollTo: false
-				}
-
-				if (contents) {
-					container.trigger('pjax:start', [null, options])
-
-					if (state.title) document.title = state.title
-					container.html(contents)
-					pjax.state = state
-
-					container.trigger('pjax:end', [null, options])
-				} else {
-					pjax(options)
-				}
-
-				// Force reflow/relayout before the browser tries to restore the
-				// scroll position.
-				container[0].offsetHeight
-			} else {
-				locationReplace(location.href)
-			}
-		}
-		initialPop = false
-	}
-
-// Fallback version of main pjax function for browsers that don't
-// support pushState.
-//
-// Returns nothing since it retriggers a hard form submission.
-	function fallbackPjax(options) {
-		var url = $.isFunction(options.url) ? options.url() : options.url,
-			method = options.type ? options.type.toUpperCase() : 'GET'
-
-		var form = $('<form>', {
-			method: method === 'GET' ? 'GET' : 'POST',
-			action: url,
-			style: 'display:none'
-		})
-
-		if (method !== 'GET' && method !== 'POST') {
-			form.append($('<input>', {
-				type: 'hidden',
-				name: '_method',
-				value: method.toLowerCase()
-			}))
-		}
-
-		var data = options.data
-		if (typeof data === 'string') {
-			$.each(data.split('&'), function(index, value) {
-				var pair = value.split('=')
-				form.append($('<input>', {type: 'hidden', name: pair[0], value: pair[1]}))
-			})
-		} else if (typeof data === 'object') {
-			for (key in data)
-				form.append($('<input>', {type: 'hidden', name: key, value: data[key]}))
-		}
-
-		$(document.body).append(form)
-		form.submit()
-	}
-
-// Internal: Generate unique id for state object.
-//
-// Use a timestamp instead of a counter since ids should still be
-// unique across page loads.
-//
-// Returns Number.
-	function uniqueId() {
-		return (new Date).getTime()
-	}
-
-// Internal: Strips _pjax param from url
-//
-// url - String
-//
-// Returns String.
-	function stripPjaxParam(url) {
-		return url
-			.replace(/\?_pjax=[^&]+&?/, '?')
-			.replace(/_pjax=[^&]+&?/, '')
-			.replace(/[\?&]$/, '')
-	}
-
-// Internal: Parse URL components and returns a Locationish object.
-//
-// url - String URL
-//
-// Returns HTMLAnchorElement that acts like Location.
-	function parseURL(url) {
-		var a = document.createElement('a')
-		a.href = url
-		return a
-	}
-
-// Internal: Build options Object for arguments.
-//
-// For convenience the first parameter can be either the container or
-// the options object.
-//
-// Examples
-//
-//   optionsFor('#container')
-//   // => {container: '#container'}
-//
-//   optionsFor('#container', {push: true})
-//   // => {container: '#container', push: true}
-//
-//   optionsFor({container: '#container', push: true})
-//   // => {container: '#container', push: true}
-//
-// Returns options Object.
-	function optionsFor(container, options) {
-		// Both container and options
-		if ( container && options )
-			options.container = container
-
-		// First argument is options Object
-		else if ( $.isPlainObject(container) )
-			options = container
-
-		// Only container
-		else
-			options = {container: container}
-
-		// Find and validate container
-		if (options.container)
-			options.container = findContainerFor(options.container)
-
-		return options
-	}
-
-// Internal: Find container element for a variety of inputs.
-//
-// Because we can't persist elements using the history API, we must be
-// able to find a String selector that will consistently find the Element.
-//
-// container - A selector String, jQuery object, or DOM Element.
-//
-// Returns a jQuery object whose context is `document` and has a selector.
-	function findContainerFor(container) {
-		container = $(container)
-
-		if ( !container.length ) {
-			throw "no pjax container for " + container.selector
-		} else if ( container.selector !== '' && container.context === document ) {
-			return container
-		} else if ( container.attr('id') ) {
-			return $('#' + container.attr('id'))
-		} else {
-			throw "cant get selector for pjax container!"
-		}
-	}
-
-// Internal: Filter and find all elements matching the selector.
-//
-// Where $.fn.find only matches descendants, findAll will test all the
-// top level elements in the jQuery object as well.
-//
-// elems    - jQuery object of Elements
-// selector - String selector to match
-//
-// Returns a jQuery object.
-	function findAll(elems, selector) {
-		return elems.filter(selector).add(elems.find(selector));
-	}
-
-	function parseHTML(html) {
-		return $.parseHTML(html, document, true)
-	}
-
-// Internal: Extracts container and metadata from response.
-//
-// 1. Extracts X-PJAX-URL header if set
-// 2. Extracts inline <title> tags
-// 3. Builds response Element and extracts fragment if set
-//
-// data    - String response data
-// xhr     - XHR response
-// options - pjax options Object
-//
-// Returns an Object with url, title, and contents keys.
-	function extractContainer(data, xhr, options) {
-		var obj = {}
-
-		// Prefer X-PJAX-URL header if it was set, otherwise fallback to
-		// using the original requested url.
-		obj.url = stripPjaxParam(xhr.getResponseHeader('X-PJAX-URL') || options.requestUrl)
-
-		// Attempt to parse response html into elements
-		if (/<html/i.test(data)) {
-			var $head = $(parseHTML(data.match(/<head[^>]*>([\s\S.]*)<\/head>/i)[0]))
-			var $body = $(parseHTML(data.match(/<body[^>]*>([\s\S.]*)<\/body>/i)[0]))
-		} else {
-			var $head = $body = $(parseHTML(data))
-		}
-
-		// If response data is empty, return fast
-		if ($body.length === 0)
-			return obj
-
-		// If there's a <title> tag in the header, use it as
-		// the page's title.
-		obj.title = findAll($head, 'title').last().text()
-
-		if (options.fragment) {
-			// If they specified a fragment, look for it in the response
-			// and pull it out.
-			if (options.fragment === 'body') {
-				var $fragment = $body
-			} else {
-				var $fragment = findAll($body, options.fragment).first()
-			}
-
-			if ($fragment.length) {
-				obj.contents = $fragment.contents()
-
-				// If there's no title, look for data-title and title attributes
-				// on the fragment
-				if (!obj.title)
-					obj.title = $fragment.attr('title') || $fragment.data('title')
-			}
-
-		} else if (!/<html/i.test(data)) {
-			obj.contents = $body
-		}
-
-		// Clean up any <title> tags
-		if (obj.contents) {
-			// Remove any parent title elements
-			obj.contents = obj.contents.not(function() { return $(this).is('title') })
-
-			// Then scrub any titles from their descendants
-			obj.contents.find('title').remove()
-
-			// Gather all script[src] elements
-			obj.scripts = findAll(obj.contents, 'script[src]').remove()
-			obj.contents = obj.contents.not(obj.scripts)
-		}
-
-		// Trim any whitespace off the title
-		if (obj.title) obj.title = $.trim(obj.title)
-
-		return obj
-	}
-
-// Load an execute scripts using standard script request.
-//
-// Avoids jQuery's traditional $.getScript which does a XHR request and
-// globalEval.
-//
-// scripts - jQuery object of script Elements
-//
-// Returns nothing.
-	function executeScriptTags(scripts) {
-		if (!scripts) return
-
-		var existingScripts = $('script[src]')
-
-		scripts.each(function() {
-			var src = this.src
-			var matchedScripts = existingScripts.filter(function() {
-				return this.src === src
-			})
-			if (matchedScripts.length) return
-
-			var script = document.createElement('script')
-			script.type = $(this).attr('type')
-			script.src = $(this).attr('src')
-			document.head.appendChild(script)
-		})
-	}
-
-// Internal: History DOM caching class.
-	var cacheMapping      = {}
-	var cacheForwardStack = []
-	var cacheBackStack    = []
-
-// Push previous state id and container contents into the history
-// cache. Should be called in conjunction with `pushState` to save the
-// previous container contents.
-//
-// id    - State ID Number
-// value - DOM Element to cache
-//
-// Returns nothing.
-	function cachePush(id, value) {
-		cacheMapping[id] = value
-		cacheBackStack.push(id)
-
-		// Remove all entires in forward history stack after pushing
-		// a new page.
-		while (cacheForwardStack.length)
-			delete cacheMapping[cacheForwardStack.shift()]
-
-		// Trim back history stack to max cache length.
-		while (cacheBackStack.length > pjax.defaults.maxCacheLength)
-			delete cacheMapping[cacheBackStack.shift()]
-	}
-
-// Shifts cache from directional history cache. Should be
-// called on `popstate` with the previous state id and container
-// contents.
-//
-// direction - "forward" or "back" String
-// id        - State ID Number
-// value     - DOM Element to cache
-//
-// Returns nothing.
-	function cachePop(direction, id, value) {
-		var pushStack, popStack
-		cacheMapping[id] = value
-
-		if (direction === 'forward') {
-			pushStack = cacheBackStack
-			popStack  = cacheForwardStack
-		} else {
-			pushStack = cacheForwardStack
-			popStack  = cacheBackStack
-		}
-
-		pushStack.push(id)
-		if (id = popStack.pop())
-			delete cacheMapping[id]
-	}
-
-// Public: Find version identifier for the initial page load.
-//
-// Returns String version or undefined.
-	function findVersion() {
-		return $('meta').filter(function() {
-			var name = $(this).attr('http-equiv')
-			return name && name.toUpperCase() === 'X-PJAX-VERSION'
-		}).attr('content')
-	}
-
-// Install pjax functions on $.pjax to enable pushState behavior.
-//
-// Does nothing if already enabled.
-//
-// Examples
-//
-//     $.pjax.enable()
-//
-// Returns nothing.
-	function enable() {
-		$.fn.pjax = fnPjax
-		$.pjax = pjax
-		$.pjax.enable = $.noop
-		$.pjax.disable = disable
-		$.pjax.click = handleClick
-		$.pjax.submit = handleSubmit
-		$.pjax.reload = pjaxReload
-		$.pjax.defaults = {
-			timeout: 650,
-			push: true,
-			replace: false,
-			type: 'GET',
-			dataType: 'html',
-			scrollTo: 0,
-			maxCacheLength: 20,
-			version: findVersion
-		}
-		$(window).on('popstate.pjax', onPjaxPopstate)
-	}
-
-// Disable pushState behavior.
-//
-// This is the case when a browser doesn't support pushState. It is
-// sometimes useful to disable pushState for debugging on a modern
-// browser.
-//
-// Examples
-//
-//     $.pjax.disable()
-//
-// Returns nothing.
-	function disable() {
-		$.fn.pjax = function() { return this }
-		$.pjax = fallbackPjax
-		$.pjax.enable = enable
-		$.pjax.disable = $.noop
-		$.pjax.click = $.noop
-		$.pjax.submit = $.noop
-		$.pjax.reload = function() { window.location.reload() }
-
-		$(window).off('popstate.pjax', onPjaxPopstate)
-	}
-
-
-// Add the state property to jQuery's event object so we can use it in
-// $(window).bind('popstate')
-	if ( $.inArray('state', $.event.props) < 0 )
-		$.event.props.push('state')
-
-// Is pjax supported by this browser?
-	$.support.pjax =
-		window.history && window.history.pushState && window.history.replaceState &&
-			// pushState isn't reliable on iOS until 5.
-			!navigator.userAgent.match(/((iPod|iPhone|iPad).+\bOS\s+[1-4]|WebApps\/.+CFNetwork)/)
-
-	$.support.pjax ? enable() : disable()
-
-})(jQuery);
diff --git a/framework/assets/yii.gridView.js b/framework/assets/yii.gridView.js
index 496e3cd..ca2b99a 100644
--- a/framework/assets/yii.gridView.js
+++ b/framework/assets/yii.gridView.js
@@ -26,17 +26,18 @@
 		filterSelector: undefined
 	};
 
+	var gridData = {};
+
 	var methods = {
 		init: function (options) {
 			return this.each(function () {
 				var $e = $(this);
 				var settings = $.extend({}, defaults, options || {});
-				$e.data('yiiGridView', {
-					settings: settings
-				});
+				gridData[$e.prop('id')] = {settings: settings};
 
 				var enterPressed = false;
-				$(settings.filterSelector).on('change.yiiGridView keydown.yiiGridView', function (event) {
+				$(document).off('change.yiiGridView keydown.yiiGridView', settings.filterSelector)
+					.on('change.yiiGridView keydown.yiiGridView', settings.filterSelector, function (event) {
 					if (event.type === 'keydown') {
 						if (event.keyCode !== 13) {
 							return; // only react to enter key
@@ -60,7 +61,7 @@
 
 		applyFilter: function () {
 			var $grid = $(this);
-			var settings = $grid.data('yiiGridView').settings;
+			var settings = gridData[$grid.prop('id')].settings;
 			var data = {};
 			$.each($(settings.filterSelector).serializeArray(), function () {
 				data[this.name] = this.value;
@@ -85,15 +86,16 @@
 
 		setSelectionColumn: function (options) {
 			var $grid = $(this);
-			var data = $grid.data('yiiGridView');
-			data.selectionColumn = options.name;
+			var id = $(this).prop('id');
+			gridData[id].selectionColumn = options.name;
 			if (!options.multiple) {
 				return;
 			}
-			$grid.on('click.yiiGridView', "input[name='" + options.checkAll + "']", function () {
+			var inputs = "#" + id + " input[name='" + options.checkAll + "']";
+			$(document).off('click.yiiGridView', inputs).on('click.yiiGridView', inputs, function () {
 				$grid.find("input[name='" + options.name + "']:enabled").prop('checked', this.checked);
 			});
-			$grid.on('click.yiiGridView', "input[name='" + options.name + "']:enabled", function () {
+			$(document).off('click.yiiGridView', inputs + ":enabled").on('click.yiiGridView', inputs + ":enabled", function () {
 				var all = $grid.find("input[name='" + options.name + "']").length == $grid.find("input[name='" + options.name + "']:checked").length;
 				$grid.find("input[name='" + options.checkAll + "']").prop('checked', all);
 			});
@@ -101,7 +103,7 @@
 
 		getSelectedRows: function () {
 			var $grid = $(this);
-			var data = $grid.data('yiiGridView');
+			var data = gridData[$grid.prop('id')];
 			var keys = [];
 			if (data.selectionColumn) {
 				$grid.find("input[name='" + data.selectionColumn + "']:checked").each(function () {
@@ -118,8 +120,9 @@
 			});
 		},
 
-		data: function() {
-			return this.data('yiiGridView');
+		data: function () {
+			var id = $(this).prop('id');
+			return gridData[id];
 		}
 	};
 })(window.jQuery);
diff --git a/framework/base/Formatter.php b/framework/base/Formatter.php
index 78fdac8..80c08e1 100644
--- a/framework/base/Formatter.php
+++ b/framework/base/Formatter.php
@@ -442,17 +442,17 @@ class Formatter extends Component
 		
 		switch($position) {
 			case 0:
-				return $verbose ? Yii::t('yii','{n, plural, =1{# byte} other{# bytes}}', $params) : Yii::t('yii', '{n} B', $params);
+				return $verbose ? Yii::t('yii', '{n, plural, =1{# byte} other{# bytes}}', $params) : Yii::t('yii', '{n} B', $params);
 			case 1:
-				return $verbose ? Yii::t('yii','{n, plural, =1{# kilobyte} other{# kilobytes}}', $params) : Yii::t('yii','{n} KB', $params);
+				return $verbose ? Yii::t('yii', '{n, plural, =1{# kilobyte} other{# kilobytes}}', $params) : Yii::t('yii', '{n} KB', $params);
 			case 2:
-				return $verbose ? Yii::t('yii','{n, plural, =1{# megabyte} other{# megabytes}}', $params) : Yii::t('yii','{n} MB', $params);
+				return $verbose ? Yii::t('yii', '{n, plural, =1{# megabyte} other{# megabytes}}', $params) : Yii::t('yii', '{n} MB', $params);
 			case 3:
-				return $verbose ? Yii::t('yii','{n, plural, =1{# gigabyte} other{# gigabytes}}', $params) : Yii::t('yii','{n} GB', $params);
+				return $verbose ? Yii::t('yii', '{n, plural, =1{# gigabyte} other{# gigabytes}}', $params) : Yii::t('yii', '{n} GB', $params);
 			case 4:
-				return $verbose ? Yii::t('yii','{n, plural, =1{# terabyte} other{# terabytes}}', $params) : Yii::t('yii','{n} TB', $params);
+				return $verbose ? Yii::t('yii', '{n, plural, =1{# terabyte} other{# terabytes}}', $params) : Yii::t('yii', '{n} TB', $params);
 			default:
-				return $verbose ? Yii::t('yii','{n, plural, =1{# petabyte} other{# petabytes}}', $params) : Yii::t('yii','{n} PB', $params);
+				return $verbose ? Yii::t('yii', '{n, plural, =1{# petabyte} other{# petabytes}}', $params) : Yii::t('yii', '{n} PB', $params);
 		}
 	}
 }
diff --git a/framework/base/Module.php b/framework/base/Module.php
index 2f31e88..cba919d 100644
--- a/framework/base/Module.php
+++ b/framework/base/Module.php
@@ -596,12 +596,21 @@ class Module extends Component
 	}
 
 	/**
-	 * Creates a controller instance based on the controller ID.
+	 * Creates a controller instance based on the given route.
 	 *
-	 * The controller is created within this module. The method first attempts to
-	 * create the controller based on the [[controllerMap]] of the module. If not available,
-	 * it will look for the controller class under the [[controllerPath]] and create an
-	 * instance of it.
+	 * The route should be relative to this module. The method implements the following algorithm
+	 * to resolve the given route:
+	 *
+	 * 1. If the route is empty, use [[defaultRoute]];
+	 * 2. If the first segment of the route is a valid module ID as declared in [[modules]],
+	 *    call the module's `createController()` with the rest part of the route;
+	 * 3. If the first segment of the route is found in [[controllerMap]], create a controller
+	 *    based on the corresponding configuration found in [[controllerMap]];
+	 * 4. The given route is in the format of `abc/def/xyz`. Try either `abc\DefController`
+	 *    or `abc\def\XyzController` class within the [[controllerNamespace|controller namespace]].
+	 *
+	 * If any of the above steps resolves into a controller, it is returned together with the rest
+	 * part of the route which will be treated as the action ID. Otherwise, false will be returned.
 	 *
 	 * @param string $route the route consisting of module, controller and action IDs.
 	 * @return array|boolean If the controller is created successfully, it will be returned together
@@ -613,6 +622,13 @@ class Module extends Component
 		if ($route === '') {
 			$route = $this->defaultRoute;
 		}
+
+		// double slashes or leading/ending slashes may cause substr problem
+		$route = trim($route, '/');
+		if (strpos($route, '//') !== false) {
+			return false;
+		}
+
 		if (strpos($route, '/') !== false) {
 			list ($id, $route) = explode('/', $route, 2);
 		} else {
@@ -620,29 +636,73 @@ class Module extends Component
 			$route = '';
 		}
 
+		// module and controller map take precedence
 		$module = $this->getModule($id);
 		if ($module !== null) {
 			return $module->createController($route);
 		}
-
 		if (isset($this->controllerMap[$id])) {
 			$controller = Yii::createObject($this->controllerMap[$id], $id, $this);
-		} elseif (preg_match('/^[a-z0-9\\-_]+$/', $id) && strpos($id, '--') === false && trim($id, '-') === $id) {
-			$className = str_replace(' ', '', ucwords(str_replace('-', ' ', $id))) . 'Controller';
-			$classFile = $this->controllerPath . DIRECTORY_SEPARATOR . $className . '.php';
-			if (!is_file($classFile)) {
-				return false;
-			}
-			$className = ltrim($this->controllerNamespace . '\\' . $className, '\\');
-			Yii::$classMap[$className] = $classFile;
-			if (is_subclass_of($className, 'yii\base\Controller')) {
-				$controller = new $className($id, $this);
-			} elseif (YII_DEBUG) {
-				throw new InvalidConfigException("Controller class must extend from \\yii\\base\\Controller.");
-			}
+			return [$controller, $route];
+		}
+
+		if (($pos = strrpos($route, '/')) !== false) {
+			$id .= '/' . substr($route, 0, $pos);
+			$route = substr($route, $pos + 1);
+		}
+
+		$controller = $this->createControllerByID($id);
+		if ($controller === null && $route !== '') {
+			$controller = $this->createControllerByID($id . '/' . $route);
+			$route = '';
+		}
+
+		return $controller === null ? false : [$controller, $route];
+	}
+
+	/**
+	 * Creates a controller based on the given controller ID.
+	 *
+	 * The controller ID is relative to this module. The controller class
+	 * should be located under [[controllerPath]] and namespaced under [[controllerNamespace]].
+	 *
+	 * Note that this method does not check [[modules]] or [[controllerMap]].
+	 *
+	 * @param string $id the controller ID
+	 * @return Controller the newly created controller instance, or null if the controller ID is invalid.
+	 * @throws InvalidConfigException if the controller class and its file name do not match.
+	 * This exception is only thrown when in debug mode.
+	 */
+	public function createControllerByID($id)
+	{
+		if (!preg_match('%^[a-z0-9\\-_/]+$%', $id)) {
+			return null;
 		}
 
-		return isset($controller) ? [$controller, $route] : false;
+		$pos = strrpos($id, '/');
+		if ($pos === false) {
+			$prefix = '';
+			$className = $id;
+		} else {
+			$prefix = substr($id, 0, $pos + 1);
+			$className = substr($id, $pos + 1);
+		}
+
+		$className = str_replace(' ', '', ucwords(str_replace('-', ' ', $className))) . 'Controller';
+		$classFile = $this->controllerPath . '/' . $prefix . $className . '.php';
+		$className = ltrim($this->controllerNamespace . '\\' . str_replace('/', '\\', $prefix)  . $className, '\\');
+		if (strpos($className, '-') !== false || !is_file($classFile)) {
+			return null;
+		}
+
+		Yii::$classMap[$className] = $classFile;
+		if (is_subclass_of($className, 'yii\base\Controller')) {
+			return new $className($id, $this);
+		} elseif (YII_DEBUG) {
+			throw new InvalidConfigException("Controller class must extend from \\yii\\base\\Controller.");
+		} else {
+			return null;
+		}
 	}
 
 	/**
diff --git a/framework/base/Request.php b/framework/base/Request.php
index b76886e..eb9f805 100644
--- a/framework/base/Request.php
+++ b/framework/base/Request.php
@@ -6,6 +6,7 @@
  */
 
 namespace yii\base;
+
 use Yii;
 
 /**
diff --git a/framework/base/Theme.php b/framework/base/Theme.php
index 01a6964..63382ad 100644
--- a/framework/base/Theme.php
+++ b/framework/base/Theme.php
@@ -13,7 +13,7 @@ use yii\helpers\FileHelper;
 /**
  * Theme represents an application theme.
  *
- * When [[View]] renders a view file, it will check the [[Application::theme|active theme]]
+ * When [[View]] renders a view file, it will check the [[View::theme|active theme]]
  * to see if there is a themed version of the view file exists. If so, the themed version will be rendered instead.
  *
  * A theme is a directory consisting of view files which are meant to replace their non-themed counterparts.
diff --git a/framework/caching/FileDependency.php b/framework/caching/FileDependency.php
index 11afde3..200cdde 100644
--- a/framework/caching/FileDependency.php
+++ b/framework/caching/FileDependency.php
@@ -6,6 +6,7 @@
  */
 
 namespace yii\caching;
+
 use yii\base\InvalidConfigException;
 
 /**
diff --git a/framework/caching/GroupDependency.php b/framework/caching/GroupDependency.php
index 1cf7869..bcac858 100644
--- a/framework/caching/GroupDependency.php
+++ b/framework/caching/GroupDependency.php
@@ -6,6 +6,7 @@
  */
 
 namespace yii\caching;
+
 use yii\base\InvalidConfigException;
 
 /**
diff --git a/framework/composer.json b/framework/composer.json
index bd11fc7..5a34ab0 100644
--- a/framework/composer.json
+++ b/framework/composer.json
@@ -1,7 +1,7 @@
 {
 	"name": "yiisoft/yii2",
 	"description": "Yii PHP Framework Version 2",
-	"keywords": ["yii", "framework"],
+	"keywords": ["yii2", "framework"],
 	"homepage": "http://www.yiiframework.com/",
 	"type": "library",
 	"license": "BSD-3-Clause",
@@ -54,6 +54,7 @@
 		"lib-pcre": "*",
 		"yiisoft/yii2-composer": "*",
 		"yiisoft/jquery": "~2.0 | ~1.10",
+		"yiisoft/jquery-pjax": "*",
 		"ezyang/htmlpurifier": "4.6.*",
 		"cebe/markdown": "0.9.*"
 	},
diff --git a/framework/console/controllers/FixtureController.php b/framework/console/controllers/FixtureController.php
index 858f08f..c72efd2 100644
--- a/framework/console/controllers/FixtureController.php
+++ b/framework/console/controllers/FixtureController.php
@@ -64,7 +64,7 @@ class FixtureController extends Controller
 	public function globalOptions()
 	{
 		return array_merge(parent::globalOptions(), [
-			'namespace','globalFixtures'
+			'namespace', 'globalFixtures'
 		]);
 	}
 
@@ -74,6 +74,7 @@ class FixtureController extends Controller
 	 * whitespace between names. Note that if you are loading fixtures to storage, for example: database or nosql,
 	 * storage will not be cleared, data will be appended to already existed.
 	 * @param array $fixtures
+	 * @param array $except
 	 * @throws \yii\console\Exception
 	 */
 	public function actionLoad(array $fixtures, array $except = [])
@@ -99,7 +100,7 @@ class FixtureController extends Controller
 		}
 
 		$filtered = array_diff($foundFixtures, $except);
-		$fixtures = $this->getFixturesConfig(array_merge($this->globalFixtures ,$filtered));
+		$fixtures = $this->getFixturesConfig(array_merge($this->globalFixtures, $filtered));
 
 		if (!$fixtures) {
 			throw new Exception('No fixtures were found in namespace: "' . $this->namespace . '"' . '');
@@ -317,5 +318,4 @@ class FixtureController extends Controller
 	{
 		return Yii::getAlias('@' . str_replace('\\', '/', $this->namespace));
 	}
-
 }
diff --git a/framework/console/controllers/MessageController.php b/framework/console/controllers/MessageController.php
index 0345b69..cb34a38 100644
--- a/framework/console/controllers/MessageController.php
+++ b/framework/console/controllers/MessageController.php
@@ -134,11 +134,14 @@ class MessageController extends Controller
 				throw new Exception('The "db" option must refer to a valid database application component.');
 			}
 			$sourceMessageTable = isset($config['sourceMessageTable']) ? $config['sourceMessageTable'] : '{{%source_message}}';
+			$messageTable = isset($config['messageTable']) ? $config['messageTable'] : '{{%message}}';
 			$this->saveMessagesToDb(
 				$messages,
 				$db,
 				$sourceMessageTable,
-				$config['removeUnused']
+				$messageTable,
+				$config['removeUnused'],
+				$config['languages']
 			);
 		}
 	}
@@ -149,9 +152,11 @@ class MessageController extends Controller
 	 * @param array $messages
 	 * @param \yii\db\Connection $db
 	 * @param string $sourceMessageTable
+	 * @param string $messageTable
 	 * @param boolean $removeUnused
+	 * @param array $languages
 	 */
-	protected function saveMessagesToDb($messages, $db, $sourceMessageTable, $removeUnused)
+	protected function saveMessagesToDb($messages, $db, $sourceMessageTable, $messageTable, $removeUnused, $languages)
 	{
 		$q = new \yii\db\Query;
 		$current = [];
@@ -190,12 +195,17 @@ class MessageController extends Controller
 		echo "Inserting new messages...";
 		$savedFlag = false;
 
-		foreach ($new  as $category => $msgs) {
+		foreach ($new as $category => $msgs) {
 			foreach ($msgs as $m) {
 				$savedFlag = true;
 
 				$db->createCommand()
-					->insert($sourceMessageTable, ['category' => $category, 'message' => $m])->execute();
+				->insert($sourceMessageTable, ['category' => $category, 'message' => $m])->execute();
+				$lastId = $db->getLastInsertID();
+				foreach ($languages as $language) {
+					$db->createCommand()
+					->insert($messageTable, ['id' => $lastId, 'language' => $language])->execute();
+				}
 			}
 		}
 
@@ -207,15 +217,20 @@ class MessageController extends Controller
 		} else {
 			if ($removeUnused) {
 				$db->createCommand()
-					->delete($sourceMessageTable, ['in', 'id', $obsolete])->execute();
-			echo "deleted.\n";
+				->delete($sourceMessageTable, ['in', 'id', $obsolete])->execute();
+				echo "deleted.\n";
 			} else {
+				$last_id = $db->getLastInsertID();
 				$db->createCommand()
-					->update(
+				->update(
 						$sourceMessageTable,
 						['message' => new \yii\db\Expression("CONCAT('@@',message,'@@')")],
 						['in', 'id', $obsolete]
 					)->execute();
+				foreach ($languages as $language) {
+					$db->createCommand()
+					->insert($messageTable, ['id' => $last_id, 'language' => $language])->execute();
+				}
 				echo "updated.\n";
 			}
 		}
@@ -268,7 +283,7 @@ class MessageController extends Controller
 	{
 		echo "Saving messages to $fileName...";
 		if (is_file($fileName)) {
-			if($format === 'po'){
+			if ($format === 'po') {
 				$translated = file_get_contents($fileName);
 				preg_match_all('/(?<=msgid ").*(?="\n(#*)msgstr)/', $translated, $keys);
 				preg_match_all('/(?<=msgstr ").*(?="\n\n)/', $translated, $values);
@@ -285,7 +300,7 @@ class MessageController extends Controller
 			$merged = [];
 			$untranslated = [];
 			foreach ($messages as $message) {
-				if($format === 'po'){
+				if ($format === 'po') {
 					$message = preg_replace('/\"/', '\"', $message);
 				}
 				if (array_key_exists($message, $translated) && strlen($translated[$message]) > 0) {
@@ -317,9 +332,9 @@ class MessageController extends Controller
 			if (false === $overwrite) {
 				$fileName .= '.merged';
 			}
-			if ($format === 'po'){
+			if ($format === 'po') {
 				$output = '';
-				foreach ($merged as $k => $v){
+				foreach ($merged as $k => $v) {
 					$k = preg_replace('/(\")|(\\\")/', "\\\"", $k);
 					$v = preg_replace('/(\")|(\\\")/', "\\\"", $v);
 					if (substr($v, 0, 2) === '@@' && substr($v, -2) === '@@') {
@@ -338,7 +353,7 @@ class MessageController extends Controller
 			if ($format === 'po') {
 				$merged = '';
 				sort($messages);
-				foreach($messages as $message) {
+				foreach ($messages as $message) {
 					$message = preg_replace('/(\")|(\\\")/', '\\\"', $message);
 					$merged .= "msgid \"$message\"\n";
 					$merged .= "msgstr \"\"\n";
diff --git a/framework/db/ActiveQuery.php b/framework/db/ActiveQuery.php
index ee92f22..23e7f1f 100644
--- a/framework/db/ActiveQuery.php
+++ b/framework/db/ActiveQuery.php
@@ -120,7 +120,7 @@ class ActiveQuery extends Query implements ActiveQueryInterface
 			$this->findWith($this->with, $models);
 		}
 		if (!$this->asArray) {
-			foreach($models as $model) {
+			foreach ($models as $model) {
 				$model->afterFind();
 			}
 		}
diff --git a/framework/db/ActiveRecord.php b/framework/db/ActiveRecord.php
index e7461c6..539508b 100644
--- a/framework/db/ActiveRecord.php
+++ b/framework/db/ActiveRecord.php
@@ -35,9 +35,6 @@ use yii\helpers\StringHelper;
  *
  * class Customer extends \yii\db\ActiveRecord
  * {
- *     /**
- *      * @return string the name of the table associated with this ActiveRecord class.
- *      * /
  *     public static function tableName()
  *     {
  *         return 'tbl_customer';
diff --git a/framework/db/ActiveRecordInterface.php b/framework/db/ActiveRecordInterface.php
index 47cdb75..737abbf 100644
--- a/framework/db/ActiveRecordInterface.php
+++ b/framework/db/ActiveRecordInterface.php
@@ -87,6 +87,13 @@ interface ActiveRecordInterface
 	public function getOldPrimaryKey($asArray = false);
 
 	/**
+	 * Returns a value indicating whether the given set of attributes represents the primary key for this model
+	 * @param array $keys the set of attributes to check
+	 * @return boolean whether the given set of attributes represents the primary key for this model
+	 */
+	public static function isPrimaryKey($keys);
+
+	/**
 	 * Creates an [[ActiveQueryInterface|ActiveQuery]] instance for query purpose.
 	 *
 	 * This method is usually ment to be used like this:
diff --git a/framework/db/ActiveRelationTrait.php b/framework/db/ActiveRelationTrait.php
index ab06c16..32f6953 100644
--- a/framework/db/ActiveRelationTrait.php
+++ b/framework/db/ActiveRelationTrait.php
@@ -288,7 +288,7 @@ trait ActiveRelationTrait
 				foreach ($primaryModels as $i => $primaryModel) {
 					if ($primaryModels[$i][$primaryName] instanceof ActiveRecordInterface) {
 						$primaryModels[$i][$primaryName]->populateRelation($name, $primaryModel);
-					} elseif  (!empty($primaryModels[$i][$primaryName])) {
+					} elseif (!empty($primaryModels[$i][$primaryName])) {
 						$primaryModels[$i][$primaryName][$name] = $primaryModel;
 					}
 				}
diff --git a/framework/db/BaseActiveRecord.php b/framework/db/BaseActiveRecord.php
index 4436545..69bc1da 100644
--- a/framework/db/BaseActiveRecord.php
+++ b/framework/db/BaseActiveRecord.php
@@ -19,6 +19,8 @@ use yii\base\InvalidCallException;
 /**
  * ActiveRecord is the base class for classes representing relational data in terms of objects.
  *
+ * See [[yii\db\ActiveRecord]] for a concrete implementation.
+ *
  * @property array $dirtyAttributes The changed attribute values (name-value pairs). This property is
  * read-only.
  * @property boolean $isNewRecord Whether the record is new and should be inserted when calling [[save()]].
@@ -342,7 +344,7 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface
 	 */
 	public function hasOne($class, $link)
 	{
-		/** @var ActiveRecord $class */
+		/** @var ActiveRecordInterface $class */
 		return $class::createQuery([
 			'modelClass' => $class,
 			'primaryModel' => $this,
@@ -383,7 +385,7 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface
 	 */
 	public function hasMany($class, $link)
 	{
-		/** @var ActiveRecord $class */
+		/** @var ActiveRecordInterface $class */
 		return $class::createQuery([
 			'modelClass' => $class,
 			'primaryModel' => $this,
@@ -396,7 +398,7 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface
 	 * Populates the named relation with the related records.
 	 * Note that this method does not check if the relation exists or not.
 	 * @param string $name the relation name (case-sensitive)
-	 * @param ActiveRecord|array|null $records the related records to be populated into the relation.
+	 * @param ActiveRecordInterface|array|null $records the related records to be populated into the relation.
 	 */
 	public function populateRelation($name, $records)
 	{
@@ -936,7 +938,7 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface
 	 * Returns a value indicating whether the given active record is the same as the current one.
 	 * The comparison is made by comparing the table names and the primary key values of the two active records.
 	 * If one of the records [[isNewRecord|is new]] they are also considered not equal.
-	 * @param ActiveRecord $record record to compare to
+	 * @param ActiveRecordInterface $record record to compare to
 	 * @return boolean whether the two active records refer to the same row in the same database table.
 	 */
 	public function equals($record)
@@ -1104,7 +1106,7 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface
 	 * Note that this method requires that the primary key value is not null.
 	 *
 	 * @param string $name the case sensitive name of the relationship
-	 * @param ActiveRecord $model the model to be linked with the current one.
+	 * @param ActiveRecordInterface $model the model to be linked with the current one.
 	 * @param array $extraColumns additional column values to be saved into the pivot table.
 	 * This parameter is only meaningful for a relationship involving a pivot table
 	 * (i.e., a relation set with [[ActiveRelationTrait::via()]] or `[[ActiveQuery::viaTable()]]`.)
@@ -1139,8 +1141,8 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface
 				$columns[$k] = $v;
 			}
 			if (is_array($relation->via)) {
-				/** @var $viaClass ActiveRecord */
-				/** @var $record ActiveRecord */
+				/** @var $viaClass ActiveRecordInterface */
+				/** @var $record ActiveRecordInterface */
 				$record = new $viaClass();
 				foreach ($columns as $column => $value) {
 					$record->$column = $value;
@@ -1191,7 +1193,7 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface
 	 * Otherwise, the foreign key will be set null and the model will be saved without validation.
 	 *
 	 * @param string $name the case sensitive name of the relationship.
-	 * @param ActiveRecord $model the model to be unlinked from the current one.
+	 * @param ActiveRecordInterface $model the model to be unlinked from the current one.
 	 * @param boolean $delete whether to delete the model that contains the foreign key.
 	 * If false, the model's foreign key will be set null and saved.
 	 * If true, the model containing the foreign key will be deleted.
@@ -1219,7 +1221,7 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface
 				$columns[$b] = $model->$a;
 			}
 			if (is_array($relation->via)) {
-				/** @var $viaClass ActiveRecord */
+				/** @var $viaClass ActiveRecordInterface */
 				if ($delete) {
 					$viaClass::deleteAll($columns);
 				} else {
@@ -1231,6 +1233,7 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface
 				}
 			} else {
 				/** @var $viaTable string */
+				/** @var Command $command */
 				$command = static::getDb()->createCommand();
 				if ($delete) {
 					$command->delete($viaTable, $columns)->execute();
@@ -1263,7 +1266,7 @@ abstract class BaseActiveRecord extends Model implements ActiveRecordInterface
 		if (!$relation->multiple) {
 			unset($this->_related[$name]);
 		} elseif (isset($this->_related[$name])) {
-			/** @var ActiveRecord $b */
+			/** @var ActiveRecordInterface $b */
 			foreach ($this->_related[$name] as $a => $b) {
 				if ($model->getPrimaryKey() == $b->getPrimaryKey()) {
 					unset($this->_related[$name][$a]);
diff --git a/framework/db/BatchQueryResult.php b/framework/db/BatchQueryResult.php
index 774d416..3a1ba11 100644
--- a/framework/db/BatchQueryResult.php
+++ b/framework/db/BatchQueryResult.php
@@ -108,6 +108,7 @@ class BatchQueryResult extends Object implements \Iterator
 	{
 		if ($this->_batch === null || !$this->each || $this->each && next($this->_batch) === false) {
 			$this->_batch = $this->fetchData();
+			reset($this->_batch);
 		}
 
 		if ($this->each) {
diff --git a/framework/db/QueryBuilder.php b/framework/db/QueryBuilder.php
index e6b6e01..124848b 100644
--- a/framework/db/QueryBuilder.php
+++ b/framework/db/QueryBuilder.php
@@ -599,7 +599,7 @@ class QueryBuilder extends \yii\base\Object
 				if (strpos($column, '(') === false) {
 					$column = $this->db->quoteColumnName($column);
 				}
-				$columns[$i] = "$column AS " . $this->db->quoteColumnName($i);;
+				$columns[$i] = "$column AS " . $this->db->quoteColumnName($i);
 			} elseif (strpos($column, '(') === false) {
 				if (preg_match('/^(.*?)(?i:\s+as\s+|\s+)([\w\-_\.]+)$/', $column, $matches)) {
 					$columns[$i] = $this->db->quoteColumnName($matches[1]) . ' AS ' . $this->db->quoteColumnName($matches[2]);
diff --git a/framework/db/oci/Schema.php b/framework/db/oci/Schema.php
index e29a77b..1edbf6b 100644
--- a/framework/db/oci/Schema.php
+++ b/framework/db/oci/Schema.php
@@ -242,7 +242,7 @@ EOD;
 		} elseif (strpos($dbType, 'NUMBER') !== false || strpos($dbType, 'INTEGER') !== false) {
 			if (strpos($dbType, '(') && preg_match('/\((.*)\)/', $dbType, $matches)) {
 				$values = explode(',', $matches[1]);
-				if (isset($values[1]) and (((int)$values[1]) > 0)) {
+				if (isset($values[1]) && (((int)$values[1]) > 0)) {
 					$column->type = 'double';
 				} else {
 					$column->type = 'integer';
diff --git a/framework/grid/ActionColumn.php b/framework/grid/ActionColumn.php
index ffcfe0a..7d42bec 100644
--- a/framework/grid/ActionColumn.php
+++ b/framework/grid/ActionColumn.php
@@ -88,6 +88,7 @@ class ActionColumn extends Column
 			$this->buttons['view'] = function ($url, $model) {
 				return Html::a('<span class="glyphicon glyphicon-eye-open"></span>', $url, [
 					'title' => Yii::t('yii', 'View'),
+					'data-pjax' => '0',
 				]);
 			};
 		}
@@ -95,6 +96,7 @@ class ActionColumn extends Column
 			$this->buttons['update'] = function ($url, $model) {
 				return Html::a('<span class="glyphicon glyphicon-pencil"></span>', $url, [
 					'title' => Yii::t('yii', 'Update'),
+					'data-pjax' => '0',
 				]);
 			};
 		}
@@ -104,6 +106,7 @@ class ActionColumn extends Column
 					'title' => Yii::t('yii', 'Delete'),
 					'data-confirm' => Yii::t('yii', 'Are you sure to delete this item?'),
 					'data-method' => 'post',
+					'data-pjax' => '0',
 				]);
 			};
 		}
diff --git a/framework/grid/DataColumn.php b/framework/grid/DataColumn.php
index a8ef9ad..7b0f493 100644
--- a/framework/grid/DataColumn.php
+++ b/framework/grid/DataColumn.php
@@ -152,7 +152,7 @@ class DataColumn extends Column
 			return parent::getDataCellContent($model, $key, $index);
 		}
 		return $value;
-	}	 
+	}
 
 	/**
 	 * @inheritdoc
diff --git a/framework/helpers/BaseFileHelper.php b/framework/helpers/BaseFileHelper.php
index c544a91..6da4712 100644
--- a/framework/helpers/BaseFileHelper.php
+++ b/framework/helpers/BaseFileHelper.php
@@ -147,6 +147,7 @@ class BaseFileHelper
 	 * @param string $src the source directory
 	 * @param string $dst the destination directory
 	 * @param array $options options for directory copy. Valid options are:
+	 * @throws \yii\base\InvalidParamException if unable to open directory
 	 *
 	 * - dirMode: integer, the permission to be set for newly copied directories. Defaults to 0775.
 	 * - fileMode:  integer, the permission to be set for newly copied files. Defaults to the current environment setting.
@@ -280,14 +281,14 @@ class BaseFileHelper
 			$options['basePath'] = realpath($dir);
 			// this should also be done only once
 			if (isset($options['except'])) {
-				foreach($options['except'] as $key=>$value) {
+				foreach ($options['except'] as $key => $value) {
 					if (is_string($value)) {
 						$options['except'][$key] = static::parseExcludePattern($value);
 					}
 				}
 			}
 			if (isset($options['only'])) {
-				foreach($options['only'] as $key=>$value) {
+				foreach ($options['only'] as $key => $value) {
 					if (is_string($value)) {
 						$options['only'][$key] = static::parseExcludePattern($value);
 					}
@@ -397,7 +398,7 @@ class BaseFileHelper
 			if ($pattern === $baseName) {
 				return true;
 			}
-		} else if ($flags & self::PATTERN_ENDSWITH) {
+		} elseif ($flags & self::PATTERN_ENDSWITH) {
 			/* "*literal" matching against "fooliteral" */
 			$n = StringHelper::byteLength($pattern);
 			if (StringHelper::byteSubstr($pattern, 1, $n) === StringHelper::byteSubstr($baseName, -$n, $n)) {
@@ -472,7 +473,7 @@ class BaseFileHelper
 	 */
 	private static function lastExcludeMatchingFromList($basePath, $path, $excludes)
 	{
-		foreach(array_reverse($excludes) as $exclude) {
+		foreach (array_reverse($excludes) as $exclude) {
 			if (is_string($exclude)) {
 				$exclude = self::parseExcludePattern($exclude);
 			}
@@ -508,13 +509,14 @@ class BaseFileHelper
 		if (!is_string($pattern)) {
 			throw new InvalidParamException('Exclude/include pattern must be a string.');
 		}
-		$result = array(
+		$result = [
 			'pattern' => $pattern,
 			'flags' => 0,
 			'firstWildcard' => false,
-		);
-		if (!isset($pattern[0]))
+		];
+		if (!isset($pattern[0])) {
 			return $result;
+		}
 
 		if ($pattern[0] == '!') {
 			$result['flags'] |= self::PATTERN_NEGATIVE;
@@ -526,11 +528,13 @@ class BaseFileHelper
 			$len--;
 			$result['flags'] |= self::PATTERN_MUSTBEDIR;
 		}
-		if (strpos($pattern, '/') === false)
+		if (strpos($pattern, '/') === false) {
 			$result['flags'] |= self::PATTERN_NODIR;
+		}
 		$result['firstWildcard'] = self::firstWildcardInPattern($pattern);
-		if ($pattern[0] == '*' && self::firstWildcardInPattern(StringHelper::byteSubstr($pattern, 1, StringHelper::byteLength($pattern))) === false)
+		if ($pattern[0] == '*' && self::firstWildcardInPattern(StringHelper::byteSubstr($pattern, 1, StringHelper::byteLength($pattern))) === false) {
 			$result['flags'] |= self::PATTERN_ENDSWITH;
+		}
 		$result['pattern'] = $pattern;
 		return $result;
 	}
@@ -542,8 +546,8 @@ class BaseFileHelper
 	 */
 	private static function firstWildcardInPattern($pattern)
 	{
-		$wildcards = array('*','?','[','\\');
-		$wildcardSearch = function($r, $c) use ($pattern) {
+		$wildcards = ['*', '?', '[', '\\'];
+		$wildcardSearch = function ($r, $c) use ($pattern) {
 			$p = strpos($pattern, $c);
 			return $r===false ? $p : ($p===false ? $r : min($r, $p));
 		};
diff --git a/framework/helpers/BaseHtml.php b/framework/helpers/BaseHtml.php
index 01151ec..f0fe5b4 100644
--- a/framework/helpers/BaseHtml.php
+++ b/framework/helpers/BaseHtml.php
@@ -120,7 +120,7 @@ class BaseHtml
 	 * For example when using `['class' => 'my-class', 'target' => '_blank', 'value' => null]` it will result in the
 	 * html attributes rendered like this: `class="my-class" target="_blank"`.
 	 *
-	 * See [[renderTagAttributes()]] for details on how these are beeing rendered.
+	 * See [[renderTagAttributes()]] for details on how these are being rendered.
 	 *
 	 * @return string the generated HTML tag
 	 * @see beginTag()
@@ -138,7 +138,7 @@ class BaseHtml
 	 * @param array $options the tag options in terms of name-value pairs. These will be rendered as
 	 * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
 	 * If a value is null, the corresponding attribute will not be rendered.
-	 * See [[renderTagAttributes()]] for details on how these are beeing rendered.
+	 * See [[renderTagAttributes()]] for details on how these are being rendered.
 	 * @return string the generated start tag
 	 * @see endTag()
 	 * @see tag()
@@ -167,7 +167,7 @@ class BaseHtml
 	 * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
 	 * If a value is null, the corresponding attribute will not be rendered.
 	 * If the options does not contain "type", a "type" attribute with value "text/css" will be used.
-	 * See [[renderTagAttributes()]] for details on how these are beeing rendered.
+	 * See [[renderTagAttributes()]] for details on how these are being rendered.
 	 * @return string the generated style tag
 	 */
 	public static function style($content, $options = [])
@@ -182,7 +182,7 @@ class BaseHtml
 	 * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
 	 * If a value is null, the corresponding attribute will not be rendered.
 	 * If the options does not contain "type", a "type" attribute with value "text/javascript" will be rendered.
-	 * See [[renderTagAttributes()]] for details on how these are beeing rendered.
+	 * See [[renderTagAttributes()]] for details on how these are being rendered.
 	 * @return string the generated script tag
 	 */
 	public static function script($content, $options = [])
@@ -196,7 +196,7 @@ class BaseHtml
 	 * @param array $options the tag options in terms of name-value pairs. These will be rendered as
 	 * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
 	 * If a value is null, the corresponding attribute will not be rendered.
-	 * See [[renderTagAttributes()]] for details on how these are beeing rendered.
+	 * See [[renderTagAttributes()]] for details on how these are being rendered.
 	 * @return string the generated link tag
 	 * @see url()
 	 */
@@ -215,7 +215,7 @@ class BaseHtml
 	 * @param array $options the tag options in terms of name-value pairs. These will be rendered as
 	 * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
 	 * If a value is null, the corresponding attribute will not be rendered.
-	 * See [[renderTagAttributes()]] for details on how these are beeing rendered.
+	 * See [[renderTagAttributes()]] for details on how these are being rendered.
 	 * @return string the generated script tag
 	 * @see url()
 	 */
@@ -235,7 +235,7 @@ class BaseHtml
 	 * @param array $options the tag options in terms of name-value pairs. These will be rendered as
 	 * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
 	 * If a value is null, the corresponding attribute will not be rendered.
-	 * See [[renderTagAttributes()]] for details on how these are beeing rendered.
+	 * See [[renderTagAttributes()]] for details on how these are being rendered.
 	 * @return string the generated form start tag.
 	 * @see endForm()
 	 */
@@ -304,7 +304,7 @@ class BaseHtml
 	 * @param array $options the tag options in terms of name-value pairs. These will be rendered as
 	 * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
 	 * If a value is null, the corresponding attribute will not be rendered.
-	 * See [[renderTagAttributes()]] for details on how these are beeing rendered.
+	 * See [[renderTagAttributes()]] for details on how these are being rendered.
 	 * @return string the generated hyperlink
 	 * @see url()
 	 */
@@ -326,7 +326,7 @@ class BaseHtml
 	 * @param array $options the tag options in terms of name-value pairs. These will be rendered as
 	 * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
 	 * If a value is null, the corresponding attribute will not be rendered.
-	 * See [[renderTagAttributes()]] for details on how these are beeing rendered.
+	 * See [[renderTagAttributes()]] for details on how these are being rendered.
 	 * @return string the generated mailto link
 	 */
 	public static function mailto($text, $email = null, $options = [])
@@ -341,7 +341,7 @@ class BaseHtml
 	 * @param array $options the tag options in terms of name-value pairs. These will be rendered as
 	 * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
 	 * If a value is null, the corresponding attribute will not be rendered.
-	 * See [[renderTagAttributes()]] for details on how these are beeing rendered.
+	 * See [[renderTagAttributes()]] for details on how these are being rendered.
 	 * @return string the generated image tag
 	 */
 	public static function img($src, $options = [])
@@ -363,7 +363,7 @@ class BaseHtml
 	 * @param array $options the tag options in terms of name-value pairs. These will be rendered as
 	 * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
 	 * If a value is null, the corresponding attribute will not be rendered.
-	 * See [[renderTagAttributes()]] for details on how these are beeing rendered.
+	 * See [[renderTagAttributes()]] for details on how these are being rendered.
 	 * @return string the generated label tag
 	 */
 	public static function label($content, $for = null, $options = [])
@@ -380,7 +380,7 @@ class BaseHtml
 	 * @param array $options the tag options in terms of name-value pairs. These will be rendered as
 	 * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
 	 * If a value is null, the corresponding attribute will not be rendered.
-	 * See [[renderTagAttributes()]] for details on how these are beeing rendered.
+	 * See [[renderTagAttributes()]] for details on how these are being rendered.
 	 * @return string the generated button tag
 	 */
 	public static function button($content = 'Button', $options = [])
@@ -396,7 +396,7 @@ class BaseHtml
 	 * @param array $options the tag options in terms of name-value pairs. These will be rendered as
 	 * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
 	 * If a value is null, the corresponding attribute will not be rendered.
-	 * See [[renderTagAttributes()]] for details on how these are beeing rendered.
+	 * See [[renderTagAttributes()]] for details on how these are being rendered.
 	 * @return string the generated submit button tag
 	 */
 	public static function submitButton($content = 'Submit', $options = [])
@@ -413,7 +413,7 @@ class BaseHtml
 	 * @param array $options the tag options in terms of name-value pairs. These will be rendered as
 	 * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
 	 * If a value is null, the corresponding attribute will not be rendered.
-	 * See [[renderTagAttributes()]] for details on how these are beeing rendered.
+	 * See [[renderTagAttributes()]] for details on how these are being rendered.
 	 * @return string the generated reset button tag
 	 */
 	public static function resetButton($content = 'Reset', $options = [])
@@ -430,7 +430,7 @@ class BaseHtml
 	 * @param array $options the tag options in terms of name-value pairs. These will be rendered as
 	 * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
 	 * If a value is null, the corresponding attribute will not be rendered.
-	 * See [[renderTagAttributes()]] for details on how these are beeing rendered.
+	 * See [[renderTagAttributes()]] for details on how these are being rendered.
 	 * @return string the generated input tag
 	 */
 	public static function input($type, $name = null, $value = null, $options = [])
@@ -447,7 +447,7 @@ class BaseHtml
 	 * @param array $options the tag options in terms of name-value pairs. These will be rendered as
 	 * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
 	 * If a value is null, the corresponding attribute will not be rendered.
-	 * See [[renderTagAttributes()]] for details on how these are beeing rendered.
+	 * See [[renderTagAttributes()]] for details on how these are being rendered.
 	 * @return string the generated button tag
 	 */
 	public static function buttonInput($label = 'Button', $options = [])
@@ -463,7 +463,7 @@ class BaseHtml
 	 * @param array $options the tag options in terms of name-value pairs. These will be rendered as
 	 * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
 	 * If a value is null, the corresponding attribute will not be rendered.
-	 * See [[renderTagAttributes()]] for details on how these are beeing rendered.
+	 * See [[renderTagAttributes()]] for details on how these are being rendered.
 	 * @return string the generated button tag
 	 */
 	public static function submitInput($label = 'Submit', $options = [])
@@ -478,7 +478,7 @@ class BaseHtml
 	 * @param string $label the value attribute. If it is null, the value attribute will not be generated.
 	 * @param array $options the attributes of the button tag. The values will be HTML-encoded using [[encode()]].
 	 * Attributes whose value is null will be ignored and not put in the tag returned.
-	 * See [[renderTagAttributes()]] for details on how these are beeing rendered.
+	 * See [[renderTagAttributes()]] for details on how these are being rendered.
 	 * @return string the generated button tag
 	 */
 	public static function resetInput($label = 'Reset', $options = [])
@@ -495,7 +495,7 @@ class BaseHtml
 	 * @param array $options the tag options in terms of name-value pairs. These will be rendered as
 	 * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
 	 * If a value is null, the corresponding attribute will not be rendered.
-	 * See [[renderTagAttributes()]] for details on how these are beeing rendered.
+	 * See [[renderTagAttributes()]] for details on how these are being rendered.
 	 * @return string the generated button tag
 	 */
 	public static function textInput($name, $value = null, $options = [])
@@ -510,7 +510,7 @@ class BaseHtml
 	 * @param array $options the tag options in terms of name-value pairs. These will be rendered as
 	 * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
 	 * If a value is null, the corresponding attribute will not be rendered.
-	 * See [[renderTagAttributes()]] for details on how these are beeing rendered.
+	 * See [[renderTagAttributes()]] for details on how these are being rendered.
 	 * @return string the generated button tag
 	 */
 	public static function hiddenInput($name, $value = null, $options = [])
@@ -525,7 +525,7 @@ class BaseHtml
 	 * @param array $options the tag options in terms of name-value pairs. These will be rendered as
 	 * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
 	 * If a value is null, the corresponding attribute will not be rendered.
-	 * See [[renderTagAttributes()]] for details on how these are beeing rendered.
+	 * See [[renderTagAttributes()]] for details on how these are being rendered.
 	 * @return string the generated button tag
 	 */
 	public static function passwordInput($name, $value = null, $options = [])
@@ -543,7 +543,7 @@ class BaseHtml
 	 * @param array $options the tag options in terms of name-value pairs. These will be rendered as
 	 * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
 	 * If a value is null, the corresponding attribute will not be rendered.
-	 * See [[renderTagAttributes()]] for details on how these are beeing rendered.
+	 * See [[renderTagAttributes()]] for details on how these are being rendered.
 	 * @return string the generated button tag
 	 */
 	public static function fileInput($name, $value = null, $options = [])
@@ -558,7 +558,7 @@ class BaseHtml
 	 * @param array $options the tag options in terms of name-value pairs. These will be rendered as
 	 * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
 	 * If a value is null, the corresponding attribute will not be rendered.
-	 * See [[renderTagAttributes()]] for details on how these are beeing rendered.
+	 * See [[renderTagAttributes()]] for details on how these are being rendered.
 	 * @return string the generated text area tag
 	 */
 	public static function textarea($name, $value = '', $options = [])
@@ -586,7 +586,7 @@ class BaseHtml
 	 *
 	 * The rest of the options will be rendered as the attributes of the resulting radio button tag. The values will
 	 * be HTML-encoded using [[encode()]]. If a value is null, the corresponding attribute will not be rendered.
-	 * See [[renderTagAttributes()]] for details on how these are beeing rendered.
+	 * See [[renderTagAttributes()]] for details on how these are being rendered.
 	 *
 	 * @return string the generated radio button tag
 	 */
@@ -636,7 +636,7 @@ class BaseHtml
 	 *
 	 * The rest of the options will be rendered as the attributes of the resulting checkbox tag. The values will
 	 * be HTML-encoded using [[encode()]]. If a value is null, the corresponding attribute will not be rendered.
-	 * See [[renderTagAttributes()]] for details on how these are beeing rendered.
+	 * See [[renderTagAttributes()]] for details on how these are being rendered.
 	 *
 	 * @return string the generated checkbox tag
 	 */
@@ -697,7 +697,7 @@ class BaseHtml
 	 *
 	 * The rest of the options will be rendered as the attributes of the resulting tag. The values will
 	 * be HTML-encoded using [[encode()]]. If a value is null, the corresponding attribute will not be rendered.
-	 * See [[renderTagAttributes()]] for details on how these are beeing rendered.
+	 * See [[renderTagAttributes()]] for details on how these are being rendered.
 	 *
 	 * @return string the generated drop-down list tag
 	 */
@@ -744,7 +744,7 @@ class BaseHtml
 	 *
 	 * The rest of the options will be rendered as the attributes of the resulting tag. The values will
 	 * be HTML-encoded using [[encode()]]. If a value is null, the corresponding attribute will not be rendered.
-	 * See [[renderTagAttributes()]] for details on how these are beeing rendered.
+	 * See [[renderTagAttributes()]] for details on how these are being rendered.
 	 *
 	 * @return string the generated list box tag
 	 */
@@ -800,7 +800,7 @@ class BaseHtml
 	 * is the label for the checkbox; and $name, $value and $checked represent the name,
 	 * value and the checked status of the checkbox input, respectively.
 	 *
-	 * See [[renderTagAttributes()]] for details on how these are beeing rendered.
+	 * See [[renderTagAttributes()]] for details on how these are being rendered.
 	 *
 	 * @return string the generated checkbox list
 	 */
@@ -871,7 +871,7 @@ class BaseHtml
 	 * is the label for the radio button; and $name, $value and $checked represent the name,
 	 * value and the checked status of the radio button input, respectively.
 	 *
-	 * See [[renderTagAttributes()]] for details on how these are beeing rendered.
+	 * See [[renderTagAttributes()]] for details on how these are being rendered.
 	 *
 	 * @return string the generated radio button list
 	 */
@@ -930,7 +930,7 @@ class BaseHtml
 	 * where $index is the array key corresponding to `$item` in `$items`. The callback should return
 	 * the whole list item tag.
 	 *
-	 * See [[renderTagAttributes()]] for details on how these are beeing rendered.
+	 * See [[renderTagAttributes()]] for details on how these are being rendered.
 	 *
 	 * @return string the generated unordered list. An empty string is returned if `$items` is empty.
 	 */
@@ -974,7 +974,7 @@ class BaseHtml
 	 * where $index is the array key corresponding to `$item` in `$items`. The callback should return
 	 * the whole list item tag.
 	 *
-	 * See [[renderTagAttributes()]] for details on how these are beeing rendered.
+	 * See [[renderTagAttributes()]] for details on how these are being rendered.
 	 *
 	 * @return string the generated ordered list. An empty string is returned if `$items` is empty.
 	 */
@@ -999,7 +999,7 @@ class BaseHtml
 	 *   If this is not set, [[Model::getAttributeLabel()]] will be called to get the label for display
 	 *   (after encoding).
 	 *
-	 * See [[renderTagAttributes()]] for details on how these are beeing rendered.
+	 * See [[renderTagAttributes()]] for details on how these are being rendered.
 	 *
 	 * @return string the generated label tag
 	 */
@@ -1025,7 +1025,7 @@ class BaseHtml
 	 *
 	 * - tag: this specifies the tag name. If not set, "div" will be used.
 	 *
-	 * See [[renderTagAttributes()]] for details on how these are beeing rendered.
+	 * See [[renderTagAttributes()]] for details on how these are being rendered.
 	 *
 	 * @return string the generated label tag
 	 */
@@ -1048,7 +1048,7 @@ class BaseHtml
 	 * about attribute expression.
 	 * @param array $options the tag options in terms of name-value pairs. These will be rendered as
 	 * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
-	 * See [[renderTagAttributes()]] for details on how these are beeing rendered.
+	 * See [[renderTagAttributes()]] for details on how these are being rendered.
 	 * @return string the generated input tag
 	 */
 	public static function activeInput($type, $model, $attribute, $options = [])
@@ -1070,7 +1070,7 @@ class BaseHtml
 	 * about attribute expression.
 	 * @param array $options the tag options in terms of name-value pairs. These will be rendered as
 	 * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
-	 * See [[renderTagAttributes()]] for details on how these are beeing rendered.
+	 * See [[renderTagAttributes()]] for details on how these are being rendered.
 	 * @return string the generated input tag
 	 */
 	public static function activeTextInput($model, $attribute, $options = [])
@@ -1087,7 +1087,7 @@ class BaseHtml
 	 * about attribute expression.
 	 * @param array $options the tag options in terms of name-value pairs. These will be rendered as
 	 * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
-	 * See [[renderTagAttributes()]] for details on how these are beeing rendered.
+	 * See [[renderTagAttributes()]] for details on how these are being rendered.
 	 * @return string the generated input tag
 	 */
 	public static function activeHiddenInput($model, $attribute, $options = [])
@@ -1104,7 +1104,7 @@ class BaseHtml
 	 * about attribute expression.
 	 * @param array $options the tag options in terms of name-value pairs. These will be rendered as
 	 * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
-	 * See [[renderTagAttributes()]] for details on how these are beeing rendered.
+	 * See [[renderTagAttributes()]] for details on how these are being rendered.
 	 * @return string the generated input tag
 	 */
 	public static function activePasswordInput($model, $attribute, $options = [])
@@ -1121,7 +1121,7 @@ class BaseHtml
 	 * about attribute expression.
 	 * @param array $options the tag options in terms of name-value pairs. These will be rendered as
 	 * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
-	 * See [[renderTagAttributes()]] for details on how these are beeing rendered.
+	 * See [[renderTagAttributes()]] for details on how these are being rendered.
 	 * @return string the generated input tag
 	 */
 	public static function activeFileInput($model, $attribute, $options = [])
@@ -1140,12 +1140,12 @@ class BaseHtml
 	 * about attribute expression.
 	 * @param array $options the tag options in terms of name-value pairs. These will be rendered as
 	 * the attributes of the resulting tag. The values will be HTML-encoded using [[encode()]].
-	 * See [[renderTagAttributes()]] for details on how these are beeing rendered.
+	 * See [[renderTagAttributes()]] for details on how these are being rendered.
 	 * @return string the generated textarea tag
 	 */
 	public static function activeTextarea($model, $attribute, $options = [])
 	{
-		$name = static::getInputName($model, $attribute);
+		$name = isset($options['name']) ? $options['name'] : static::getInputName($model, $attribute);
 		$value = static::getAttributeValue($model, $attribute);
 		if (!array_key_exists('id', $options)) {
 			$options['id'] = static::getInputId($model, $attribute);
@@ -1173,7 +1173,7 @@ class BaseHtml
 	 * The rest of the options will be rendered as the attributes of the resulting tag. The values will
 	 * be HTML-encoded using [[encode()]]. If a value is null, the corresponding attribute will not be rendered.
 	 *
-	 * See [[renderTagAttributes()]] for details on how these are beeing rendered.
+	 * See [[renderTagAttributes()]] for details on how these are being rendered.
 	 *
 	 * @return string the generated radio button tag
 	 */
@@ -1216,7 +1216,7 @@ class BaseHtml
 	 *
 	 * The rest of the options will be rendered as the attributes of the resulting tag. The values will
 	 * be HTML-encoded using [[encode()]]. If a value is null, the corresponding attribute will not be rendered.
-	 * See [[renderTagAttributes()]] for details on how these are beeing rendered.
+	 * See [[renderTagAttributes()]] for details on how these are being rendered.
 	 *
 	 * @return string the generated checkbox tag
 	 */
@@ -1272,7 +1272,7 @@ class BaseHtml
 	 *
 	 * The rest of the options will be rendered as the attributes of the resulting tag. The values will
 	 * be HTML-encoded using [[encode()]]. If a value is null, the corresponding attribute will not be rendered.
-	 * See [[renderTagAttributes()]] for details on how these are beeing rendered.
+	 * See [[renderTagAttributes()]] for details on how these are being rendered.
 	 *
 	 * @return string the generated drop-down list tag
 	 */
@@ -1324,7 +1324,7 @@ class BaseHtml
 	 *
 	 * The rest of the options will be rendered as the attributes of the resulting tag. The values will
 	 * be HTML-encoded using [[encode()]]. If a value is null, the corresponding attribute will not be rendered.
-	 * See [[renderTagAttributes()]] for details on how these are beeing rendered.
+	 * See [[renderTagAttributes()]] for details on how these are being rendered.
 	 *
 	 * @return string the generated list box tag
 	 */
@@ -1369,7 +1369,7 @@ class BaseHtml
 	 * is the label for the checkbox; and $name, $value and $checked represent the name,
 	 * value and the checked status of the checkbox input.
 	 *
-	 * See [[renderTagAttributes()]] for details on how these are beeing rendered.
+	 * See [[renderTagAttributes()]] for details on how these are being rendered.
 	 *
 	 * @return string the generated checkbox list
 	 */
@@ -1413,7 +1413,7 @@ class BaseHtml
 	 * is the label for the radio button; and $name, $value and $checked represent the name,
 	 * value and the checked status of the radio button input.
 	 *
-	 * See [[renderTagAttributes()]] for details on how these are beeing rendered.
+	 * See [[renderTagAttributes()]] for details on how these are being rendered.
 	 *
 	 * @return string the generated radio button list
 	 */
@@ -1579,7 +1579,7 @@ class BaseHtml
 	{
 		if (isset($options['class'])) {
 			$classes = ' ' . $options['class'] . ' ';
-			if (($pos = strpos($classes, ' ' . $class . ' ')) === false) {
+			if (strpos($classes, ' ' . $class . ' ') === false) {
 				$options['class'] .= ' ' . $class;
 			}
 		} else {
diff --git a/framework/helpers/BaseInflector.php b/framework/helpers/BaseInflector.php
index f9f19a8..3865588 100644
--- a/framework/helpers/BaseInflector.php
+++ b/framework/helpers/BaseInflector.php
@@ -275,7 +275,18 @@ class BaseInflector
 		'Ā' => 'A', 'Č' => 'C', 'Ē' => 'E', 'Ģ' => 'G', 'Ī' => 'i', 'Ķ' => 'k', 'Ļ' => 'L', 'Ņ' => 'N',
 		'Š' => 'S', 'Ū' => 'u', 'Ž' => 'Z',
 		'ā' => 'a', 'č' => 'c', 'ē' => 'e', 'ģ' => 'g', 'ī' => 'i', 'ķ' => 'k', 'ļ' => 'l', 'ņ' => 'n',
-		'š' => 's', 'ū' => 'u', 'ž' => 'z'
+		'š' => 's', 'ū' => 'u', 'ž' => 'z',
+		//Vietnamese
+		'Ấ' => 'A', 'Ầ' => 'A', 'Ẩ' => 'A', 'Ẫ' => 'A', 'Ậ' => 'A',
+		'Ắ' => 'A', 'Ằ' => 'A', 'Ẳ' => 'A', 'Ẵ' => 'A', 'Ặ' => 'A',
+		'Ố' => 'O', 'Ồ' => 'O', 'Ổ' => 'O', 'Ỗ' => 'O', 'Ộ' => 'O',
+		'Ớ' => 'O', 'Ờ' => 'O', 'Ở' => 'O', 'Ỡ' => 'O', 'Ợ' => 'O',
+		'Ế' => 'E', 'Ề' => 'E', 'Ể' => 'E', 'Ễ' => 'E', 'Ệ' => 'E',
+		'ấ' => 'a', 'ầ' => 'a', 'ẩ' => 'a', 'ẫ' => 'a', 'ậ' => 'a',
+		'ắ' => 'a', 'ằ' => 'a', 'ẳ' => 'a', 'ẵ' => 'a', 'ặ' => 'a',
+		'ố' => 'o', 'ồ' => 'o', 'ổ' => 'o', 'ỗ' => 'o', 'ộ' => 'o',
+		'ớ' => 'o', 'ờ' => 'o', 'ở' => 'o', 'ỡ' => 'o', 'ợ' => 'o',
+		'ế' => 'e', 'ề' => 'e', 'ể' => 'e', 'ễ' => 'e', 'ệ' => 'e'
 	];
 
 	/**
diff --git a/framework/helpers/BaseMarkdown.php b/framework/helpers/BaseMarkdown.php
index a22e45e..c72e079 100644
--- a/framework/helpers/BaseMarkdown.php
+++ b/framework/helpers/BaseMarkdown.php
@@ -86,7 +86,7 @@ class BaseMarkdown
 		/** @var \cebe\markdown\Markdown $parser */
 		if (!isset(static::$flavors[$flavor])) {
 			throw new InvalidParamException("Markdown flavor '$flavor' is not defined.'");
-		} elseif(!is_object($config = static::$flavors[$flavor])) {
+		} elseif (!is_object($config = static::$flavors[$flavor])) {
 			$parser = Yii::createObject($config);
 			if (is_array($config)) {
 				foreach ($config as $name => $value) {
diff --git a/framework/helpers/BaseSecurity.php b/framework/helpers/BaseSecurity.php
index d9459d9..8750a54 100644
--- a/framework/helpers/BaseSecurity.php
+++ b/framework/helpers/BaseSecurity.php
@@ -107,10 +107,10 @@ class BaseSecurity
 	*/
 	protected static function stripPadding($data)
 	{
-		$end = StringHelper::byteSubstr($data, -1, NULL);
+		$end = StringHelper::byteSubstr($data, -1, null);
 		$last = ord($end);
 		$n = StringHelper::byteLength($data) - $last;
-		if (StringHelper::byteSubstr($data, $n, NULL) == str_repeat($end, $last)) {
+		if (StringHelper::byteSubstr($data, $n, null) == str_repeat($end, $last)) {
 			return StringHelper::byteSubstr($data, 0, $n);
 		}
 		return false;
diff --git a/framework/i18n/GettextMessageSource.php b/framework/i18n/GettextMessageSource.php
index 8da8edc..fc6d87f 100644
--- a/framework/i18n/GettextMessageSource.php
+++ b/framework/i18n/GettextMessageSource.php
@@ -70,9 +70,9 @@ class GettextMessageSource extends MessageSource
 
 			if ($messages === null && $fallbackMessages === null && $fallbackLanguage != $this->sourceLanguage) {
 				Yii::error("The message file for category '$category' does not exist: $messageFile Fallback file does not exist as well: $fallbackMessageFile", __METHOD__);
-			} else if (empty($messages)) {
+			} elseif (empty($messages)) {
 				return $fallbackMessages;
-			} else if (!empty($fallbackMessages)) {
+			} elseif (!empty($fallbackMessages)) {
 				foreach ($fallbackMessages as $key => $value) {
 					if (!empty($value) && empty($messages[$key])) {
 						$messages[$key] = $fallbackMessages[$key];
diff --git a/framework/i18n/I18N.php b/framework/i18n/I18N.php
index d0bbfcc..6be3899 100644
--- a/framework/i18n/I18N.php
+++ b/framework/i18n/I18N.php
@@ -126,7 +126,7 @@ class I18N extends Component
 		}
 
 		$p = [];
-		foreach($params as $name => $value) {
+		foreach ($params as $name => $value) {
 			$p['{' . $name . '}'] = $value;
 		}
 		return strtr($message, $p);
diff --git a/framework/i18n/MessageFormatter.php b/framework/i18n/MessageFormatter.php
index 4ea7083..c3d8c56 100644
--- a/framework/i18n/MessageFormatter.php
+++ b/framework/i18n/MessageFormatter.php
@@ -143,7 +143,7 @@ class MessageFormatter extends Component
 			return false;
 		}
 		$map = [];
-		foreach($tokens as $i => $token) {
+		foreach ($tokens as $i => $token) {
 			if (is_array($token)) {
 				$param = trim($token[0]);
 				if (!isset($map[$param])) {
@@ -169,7 +169,7 @@ class MessageFormatter extends Component
 			return false;
 		} else {
 			$values = [];
-			foreach($result as $key => $value) {
+			foreach ($result as $key => $value) {
 				$values[$map[$key]] = $value;
 			}
 			return $values;
@@ -190,7 +190,7 @@ class MessageFormatter extends Component
 		if (($tokens = self::tokenizePattern($pattern)) === false) {
 			return false;
 		}
-		foreach($tokens as $i => $token) {
+		foreach ($tokens as $i => $token) {
 			if (!is_array($token)) {
 				continue;
 			}
@@ -210,7 +210,7 @@ class MessageFormatter extends Component
 			}
 			$type = isset($token[1]) ? trim($token[1]) : 'none';
 			// replace plural and select format recursively
-			if ($type == 'plural' || $type == 'select')	{
+			if ($type == 'plural' || $type == 'select') {
 				if (!isset($token[2])) {
 					return false;
 				}
@@ -244,7 +244,7 @@ class MessageFormatter extends Component
 			$this->_errorMessage = "Message pattern is invalid.";
 			return false;
 		}
-		foreach($tokens as $i => $token) {
+		foreach ($tokens as $i => $token) {
 			if (is_array($token)) {
 				if (($tokens[$i] = $this->parseToken($token, $args, $locale)) === false) {
 					$this->_errorCode = -1;
diff --git a/framework/i18n/PhpMessageSource.php b/framework/i18n/PhpMessageSource.php
index 2e611f5..7866511 100644
--- a/framework/i18n/PhpMessageSource.php
+++ b/framework/i18n/PhpMessageSource.php
@@ -73,9 +73,9 @@ class PhpMessageSource extends MessageSource
 
 			if ($messages === null && $fallbackMessages === null && $fallbackLanguage != $this->sourceLanguage) {
 				Yii::error("The message file for category '$category' does not exist: $messageFile Fallback file does not exist as well: $fallbackMessageFile", __METHOD__);
-			} else if (empty($messages)) {
+			} elseif (empty($messages)) {
 				return $fallbackMessages;
-			} else if (!empty($fallbackMessages)) {
+			} elseif (!empty($fallbackMessages)) {
 				foreach ($fallbackMessages as $key => $value) {
 					if (!empty($value) && empty($messages[$key])) {
 						$messages[$key] = $fallbackMessages[$key];
diff --git a/framework/mail/BaseMailer.php b/framework/mail/BaseMailer.php
index 139b4af..01f6635 100644
--- a/framework/mail/BaseMailer.php
+++ b/framework/mail/BaseMailer.php
@@ -348,5 +348,4 @@ abstract class BaseMailer extends Component implements MailerInterface, ViewCont
 		$event = new MailEvent(['message' => $message, 'isSuccessful' => $isSuccessful]);
 		$this->trigger(self::EVENT_AFTER_SEND, $event);
 	}
-
 }
diff --git a/framework/messages/pt-PT/yii.php b/framework/messages/pt-PT/yii.php
index 375b4d6..2d383c0 100644
--- a/framework/messages/pt-PT/yii.php
+++ b/framework/messages/pt-PT/yii.php
@@ -1,4 +1,4 @@
-<?php
+<?php
 /**
  * Message translations.
  *
diff --git a/framework/requirements/views/web/index.php b/framework/requirements/views/web/index.php
index 287d4bb..a2aa59d 100644
--- a/framework/requirements/views/web/index.php
+++ b/framework/requirements/views/web/index.php
@@ -27,7 +27,7 @@
 		</p>
 		<p>
 		There are two kinds of requirements being checked. Mandatory requirements are those that have to be met
-		to allow Yii to work as expected. There are also some optional requirements beeing checked which will
+		to allow Yii to work as expected. There are also some optional requirements being checked which will
 		show you a warning when they do not meet. You can use Yii framework without them but some specific
 		functionality may be not available in this case.
 		</p>
diff --git a/framework/test/Fixture.php b/framework/test/Fixture.php
index 5a38ae5..e22a139 100644
--- a/framework/test/Fixture.php
+++ b/framework/test/Fixture.php
@@ -82,4 +82,3 @@ class Fixture extends Component
 	{
 	}
 }
-
diff --git a/framework/validators/ImageValidator.php b/framework/validators/ImageValidator.php
index 52fb235..fa9587d 100644
--- a/framework/validators/ImageValidator.php
+++ b/framework/validators/ImageValidator.php
@@ -124,7 +124,7 @@ class ImageValidator extends FileValidator
 		}
 		if ($this->underHeight === null) {
 			$this->underHeight = Yii::t('yii', 'The image "{file}" is too small. The height cannot be smaller than {limit, number} {limit, plural, one{pixel} other{pixels}}.');
-		}		
+		}
 		if ($this->overWidth === null) {
 			$this->overWidth = Yii::t('yii', 'The image "{file}" is too large. The width cannot be larger than {limit, number} {limit, plural, one{pixel} other{pixels}}.');
 		}
diff --git a/framework/validators/PunycodeAsset.php b/framework/validators/PunycodeAsset.php
index c0c1e2b..5f6a411 100644
--- a/framework/validators/PunycodeAsset.php
+++ b/framework/validators/PunycodeAsset.php
@@ -6,6 +6,7 @@
  */
 
 namespace yii\validators;
+
 use yii\web\AssetBundle;
 
 /**
diff --git a/framework/validators/ValidationAsset.php b/framework/validators/ValidationAsset.php
index 14d7ad0..e9bb79d 100644
--- a/framework/validators/ValidationAsset.php
+++ b/framework/validators/ValidationAsset.php
@@ -6,6 +6,7 @@
  */
 
 namespace yii\validators;
+
 use yii\web\AssetBundle;
 
 /**
diff --git a/framework/web/AssetConverter.php b/framework/web/AssetConverter.php
index 1b7d1c8..23062d9 100644
--- a/framework/web/AssetConverter.php
+++ b/framework/web/AssetConverter.php
@@ -82,7 +82,7 @@ class AssetConverter extends Component implements AssetConverterInterface
 		$proc = proc_open($command, $descriptor, $pipes, $basePath);
 		$stdout = stream_get_contents($pipes[1]);
 		$stderr = stream_get_contents($pipes[2]);
-		foreach($pipes as $pipe) {
+		foreach ($pipes as $pipe) {
 			fclose($pipe);
 		}
 		$status = proc_close($proc);
diff --git a/framework/web/Request.php b/framework/web/Request.php
index ed48401..0f9a211 100644
--- a/framework/web/Request.php
+++ b/framework/web/Request.php
@@ -828,7 +828,7 @@ class Request extends \yii\base\Request
 	}
 
 	/**
-	 * @return string the password sent via HTTP authentication, null if the username is not given
+	 * @return string the password sent via HTTP authentication, null if the password is not given
 	 */
 	public function getAuthPassword()
 	{
diff --git a/framework/web/User.php b/framework/web/User.php
index 230f2c3..c32ae9c 100644
--- a/framework/web/User.php
+++ b/framework/web/User.php
@@ -175,6 +175,7 @@ class User extends Component
 	public function setIdentity($identity)
 	{
 		$this->_identity = $identity;
+		$this->_access = [];
 	}
 
 	/**
diff --git a/framework/widgets/ActiveFormAsset.php b/framework/widgets/ActiveFormAsset.php
index 5acb5e1..94b00e5 100644
--- a/framework/widgets/ActiveFormAsset.php
+++ b/framework/widgets/ActiveFormAsset.php
@@ -6,6 +6,7 @@
  */
 
 namespace yii\widgets;
+
 use yii\web\AssetBundle;
 
 /**
diff --git a/framework/widgets/LinkPager.php b/framework/widgets/LinkPager.php
index a2c905c..22cfdf0 100644
--- a/framework/widgets/LinkPager.php
+++ b/framework/widgets/LinkPager.php
@@ -128,7 +128,7 @@ class LinkPager extends Widget
 	protected function registerLinkTags()
 	{
 		$view = $this->getView();
-		foreach($this->pagination->getLinks() as $rel => $href) {
+		foreach ($this->pagination->getLinks() as $rel => $href) {
 			$view->registerLinkTag(['rel' => $rel, 'href' => $href], $rel);
 		}
 	}
diff --git a/framework/widgets/Pjax.php b/framework/widgets/Pjax.php
index 1d7046c..5a60498 100644
--- a/framework/widgets/Pjax.php
+++ b/framework/widgets/Pjax.php
@@ -14,7 +14,7 @@ use yii\helpers\Json;
 use yii\web\Response;
 
 /**
- * Pjax is a widget integrating the [pjax](https://github.com/defunkt/jquery-pjax) jQuery plugin.
+ * Pjax is a widget integrating the [pjax](https://github.com/yiisoft/jquery-pjax) jQuery plugin.
  *
  * Pjax only deals with the content enclosed between its [[begin()]] and [[end()]] calls, called the *body content* of the widget.
  * By default, any link click or form submission (for those forms with `data-pjax` attribute) within the body content
@@ -25,7 +25,9 @@ use yii\web\Response;
  * You may configure [[linkSelector]] to specify which links should trigger pjax, and configure [[formSelector]]
  * to specify which form submission may trigger pjax.
  *
- * The following example shows how to use Pjax with the [[\yii\gridview\GridView]] widget so that the grid pagination,
+ * You may disable pjax for a specific link inside the container by adding `data-pjax="0"` attribute to this link.
+ *
+ * The following example shows how to use Pjax with the [[\yii\grid\GridView]] widget so that the grid pagination,
  * sorting and filtering can be done via pjax:
  *
  * ```php
@@ -78,7 +80,7 @@ class Pjax extends Widget
 	public $scrollTo = false;
 	/**
 	 * @var array additional options to be passed to the pjax JS plugin. Please refer to
-	 * [pjax project page](https://github.com/defunkt/jquery-pjax) for available options.
+	 * [pjax project page](https://github.com/yiisoft/jquery-pjax) for available options.
 	 */
 	public $clientOptions;
 
diff --git a/framework/widgets/PjaxAsset.php b/framework/widgets/PjaxAsset.php
index f3e4912..3fcaf67 100644
--- a/framework/widgets/PjaxAsset.php
+++ b/framework/widgets/PjaxAsset.php
@@ -17,9 +17,9 @@ use yii\web\AssetBundle;
  */
 class PjaxAsset extends AssetBundle
 {
-	public $sourcePath = '@yii/assets';
+	public $sourcePath = '@vendor/yiisoft/jquery-pjax';
 	public $js = [
-		'pjax/jquery.pjax.js',
+		'jquery.pjax.js',
 	];
 	public $depends = [
 		'yii\web\YiiAsset',
diff --git a/tests/unit/data/travis/cubrid-setup.sh b/tests/unit/data/travis/cubrid-setup.sh
index 9c3bb74..4188e17 100755
--- a/tests/unit/data/travis/cubrid-setup.sh
+++ b/tests/unit/data/travis/cubrid-setup.sh
@@ -2,6 +2,11 @@
 #
 # install CUBRID DBMS
 
+if (php --version | grep -i HHVM > /dev/null); then
+    echo "Skipping CUBRID on HHVM"
+    exit 0
+fi
+
 # cubrid dbms
 echo 'yes' | sudo add-apt-repository ppa:cubrid/cubrid
 sudo apt-get update
diff --git a/tests/unit/data/travis/memcache-setup.sh b/tests/unit/data/travis/memcache-setup.sh
index 6b623d6..adb743b 100755
--- a/tests/unit/data/travis/memcache-setup.sh
+++ b/tests/unit/data/travis/memcache-setup.sh
@@ -1,4 +1,8 @@
 #!/bin/sh
 
-echo "extension=memcache.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
-echo "extension=memcached.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
+if (php --version | grep -i HHVM > /dev/null); then
+  echo "skipping memcache on HHVM"
+else
+  echo "extension=memcache.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
+  echo "extension=memcached.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
+fi
diff --git a/tests/unit/extensions/mongodb/CollectionTest.php b/tests/unit/extensions/mongodb/CollectionTest.php
index 3eb97b6..9a0c0b4 100644
--- a/tests/unit/extensions/mongodb/CollectionTest.php
+++ b/tests/unit/extensions/mongodb/CollectionTest.php
@@ -187,6 +187,60 @@ class CollectionTest extends MongoDbTestCase
 		$this->assertNotEmpty($result[0]['items']);
 	}
 
+	public function testFindAndModify()
+	{
+		$collection = $this->getConnection()->getCollection('customer');
+		$rows = [
+			[
+				'name' => 'customer 1',
+				'status' => 1,
+				'amount' => 100,
+			],
+			[
+				'name' => 'customer 2',
+				'status' => 1,
+				'amount' => 200,
+			],
+		];
+		$collection->batchInsert($rows);
+
+		// increment field
+		$result = $collection->findAndModify(['name' => 'customer 1'], ['$inc' => ['status' => 1]]);
+		$this->assertEquals('customer 1', $result['name']);
+		$this->assertEquals(1, $result['status']);
+		$newResult = $collection->findOne(['name' => 'customer 1']);
+		$this->assertEquals(2, $newResult['status']);
+
+		// $set and return modified document
+		$result = $collection->findAndModify(
+			['name' => 'customer 2'],
+			['$set' => ['status' => 2]],
+			[],
+			['new' => true]
+		);
+		$this->assertEquals('customer 2', $result['name']);
+		$this->assertEquals(2, $result['status']);
+
+		// Full update document
+		$data = [
+			'name' => 'customer 3',
+			'city' => 'Minsk'
+		];
+		$result = $collection->findAndModify(
+			['name' => 'customer 2'],
+			$data,
+			[],
+			['new' => true]
+		);
+		$this->assertEquals('customer 3', $result['name']);
+		$this->assertEquals('Minsk', $result['city']);
+		$this->assertTrue(!isset($result['status']));
+
+		// Test exceptions
+		$this->setExpectedException('\yii\mongodb\Exception');
+		$collection->findAndModify(['name' => 'customer 1'], ['$wrongOperator' => ['status' => 1]]);
+	}
+
 	/**
 	 * @depends testBatchInsert
 	 */
@@ -240,54 +294,54 @@ class CollectionTest extends MongoDbTestCase
 		$this->assertEquals($expectedRows, $rows);
 	}
 
-    /**
-     * @depends testMapReduce
-     */
-    public function testMapReduceInline()
-    {
-        $collection = $this->getConnection()->getCollection('customer');
-        $rows = [
-            [
-                'name' => 'customer 1',
-                'status' => 1,
-                'amount' => 100,
-            ],
-            [
-                'name' => 'customer 2',
-                'status' => 1,
-                'amount' => 200,
-            ],
-            [
-                'name' => 'customer 2',
-                'status' => 2,
-                'amount' => 400,
-            ],
-            [
-                'name' => 'customer 2',
-                'status' => 3,
-                'amount' => 500,
-            ],
-        ];
-        $collection->batchInsert($rows);
-
-        $result = $collection->mapReduce(
-            'function () {emit(this.status, this.amount)}',
-            'function (key, values) {return Array.sum(values)}',
-            ['inline' => true],
-            ['status' => ['$lt' => 3]]
-        );
-        $expectedRows = [
-            [
-                '_id' => 1,
-                'value' => 300,
-            ],
-            [
-                '_id' => 2,
-                'value' => 400,
-            ],
-        ];
-        $this->assertEquals($expectedRows, $result);
-    }
+	/**
+	 * @depends testMapReduce
+	 */
+	public function testMapReduceInline()
+	{
+		$collection = $this->getConnection()->getCollection('customer');
+		$rows = [
+			[
+				'name' => 'customer 1',
+				'status' => 1,
+				'amount' => 100,
+			],
+			[
+				'name' => 'customer 2',
+				'status' => 1,
+				'amount' => 200,
+			],
+			[
+				'name' => 'customer 2',
+				'status' => 2,
+				'amount' => 400,
+			],
+			[
+				'name' => 'customer 2',
+				'status' => 3,
+				'amount' => 500,
+			],
+		];
+		$collection->batchInsert($rows);
+
+		$result = $collection->mapReduce(
+			'function () {emit(this.status, this.amount)}',
+			'function (key, values) {return Array.sum(values)}',
+			['inline' => true],
+			['status' => ['$lt' => 3]]
+		);
+		$expectedRows = [
+			[
+				'_id' => 1,
+				'value' => 300,
+			],
+			[
+				'_id' => 2,
+				'value' => 400,
+			],
+		];
+		$this->assertEquals($expectedRows, $result);
+	}
 
 	public function testCreateIndex()
 	{
diff --git a/tests/unit/framework/base/ExceptionTest.php b/tests/unit/framework/base/ExceptionTest.php
index 635b55c..136fc28 100644
--- a/tests/unit/framework/base/ExceptionTest.php
+++ b/tests/unit/framework/base/ExceptionTest.php
@@ -15,7 +15,7 @@ class ExceptionTest extends TestCase
 		$this->assertEquals('bar', $array['message']);
 		$this->assertEquals('foo', $array['previous']['message']);
 		
-		$e = new InvalidCallException('bar', 0 ,new UserException('foo'));
+		$e = new InvalidCallException('bar', 0, new UserException('foo'));
 		$array = $e->toArray();
 		$this->assertEquals('bar', $array['message']);
 		$this->assertEquals('foo', $array['previous']['message']);
diff --git a/tests/unit/framework/rbac/ManagerTestCase.php b/tests/unit/framework/rbac/ManagerTestCase.php
index 6d80287..51c195e 100644
--- a/tests/unit/framework/rbac/ManagerTestCase.php
+++ b/tests/unit/framework/rbac/ManagerTestCase.php
@@ -173,7 +173,7 @@ abstract class ManagerTestCase extends TestCase
 		$this->assertTrue($this->auth->executeBizRule(null, [], null));
 		$this->assertTrue($this->auth->executeBizRule('return 1 == true;', [], null));
 		$this->assertTrue($this->auth->executeBizRule('return $params[0] == $params[1];', [1, '1'], null));
-		if (defined('HHVM_VERSION')) { // invalid code crashes on HHVM
+		if (!defined('HHVM_VERSION')) { // invalid code crashes on HHVM
 			$this->assertFalse($this->auth->executeBizRule('invalid;', [], null));
 		}
 	}