Commit 8f81e231 by Alexander Makarov

Fixes #4453: `yii message/extract` wasn't properly writing to po files in case…

Fixes #4453: `yii message/extract` wasn't properly writing to po files in case of multiple categories
parent ed533172
......@@ -72,6 +72,7 @@ Yii Framework 2 Change Log
- Bug #4409: Upper case letters in subdirectory prefixes of controller IDs were not properly handled (qiangxue)
- Bug #4412: Formatter used SI Prefixes for base 1024, now uses binary prefixes (kmindi)
- Bug #4427: Formatter could do one division too much (kmindi)
- Bug #4453: `yii message/extract` wasn't properly writing to po files in case of multiple categories (samdark)
- Bug: Fixed inconsistent return of `\yii\console\Application::runAction()` (samdark)
- Bug: URL encoding for the route parameter added to `\yii\web\UrlManager` (klimov-paul)
- Bug: Fixed the bug that requesting protected or private action methods would cause 500 error instead of 404 (qiangxue)
......
......@@ -209,11 +209,11 @@ class MessageController extends Controller
}
}
echo $savedFlag ? "saved.\n" : "nothing new...skipped.\n";
echo $savedFlag ? "saved.\n" : "Nothing new...skipped.\n";
echo $removeUnused ? "Deleting obsoleted messages..." : "Updating obsoleted messages...";
if (empty($obsolete)) {
echo "nothing obsoleted...skipped.\n";
echo "Nothing obsoleted...skipped.\n";
} else {
if ($removeUnused) {
$db->createCommand()
......@@ -286,12 +286,10 @@ class MessageController extends Controller
foreach ($messages as $category => $msgs) {
$file = str_replace("\\", '/', "$dirName/$category.php");
$path = dirname($file);
if (!is_dir($path)) {
mkdir($path, 0755, true);
}
FileHelper::createDirectory($path);
$msgs = array_values(array_unique($msgs));
echo "Saving messages to $file...\n";
$this->saveMessagesCategoryToPHP($msgs, $file, $overwrite, $removeUnused, $sort);
$this->saveMessagesCategoryToPHP($msgs, $file, $overwrite, $removeUnused, $sort, $category);
}
}
......@@ -303,23 +301,23 @@ class MessageController extends Controller
* @param boolean $overwrite if existing file should be overwritten without backup
* @param boolean $removeUnused if obsolete translations should be removed
* @param boolean $sort if translations should be sorted
* @param string $category message category
*/
protected function saveMessagesCategoryToPHP($messages, $fileName, $overwrite, $removeUnused, $sort)
protected function saveMessagesCategoryToPHP($messages, $fileName, $overwrite, $removeUnused, $sort, $category)
{
if (is_file($fileName)) {
$translated = require($fileName);
$existingMessages = require($fileName);
sort($messages);
ksort($translated);
if (array_keys($translated) == $messages) {
echo "nothing new...skipped.\n";
return self::EXIT_CODE_NORMAL;
ksort($existingMessages);
if (array_keys($existingMessages) == $messages) {
echo "Nothing new in \"$category\" category... Nothing to save.\n";
return;
}
$merged = [];
$untranslated = [];
foreach ($messages as $message) {
if (array_key_exists($message, $translated) && strlen($translated[$message]) > 0) {
$merged[$message] = $translated[$message];
if (array_key_exists($message, $existingMessages) && strlen($existingMessages[$message]) > 0) {
$merged[$message] = $existingMessages[$message];
} else {
$untranslated[] = $message;
}
......@@ -330,10 +328,10 @@ class MessageController extends Controller
foreach ($untranslated as $message) {
$todo[$message] = '';
}
ksort($translated);
foreach ($translated as $message => $translation) {
ksort($existingMessages);
foreach ($existingMessages as $message => $translation) {
if (!isset($merged[$message]) && !isset($todo[$message]) && !$removeUnused) {
if (substr_compare($translation, '@@', 0, 2) === 0 && substr_compare($translation, '@@', -2) === 0) {
if (mb_strlen($translation, Yii::$app->charset) >= 2 && substr_compare($translation, '@@', 0, 2) === 0 && substr_compare($translation, '@@', -2) === 0) {
$todo[$message] = $translation;
} else {
$todo[$message] = '@@' . $translation . '@@';
......@@ -355,7 +353,6 @@ class MessageController extends Controller
}
ksort($merged);
}
echo "Saved.\n";
$array = VarDumper::export($merged);
......@@ -383,6 +380,7 @@ return $array;
EOD;
file_put_contents($fileName, $content);
echo "Saved.\n";
}
/**
......@@ -398,10 +396,7 @@ EOD;
protected function saveMessagesToPO($messages, $dirName, $overwrite, $removeUnused, $sort, $catalog)
{
$file = str_replace("\\", '/', "$dirName/$catalog.po");
$path = dirname($file);
if (!is_dir($path)) {
mkdir($path, 0755, true);
}
FileHelper::createDirectory(dirname($file));
echo "Saving messages to $file...\n";
$poFile = new GettextPoFile();
......@@ -411,6 +406,7 @@ EOD;
$notTranslatedYet = [];
$todos = [];
$hasSomethingToWrite = false;
foreach ($messages as $category => $msgs) {
$msgs = array_values(array_unique($msgs));
......@@ -420,8 +416,14 @@ EOD;
sort($msgs);
ksort($existingMessages);
if (array_keys($existingMessages) == $msgs) {
echo "Nothing new... skipped.\n";
return self::EXIT_CODE_NORMAL;
echo "Nothing new in \"$category\" category...\n";
sort($msgs);
foreach ($msgs as $message) {
$merged[$category . chr(4) . $message] = '';
}
ksort($merged);
continue;
}
// merge existing message translations with new message translations
......@@ -443,7 +445,7 @@ EOD;
// add obsolete unused messages
foreach ($existingMessages as $message => $translation) {
if (!isset($merged[$category . chr(4) . $message]) && !isset($todos[$category . chr(4) . $message]) && !$removeUnused) {
if (substr($translation, 0, 2) === '@@' && substr($translation, -2) === '@@') {
if (mb_strlen($translation, Yii::$app->charset) >= 2 && substr($translation, 0, 2) === '@@' && substr($translation, -2) === '@@') {
$todos[$category . chr(4) . $message] = $translation;
} else {
$todos[$category . chr(4) . $message] = '@@' . $translation . '@@';
......@@ -459,8 +461,6 @@ EOD;
if ($overwrite === false) {
$file .= '.merged';
}
echo "Translation merged.\n";
} else {
sort($msgs);
foreach ($msgs as $message) {
......@@ -468,8 +468,14 @@ EOD;
}
ksort($merged);
}
echo "Category \"$category\" merged.\n";
$hasSomethingToWrite = true;
}
if ($hasSomethingToWrite) {
$poFile->save($file, $merged);
echo "Saved.\n";
} else {
echo "Nothing to save.\n";
}
$poFile->save($file, $merged);
echo "Saved.\n";
}
}
......@@ -15,8 +15,6 @@ return [
// with the existing ones. Defaults to false, which means the new (untranslated)
// messages will be separated from the old (translated) ones.
'sort' => false,
// boolean, whether the message file should be overwritten with the merged messages
'overwrite' => true,
// boolean, whether to remove messages that no longer appear in the source code.
// Defaults to false, which means each of these messages will be enclosed with a pair of '@@' marks.
'removeUnused' => false,
......@@ -47,6 +45,8 @@ return [
'format' => 'php',
// Root directory containing message translations.
'messagePath' => __DIR__ . DIRECTORY_SEPARATOR . 'messages',
// boolean, whether the message file should be overwritten with the merged messages
'overwrite' => true,
/*
......@@ -67,5 +67,7 @@ return [
'messagePath' => __DIR__ . DIRECTORY_SEPARATOR . 'messages',
// Name of the file that will be used for translations.
'catalog' => 'messages',
// boolean, whether the message file should be overwritten with the merged messages
'overwrite' => true,
*/
];
<?php
namespace yiiunit\framework\console\controllers;
use Yii;
use yii\helpers\FileHelper;
use yii\helpers\VarDumper;
use yiiunit\TestCase;
use yii\console\controllers\MessageController;
/**
* Base for [[\yii\console\controllers\MessageController]] unit tests.
* @see MessageController
*/
abstract class BaseMessageControllerTest extends TestCase
{
protected $sourcePath = '';
protected $configFileName = '';
protected $language = 'en';
public function setUp()
{
$this->mockApplication();
$this->sourcePath = Yii::getAlias('@yiiunit/runtime/test_source');
FileHelper::createDirectory($this->sourcePath, 0777);
if (!file_exists($this->sourcePath)) {
$this->markTestIncomplete('Unit tests runtime directory should have writable permissions!');
}
$this->configFileName = Yii::getAlias('@yiiunit/runtime') . DIRECTORY_SEPARATOR . 'message_controller_test_config.php';
}
public function tearDown()
{
FileHelper::removeDirectory($this->sourcePath);
if (file_exists($this->configFileName)) {
unlink($this->configFileName);
}
}
/**
* Creates test message controller instance.
* @return MessageController message command instance.
*/
protected function createMessageController()
{
$module = $this->getMock('yii\\base\\Module', ['fake'], ['console']);
$messageController = new MessageController('message', $module);
$messageController->interactive = false;
return $messageController;
}
/**
* Emulates running of the message controller action.
* @param string $actionId id of action to be run.
* @param array $args action arguments.
* @return string command output.
*/
protected function runMessageControllerAction($actionId, array $args = [])
{
$controller = $this->createMessageController();
ob_start();
ob_implicit_flush(false);
$controller->run($actionId, $args);
return ob_get_clean();
}
/**
* Creates message command config file named as [[configFileName]].
* @param array $config message command config.
*/
protected function saveConfigFile(array $config)
{
if (file_exists($this->configFileName)) {
unlink($this->configFileName);
}
$fileContent = '<?php return ' . VarDumper::export($config) . ';';
file_put_contents($this->configFileName, $fileContent);
}
/**
* Creates source file with given content
* @param string $content file content
* @return string path to source file
*/
protected function createSourceFile($content)
{
$fileName = $this->sourcePath . DIRECTORY_SEPARATOR . md5(uniqid()) . '.php';
file_put_contents($fileName, $content);
return $fileName;
}
/**
* Saves messages
*
* @param array $messages
* @param string $category
*/
abstract protected function saveMessages($messages, $category);
/**
* Loads messages
*
* @param string $category
* @return array
*/
abstract protected function loadMessages($category);
/**
* @return array default config
*/
abstract protected function getDefaultConfig();
/**
* Returns config
*
* @param array $additionalConfig
* @return array
*/
protected function getConfig($additionalConfig = [])
{
return array_merge($this->getDefaultConfig(), $additionalConfig);
}
// Tests:
public function testActionConfig()
{
$configFileName = $this->configFileName;
$out = $this->runMessageControllerAction('config', [$configFileName]);
$this->assertTrue(file_exists($configFileName), "Unable to create config file from template. Command output:\n\n" . $out);
}
public function testConfigFileNotExist()
{
$this->setExpectedException('yii\\console\\Exception');
$this->runMessageControllerAction('extract', ['not_existing_file.php']);
}
public function testCreateTranslation()
{
$category = 'test_category1';
$message = 'test message';
$sourceFileContent = "Yii::t('{$category}', '{$message}');";
$this->createSourceFile($sourceFileContent);
$this->saveConfigFile($this->getConfig());
$out = $this->runMessageControllerAction('extract', [$this->configFileName]);
$messages = $this->loadMessages($category);
$this->assertArrayHasKey($message, $messages, "\"$message\" is missing in translation file. Command output:\n\n" . $out);
}
/**
* @depends testCreateTranslation
*/
public function testNothingToSave()
{
$category = 'test_category2';
$message = 'test message';
$sourceFileContent = "Yii::t('{$category}', '{$message}')";
$this->createSourceFile($sourceFileContent);
$this->saveConfigFile($this->getConfig());
$out = $this->runMessageControllerAction('extract', [$this->configFileName]);
$out .= $this->runMessageControllerAction('extract', [$this->configFileName]);
$this->assertTrue(strpos($out, 'Nothing to save') !== false, "Controller should respond with \"Nothing to save\" if there's nothing to update. Command output:\n\n" . $out);
}
/**
* @depends testCreateTranslation
*/
public function testMerge()
{
$category = 'test_category3';
$existingMessage = 'test existing message';
$existingMessageTranslation = 'test existing message translation';
$this->saveMessages(
[$existingMessage => $existingMessageTranslation],
$category
);
$newMessage = 'test new message';
$sourceFileContent = "Yii::t('{$category}', '{$existingMessage}');";
$sourceFileContent .= "Yii::t('{$category}', '{$newMessage}');";
$this->createSourceFile($sourceFileContent);
$this->saveConfigFile($this->getConfig());
$out = $this->runMessageControllerAction('extract', [$this->configFileName]);
$messages = $this->loadMessages($category);
$this->assertArrayHasKey($newMessage, $messages, "Unable to add new message: \"$newMessage\". Command output:\n\n" . $out);
$this->assertArrayHasKey($existingMessage, $messages, "Unable to keep existing message: \"$existingMessage\". Command output:\n\n" . $out);
$this->assertEquals('', $messages[$newMessage], "Wrong new message content. Command output:\n\n" . $out);
$this->assertEquals($existingMessageTranslation, $messages[$existingMessage], "Unable to keep existing message content. Command output:\n\n" . $out);
}
/**
* @depends testMerge
*/
public function testMarkObosoleteMessages()
{
$category = 'category';
$obsoleteMessage = 'obsolete message';
$obsoleteTranslation = 'obsolete translation';
$this->saveMessages([$obsoleteMessage => $obsoleteTranslation], $category);
$sourceFileContent = "Yii::t('{$category}', 'any new message');";
$this->createSourceFile($sourceFileContent);
$this->saveConfigFile($this->getConfig(['removeUnused' => false]));
$out = $this->runMessageControllerAction('extract', [$this->configFileName]);
$messages = $this->loadMessages($category);
$this->assertArrayHasKey($obsoleteMessage, $messages, "Obsolete message should not be removed. Command output:\n\n" . $out);
$this->assertEquals('@@' . $obsoleteTranslation . '@@', $messages[$obsoleteMessage], "Obsolete message was not marked properly. Command output:\n\n" . $out);
}
/**
* @depends testMerge
*/
public function removeObosoleteMessages()
{
$category = 'category';
$obsoleteMessage = 'obsolete message';
$obsoleteTranslation = 'obsolete translation';
$this->saveMessages([$obsoleteMessage => $obsoleteTranslation], $category);
$sourceFileContent = "Yii::t('{$category}', 'any new message');";
$this->createSourceFile($sourceFileContent);
$this->saveConfigFile($this->getConfig(['removeUnused' => true]));
$out = $this->runMessageControllerAction('extract', [$this->configFileName]);
$messages = $this->loadMessages($category);
$this->assertArrayHasKey($obsoleteMessage, $messages, "Obsolete message should be removed. Command output:\n\n" . $out);
}
/**
* @depends testMerge
*/
public function testMergeWithContentZero()
{
$category = 'test_category5';
$zeroMessage = 'test zero message';
$zeroMessageContent = '0';
$falseMessage = 'test false message';
$falseMessageContent = 'false';
$this->saveMessages([
$zeroMessage => $zeroMessageContent,
$falseMessage => $falseMessageContent,
], $category);
$newMessage = 'test new message';
$sourceFileContent = "Yii::t('{$category}', '{$zeroMessage}')";
$sourceFileContent .= "Yii::t('{$category}', '{$falseMessage}')";
$sourceFileContent .= "Yii::t('{$category}', '{$newMessage}')";
$this->createSourceFile($sourceFileContent);
$this->saveConfigFile($this->getConfig());
$out = $this->runMessageControllerAction('extract', [$this->configFileName]);
$messages = $this->loadMessages($category);
$this->assertTrue($zeroMessageContent === $messages[$zeroMessage], "Message content \"0\" is lost. Command output:\n\n" . $out);
$this->assertTrue($falseMessageContent === $messages[$falseMessage], "Message content \"false\" is lost. Command output:\n\n" . $out);
}
/**
* @depends testCreateTranslation
*/
public function testMultipleTranslators()
{
$category = 'test_category6';
$translators = [
'Yii::t',
'Custom::translate',
];
$sourceMessages = [
'first message',
'second message',
];
$sourceFileContent = '';
foreach ($sourceMessages as $key => $message) {
$sourceFileContent .= $translators[$key] . "('{$category}', '{$message}');\n";
}
$this->createSourceFile($sourceFileContent);
$this->saveConfigFile($this->getConfig(['translator' => $translators]));
$this->runMessageControllerAction('extract', [$this->configFileName]);
$messages = $this->loadMessages($category);
foreach ($sourceMessages as $sourceMessage) {
$this->assertArrayHasKey($sourceMessage, $messages);
}
}
/**
* @depends testCreateTranslation
*/
public function testMultipleCategories()
{
$category1 = 'category1';
$category2 = 'category2';
$message1 = 'message1';
$message2 = 'message2';
$message3 = 'message3';
$this->saveConfigFile($this->getConfig(['removeUnused' => true]));
// Generate initial translation
$sourceFileContent = "Yii::t('{$category1}', '{$message1}'); Yii::t('{$category2}', '{$message2}');";
$source = $this->createSourceFile($sourceFileContent);
$out = $this->runMessageControllerAction('extract', [$this->configFileName]);
unlink($source);
$messages1 = $this->loadMessages($category1);
$messages2 = $this->loadMessages($category2);
$this->assertArrayHasKey($message1, $messages1, "message1 not found in category1. Command output:\n\n" . $out);
$this->assertArrayHasKey($message2, $messages2, "message2 not found in category2. Command output:\n\n" . $out);
$this->assertArrayNotHasKey($message3, $messages2, "message3 found in category2. Command output:\n\n" . $out);
// Change source code, run translation again
$sourceFileContent = "Yii::t('{$category1}', '{$message1}'); Yii::t('{$category2}', '{$message3}');";
$source = $this->createSourceFile($sourceFileContent);
$out .= "\n" . $this->runMessageControllerAction('extract', [$this->configFileName]);
unlink($source);
$messages1 = $this->loadMessages($category1);
$messages2 = $this->loadMessages($category2);
$this->assertArrayHasKey($message1, $messages1, "message1 not found in category1. Command output:\n\n" . $out);
$this->assertArrayHasKey($message3, $messages2, "message3 not found in category2. Command output:\n\n" . $out);
$this->assertArrayNotHasKey($message2, $messages2, "message2 found in category2. Command output:\n\n" . $out);
}
}
<?php
use yiiunit\TestCase;
use yii\console\controllers\MessageController;
/**
* Unit test for [[\yii\console\controllers\MessageController]].
* @see MessageController
*
* @group console
*/
class MessageControllerTest extends TestCase
{
protected $sourcePath = '';
protected $messagePath = '';
protected $configFileName = '';
public function setUp()
{
$this->mockApplication();
$this->sourcePath = Yii::getAlias('@yiiunit/runtime/test_source');
$this->createDir($this->sourcePath);
if (!file_exists($this->sourcePath)) {
$this->markTestIncomplete('Unit tests runtime directory should have writable permissions!');
}
$this->messagePath = Yii::getAlias('@yiiunit/runtime/test_messages');
$this->createDir($this->messagePath);
$this->configFileName = Yii::getAlias('@yiiunit/runtime') . DIRECTORY_SEPARATOR . 'message_controller_test_config.php';
}
public function tearDown()
{
$this->removeDir($this->sourcePath);
$this->removeDir($this->messagePath);
if (file_exists($this->configFileName)) {
unlink($this->configFileName);
}
}
/**
* Creates directory.
* @param $dirName directory full name
*/
protected function createDir($dirName)
{
if (!file_exists($dirName)) {
mkdir($dirName, 0777, true);
}
}
/**
* Removes directory.
* @param $dirName directory full name
*/
protected function removeDir($dirName)
{
if (!empty($dirName) && file_exists($dirName)) {
$this->removeFileSystemObject($dirName);
}
}
/**
* Removes file system object: directory or file.
* @param string $fileSystemObjectFullName file system object full name.
*/
protected function removeFileSystemObject($fileSystemObjectFullName)
{
if (!is_dir($fileSystemObjectFullName)) {
unlink($fileSystemObjectFullName);
} else {
$dirHandle = opendir($fileSystemObjectFullName);
while (($fileSystemObjectName = readdir($dirHandle)) !== false) {
if ($fileSystemObjectName === '.' || $fileSystemObjectName === '..') {
continue;
}
$this->removeFileSystemObject($fileSystemObjectFullName . DIRECTORY_SEPARATOR . $fileSystemObjectName);
}
closedir($dirHandle);
rmdir($fileSystemObjectFullName);
}
}
/**
* Creates test message controller instance.
* @return MessageController message command instance.
*/
protected function createMessageController()
{
$module = $this->getMock('yii\\base\\Module', ['fake'], ['console']);
$messageController = new MessageController('message', $module);
$messageController->interactive = false;
return $messageController;
}
/**
* Emulates running of the message controller action.
* @param string $actionId id of action to be run.
* @param array $args action arguments.
* @return string command output.
*/
protected function runMessageControllerAction($actionId, array $args = [])
{
$controller = $this->createMessageController();
ob_start();
ob_implicit_flush(false);
$controller->run($actionId, $args);
return ob_get_clean();
}
/**
* Creates message command config file named as [[configFileName]].
* @param array $config message command config.
*/
protected function composeConfigFile(array $config)
{
if (file_exists($this->configFileName)) {
unlink($this->configFileName);
}
$fileContent = '<?php return ' . var_export($config, true) . ';';
file_put_contents($this->configFileName, $fileContent);
}
/**
* Creates source file with given content
* @param string $content file content
* @param string|null $name file self name
*/
protected function createSourceFile($content, $name = null)
{
if (empty($name)) {
$name = md5(uniqid()) . '.php';
}
file_put_contents($this->sourcePath . DIRECTORY_SEPARATOR . $name, $content);
}
/**
* Creates message file with given messages.
* @param string $name file name
* @param array $messages messages.
*/
protected function createMessageFile($name, array $messages = [])
{
$fileName = $this->messagePath . DIRECTORY_SEPARATOR . $name;
if (file_exists($fileName)) {
unlink($fileName);
} else {
$dirName = dirname($fileName);
if (!file_exists($dirName)) {
mkdir($dirName, 0777, true);
}
}
$fileContent = '<?php return ' . var_export($messages, true) . ';';
file_put_contents($fileName, $fileContent);
}
// Tests:
public function testActionConfig()
{
$configFileName = $this->configFileName;
$this->runMessageControllerAction('config', [$configFileName]);
$this->assertTrue(file_exists($configFileName), 'Unable to create config file template!');
}
public function testConfigFileNotExist()
{
$this->setExpectedException('yii\\console\\Exception');
$this->runMessageControllerAction('extract', ['not_existing_file.php']);
}
public function testCreateTranslation()
{
$language = 'en';
$category = 'test_category1';
$message = 'test message';
$sourceFileContent = "Yii::t('{$category}', '{$message}')";
$this->createSourceFile($sourceFileContent);
$this->composeConfigFile([
'languages' => [$language],
'sourcePath' => $this->sourcePath,
'messagePath' => $this->messagePath,
]);
$this->runMessageControllerAction('extract', [$this->configFileName]);
$this->assertTrue(file_exists($this->messagePath . DIRECTORY_SEPARATOR . $language), 'No language dir created!');
$messageFileName = $this->messagePath . DIRECTORY_SEPARATOR . $language . DIRECTORY_SEPARATOR . $category . '.php';
$this->assertTrue(file_exists($messageFileName), 'No message file created!');
$messages = require($messageFileName);
$this->assertTrue(is_array($messages), 'Unable to compose messages!');
$this->assertTrue(array_key_exists($message, $messages), 'Source message is missing!');
}
/**
* @depends testCreateTranslation
*/
public function testNothingNew()
{
$language = 'en';
$category = 'test_category2';
$message = 'test message';
$sourceFileContent = "Yii::t('{$category}', '{$message}')";
$this->createSourceFile($sourceFileContent);
$this->composeConfigFile([
'languages' => [$language],
'sourcePath' => $this->sourcePath,
'messagePath' => $this->messagePath,
]);
$this->runMessageControllerAction('extract', [$this->configFileName]);
$messageFileName = $this->messagePath . DIRECTORY_SEPARATOR . $language . DIRECTORY_SEPARATOR . $category . '.php';
// check file not overwritten:
$messageFileContent = file_get_contents($messageFileName);
$messageFileContent .= '// some not generated by command content';
file_put_contents($messageFileName, $messageFileContent);
$this->runMessageControllerAction('extract', [$this->configFileName]);
$this->assertEquals($messageFileContent, file_get_contents($messageFileName));
}
/**
* @depends testCreateTranslation
*/
public function testMerge()
{
if (defined('HHVM_VERSION')) {
$this->markTestSkipped('Can not test on HHVM because modified files can not be reloaded.');
}
$language = 'en';
$category = 'test_category3';
$messageFileName = $language . DIRECTORY_SEPARATOR . $category . '.php';
$existingMessage = 'test existing message';
$existingMessageContent = 'test existing message content';
$this->createMessageFile($messageFileName, [
$existingMessage => $existingMessageContent
]);
$newMessage = 'test new message';
$sourceFileContent = "Yii::t('{$category}', '{$existingMessage}')";
$sourceFileContent .= "Yii::t('{$category}', '{$newMessage}')";
$this->createSourceFile($sourceFileContent);
$this->composeConfigFile([
'languages' => [$language],
'sourcePath' => $this->sourcePath,
'messagePath' => $this->messagePath,
'overwrite' => true,
]);
$commandOutput = $this->runMessageControllerAction('extract', [$this->configFileName]);
$messages = require($this->messagePath . DIRECTORY_SEPARATOR . $messageFileName);
$this->assertTrue(array_key_exists($newMessage, $messages), 'Unable to add new message: "' . $newMessage . '". Command output was:' . "\n" . $commandOutput);
$this->assertTrue(array_key_exists($existingMessage, $messages), 'Unable to keep existing message: "' . $existingMessage . '". Command output was:' . "\n" . $commandOutput);
$this->assertEquals('', $messages[$newMessage], 'Wrong new message content!. Command output was:\n' . $commandOutput);
$this->assertEquals($existingMessageContent, $messages[$existingMessage], 'Unable to keep existing message content!. Command output was:' . "\n" . $commandOutput);
}
/**
* @depends testMerge
*/
public function testNoLongerNeedTranslation()
{
if (defined('HHVM_VERSION')) {
$this->markTestSkipped('Can not test on HHVM because modified files can not be reloaded.');
}
$language = 'en';
$category = 'test_category4';
$messageFileName = $language . DIRECTORY_SEPARATOR . $category . '.php';
$oldMessage = 'test old message';
$oldMessageContent = 'test old message content';
$this->createMessageFile($messageFileName, [
$oldMessage => $oldMessageContent
]);
$sourceFileContent = "Yii::t('{$category}', 'some new message')";
$this->createSourceFile($sourceFileContent);
$this->composeConfigFile([
'languages' => [$language],
'sourcePath' => $this->sourcePath,
'messagePath' => $this->messagePath,
'overwrite' => true,
'removeUnused' => false,
]);
$this->runMessageControllerAction('extract', [$this->configFileName]);
$messages = require($this->messagePath . DIRECTORY_SEPARATOR . $messageFileName);
$this->assertTrue(array_key_exists($oldMessage, $messages), 'No longer needed message removed!');
$this->assertEquals('@@' . $oldMessageContent . '@@', $messages[$oldMessage], 'No longer needed message content does not marked properly!');
}
/**
* @depends testMerge
*/
public function testMergeWithContentZero()
{
if (defined('HHVM_VERSION')) {
$this->markTestSkipped('Can not test on HHVM because modified files can not be reloaded.');
}
$language = 'en';
$category = 'test_category5';
$messageFileName = $language . DIRECTORY_SEPARATOR . $category . '.php';
$zeroMessage = 'test zero message';
$zeroMessageContent = '0';
$falseMessage = 'test false message';
$falseMessageContent = 'false';
$this->createMessageFile($messageFileName, [
$zeroMessage => $zeroMessageContent,
$falseMessage => $falseMessageContent,
]);
$newMessage = 'test new message';
$sourceFileContent = "Yii::t('{$category}', '{$zeroMessage}')";
$sourceFileContent .= "Yii::t('{$category}', '{$falseMessage}')";
$sourceFileContent .= "Yii::t('{$category}', '{$newMessage}')";
$this->createSourceFile($sourceFileContent);
$this->composeConfigFile([
'languages' => [$language],
'sourcePath' => $this->sourcePath,
'messagePath' => $this->messagePath,
'overwrite' => true,
]);
$this->runMessageControllerAction('extract', [$this->configFileName]);
$messages = require($this->messagePath . DIRECTORY_SEPARATOR . $messageFileName);
$this->assertTrue($zeroMessageContent === $messages[$zeroMessage], 'Message content "0" is lost!');
$this->assertTrue($falseMessageContent === $messages[$falseMessage], 'Message content "false" is lost!');
}
/**
* @depends testCreateTranslation
*/
public function testMultiplyTranslators()
{
if (defined('HHVM_VERSION')) {
$this->markTestSkipped('Can not test on HHVM because modified files can not be reloaded.');
}
$language = 'en';
$category = 'test_category6';
$translators = [
'Yii::t',
'Custom::translate',
];
$sourceMessages = [
'first message',
'second message',
];
$sourceFileContent = '';
foreach ($sourceMessages as $key => $message) {
$sourceFileContent .= $translators[$key] . "('{$category}', '{$message}');\n";
}
$this->createSourceFile($sourceFileContent);
$this->composeConfigFile([
'languages' => [$language],
'sourcePath' => $this->sourcePath,
'messagePath' => $this->messagePath,
'translator' => $translators,
]);
$this->runMessageControllerAction('extract', [$this->configFileName]);
$messageFileName = $this->messagePath . DIRECTORY_SEPARATOR . $language . DIRECTORY_SEPARATOR . $category . '.php';
$messages = require($messageFileName);
foreach ($sourceMessages as $sourceMessage) {
$this->assertTrue(array_key_exists($sourceMessage, $messages));
}
}
}
<?php
namespace yiiunit\framework\console\controllers;
use Yii;
use yii\helpers\FileHelper;
use yii\helpers\VarDumper;
/**
* Tests that [[\yii\console\controllers\MessageController]] works as expected with PHP message format.
*/
class PHPMessageControllerTest extends BaseMessageControllerTest
{
protected $messagePath;
public function setUp()
{
parent::setUp();
$this->messagePath = Yii::getAlias('@yiiunit/runtime/test_messages');
FileHelper::createDirectory($this->messagePath, 0777);
}
public function tearDown()
{
parent::tearDown();
FileHelper::removeDirectory($this->messagePath);
}
/**
* @inheritdoc
*/
protected function getDefaultConfig()
{
return [
'format' => 'php',
'languages' => [$this->language],
'sourcePath' => $this->sourcePath,
'messagePath' => $this->messagePath,
'overwrite' => true,
];
}
/**
* @param string $category
* @return string message file path
*/
protected function getMessageFilePath($category)
{
return $this->messagePath . '/' . $this->language . '/' . $category . '.php';
}
/**
* @inheritdoc
*/
protected function saveMessages($messages, $category)
{
$fileName = $this->getMessageFilePath($category);
if (file_exists($fileName)) {
unlink($fileName);
} else {
$dirName = dirname($fileName);
if (!file_exists($dirName)) {
mkdir($dirName, 0777, true);
}
}
$fileContent = '<?php return ' . VarDumper::export($messages) . ';';
file_put_contents($fileName, $fileContent);
}
/**
* @inheritdoc
*/
protected function loadMessages($category)
{
if (defined('HHVM_VERSION')) {
// https://github.com/facebook/hhvm/issues/1447
$this->markTestSkipped('Can not test on HHVM because require is cached.');
}
$messageFilePath = $this->getMessageFilePath($category);
$this->assertTrue(file_exists($messageFilePath), "There's no message file $messageFilePath!");
return require $messageFilePath;
}
}
\ No newline at end of file
<?php
namespace yiiunit\framework\console\controllers;
use Yii;
use yii\helpers\FileHelper;
use yii\i18n\GettextPoFile;
/**
* Tests that [[\yii\console\controllers\MessageController]] works as expected with PO message format.
*/
class POMessageControllerTest extends BaseMessageControllerTest
{
protected $messagePath;
protected $catalog = 'messages';
public function setUp()
{
parent::setUp();
$this->messagePath = Yii::getAlias('@yiiunit/runtime/test_messages');
FileHelper::createDirectory($this->messagePath, 0777);
}
public function tearDown()
{
parent::tearDown();
FileHelper::removeDirectory($this->messagePath);
}
/**
* @inheritdoc
*/
protected function getDefaultConfig()
{
return [
'format' => 'po',
'languages' => [$this->language],
'sourcePath' => $this->sourcePath,
'messagePath' => $this->messagePath,
'overwrite' => true,
];
}
/**
* @return string message file path
*/
protected function getMessageFilePath()
{
return $this->messagePath . '/' . $this->language . '/' . $this->catalog . '.po';
}
/**
* @inheritdoc
*/
protected function saveMessages($messages, $category)
{
$messageFilePath = $this->getMessageFilePath();
FileHelper::createDirectory(dirname($messageFilePath), 0777);
$gettext = new GettextPoFile();
$data = [];
foreach ($messages as $message => $translation) {
$data[$category . chr(4) . $message] = $translation;
}
$gettext->save($messageFilePath, $data);
}
/**
* @inheritdoc
*/
protected function loadMessages($category)
{
$messageFilePath = $this->getMessageFilePath();
$this->assertTrue(file_exists($messageFilePath), "There's no message file $messageFilePath!");
$gettext = new GettextPoFile();
return $gettext->load($messageFilePath, $category);
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment