'Yii::t', 'overwrite' => false, 'removeUnused' => false, 'sort' => false, 'format' => 'php', ]; $configFile = Yii::getAlias($configFile); if (!is_file($configFile)) { throw new UserException("The configuration file does not exist: $configFile"); } $config = array_merge($config, require($configFile)); if (!is_dir($config['sourcePath'])) { throw new UserException("The source path {$config['sourcePath']} is not a valid directory."); } $files = FileHelper::findFiles(realpath($config['sourcePath']), $config); $unremoved = []; foreach ($files as $fileName) { if (!is_array($config['translator'])) { $translator = [$config['translator']]; } foreach ($translator as $currentTranslator) { $n = 0; $subject = file_get_contents($fileName); $replacedSubject = preg_replace_callback( '/\b(\\\\)?' . $currentTranslator . '\s*\(\s*(\'.*?(? $messages) { $messages = implode(PHP_EOL, $messages); Console::output("$fileName:".PHP_EOL.$messages); } } } public function actionMigrate($inputConfigFile, $outputConfigFile) { $inputConfigFile = Yii::getAlias($inputConfigFile); if (!is_file($inputConfigFile)) { throw new \Exception("The configuration file does not exist: $inputConfigFile"); } $inputConfig = array_merge([ 'translator' => 'Yii::t', 'overwrite' => false, 'removeUnused' => false, 'sort' => false, 'format' => 'php', ], require($inputConfigFile)); switch($inputConfig['format']){ case 'php': $messages = $this->readFromPhpInput($inputConfig); break; case 'db': $messages = $this->readFromDbInput($inputConfig); break; case 'po': $messages = $this->readFromPoInput($inputConfig); break; default: throw new InvalidConfigException('Unknown input format '.$inputConfig['format']); } if ($this->confirm('All existing messages in the output source will be removed. Proceed?')) { $outputConfigFile = Yii::getAlias($outputConfigFile); if (!is_file($outputConfigFile)) { throw new \Exception("The configuration file does not exist: $outputConfigFile"); } $outputConfig = array_merge([ 'translator' => 'Yii::t', 'overwrite' => false, 'removeUnused' => false, 'sort' => false, 'format' => 'php', ], require($outputConfigFile)); switch($outputConfig['format']){ case 'php': $this->saveToPhpOutput($messages, $outputConfig); break; case 'db': $this->saveToDbOutput($messages, $outputConfig); break; case 'po': $this->saveToPoOutput($messages, $outputConfig); break; default: throw new InvalidConfigException('Unknown output format'); } }; } protected function readFromPhpInput($config) { $messages = []; foreach ($config['languages'] as $language) { $messagePath = Yii::getAlias("$config[messagePath]/$language"); $files = FileHelper::findFiles(FileHelper::normalizePath($messagePath)); foreach ($files as $file) { $category = pathinfo($file, PATHINFO_FILENAME); $messages[$language][$category] = require($file); } } return $messages; } protected function readFromDbInput($config) { $messages = []; $db = Yii::$app->get(isset($config['db']) ? $config['db'] : 'db'); $sourceMessageTable = isset($config['sourceMessageTable']) ? $config['sourceMessageTable'] : '{{%source_message}}'; $messageTable = isset($config['messageTable']) ? $config['messageTable'] : '{{%message}}'; if (!$db instanceof \yii\db\Connection) { throw new \Exception('The "db" option must refer to a valid database application component.'); } $q = new \yii\db\Query; Console::output('Reading messages from database'); $sourceMessages = $q->select(['*'])->from($sourceMessageTable)->all(); foreach ($config['languages'] as $language) { $translations = $q->select(['*'])->from($messageTable)->where(['language'=>$language])->indexBy('id')->all(); foreach ($sourceMessages as $row) { $translation = ArrayHelper::getValue($translations, $row['id']); $messages[$language][$row['category']][$row['message']] = $translation ? $translation['translation'] : null; } } return $messages; } protected function readFromPoInput($config) { throw new \Exception("PO migration didn't implemented yet"); } protected function saveToDbOutput($messages, $config) { $db = Yii::$app->get(isset($config['db']) ? $config['db'] : 'db'); $sourceMessageTable = isset($config['sourceMessageTable']) ? $config['sourceMessageTable'] : '{{%source_message}}'; $messageTable = isset($config['messageTable']) ? $config['messageTable'] : '{{%message}}'; if (!$db instanceof \yii\db\Connection) { throw new \Exception('The "db" option must refer to a valid database application component.'); } $db->createCommand()->truncateTable($messageTable)->execute(); $db->createCommand()->delete($sourceMessageTable)->execute(); $insertedSourceMessages = []; foreach ($messages as $language => $categories) { Console::output("Language: $language"); foreach ($categories as $category => $msgs) { $messagesCount = count($msgs, COUNT_RECURSIVE); $i = 0; Console::output("Category: $category"); Console::startProgress(0, $messagesCount); foreach ($msgs as $m => $translation) { Console::updateProgress(++$i, $messagesCount); $lastId = array_search($m, ArrayHelper::getValue($insertedSourceMessages, $category, [])); if ($lastId == false) { $db->createCommand() ->insert($sourceMessageTable, ['category' => $category, 'message' => $m])->execute(); $lastId = $db->getLastInsertID($db->driverName == 'pgsql' ? 'i18n_source_message_id_seq' : null); $insertedSourceMessages[$category][$lastId] = $m; } $db->createCommand() ->insert($messageTable, ['id' => $lastId, 'language' => $language, 'translation'=>$translation])->execute(); } Console::endProgress(); } } } protected function saveToPhpOutput($messages, $config) { foreach ($messages as $language => $categories) { $dirName = FileHelper::normalizePath(Yii::getAlias($config['messagePath'].'/'.$language)); FileHelper::createDirectory($dirName); Console::output("Language: $language"); foreach ($categories as $category => $msgs) { $array = VarDumper::export($msgs); $content = "