Skip to content

Commit

Permalink
Version 2.3.2
Browse files Browse the repository at this point in the history
MessageController CSV Import/Export
  • Loading branch information
davidhirtz committed Apr 24, 2024
1 parent 703794e commit 4f49e48
Show file tree
Hide file tree
Showing 13 changed files with 401 additions and 32 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## 2.3.2 (under development)
## 2.3.2 (Apr 24, 2024)

- Added `MessageController` extending the default framework controller by two methods `export-csv` and `export-csv`
- Added `MigrationTrait::dropColumnIfExists()` and `MigrationTrait:dropIndexIfExists()`
- Enhanced `ErrorAction` to allow for custom error messages for 404 and 403 errors
- Enhanced `NavBar::$languageRoute` to be merged with query parameters
Expand Down
4 changes: 3 additions & 1 deletion src/console/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use davidhirtz\yii2\skeleton\base\traits\ApplicationTrait;
use davidhirtz\yii2\skeleton\console\controllers\AssetController;
use davidhirtz\yii2\skeleton\console\controllers\MaintenanceController;
use davidhirtz\yii2\skeleton\console\controllers\MessageController;
use davidhirtz\yii2\skeleton\console\controllers\MigrateController;
use davidhirtz\yii2\skeleton\console\controllers\ParamsController;
use davidhirtz\yii2\skeleton\console\controllers\TrailController;
Expand Down Expand Up @@ -43,8 +44,9 @@ public function coreCommands(): array
{
return array_merge(parent::coreCommands(), [
'asset' => AssetController::class,
'migrate' => MigrateController::class,
'maintenance' => MaintenanceController::class,
'message' => MessageController::class,
'migrate' => MigrateController::class,
'params' => ParamsController::class,
'trail' => TrailController::class,
]);
Expand Down
168 changes: 168 additions & 0 deletions src/console/controllers/MessageController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
<?php

namespace davidhirtz\yii2\skeleton\console\controllers;

use davidhirtz\yii2\skeleton\console\controllers\traits\ControllerTrait;
use davidhirtz\yii2\skeleton\helpers\FileHelper;
use Yii;
use yii\console\Exception;
use yii\console\ExitCode;
use yii\helpers\VarDumper;

class MessageController extends \yii\console\controllers\MessageController
{
use ControllerTrait;

public function actionExtract($configFile = null): void
{
$configFile ??= $this->getDefaultConfigPath();
parent::actionExtract($configFile);
}

/**
* Exports translations to CSV format after running extract.
*/
public function actionExportCsv(?string $destination = null, ?string $configFile = null): void
{
if ($this->format !== 'php') {
throw new Exception('Only PHP format is supported.');
}

$this->actionExtract($configFile);

$destination = Yii::getAlias($destination ?? '@runtime/messages');
FileHelper::createDirectory($destination);

$this->interactiveStartStdout("Exporting translations ...");

$files = FileHelper::findFiles($this->config['messagePath'], [
'only' => ['*/*.php'],
'recursive' => true,
]);

$messages = [];

foreach ($files as $file) {
$category = pathinfo($file, PATHINFO_FILENAME);
$language = pathinfo(dirname($file), PATHINFO_FILENAME);
$messages[$category][$language] = require $file;
}

foreach ($messages as $category => $languages) {
$filename = "$destination/$category.csv";
$fp = fopen($filename, 'w');

fputcsv($fp, array_unique([
Yii::$app->sourceLanguage,
...array_keys($languages),
]));

foreach ($languages[Yii::$app->sourceLanguage] as $source => $translation) {
$row = [$source];

foreach ($languages as $language => $translations) {
if ($language !== Yii::$app->sourceLanguage) {
$row[] = $translations[$source] ?? '';
}
}

fputcsv($fp, $row);
}

fclose($fp);
}

$this->interactiveDoneStdout();
}

/**
* Imports translations from CSV file.
*/
public function actionImportCsv(?string $source = null, ?string $configFile = null): int
{
if ($this->format !== 'php') {
throw new Exception('Only PHP format is supported.');
}

if (!$source) {
throw new Exception('Source file in CSV format must be provided.');
}

$source = Yii::getAlias($source);

if (!is_file($source)) {
throw new Exception("Failed to read source file \"$source\".");
}

$file = fopen($source, 'r');
$languages = fgetcsv($file);

if (($languages[0] ?? null) !== Yii::$app->sourceLanguage) {
throw new Exception('Source file must contain source language as first column.');
}

$configFile ??= $this->getDefaultConfigPath();
$this->initConfig($configFile);

foreach ($languages as $language) {
if (!in_array($language, $this->config['languages'])) {
throw new Exception("Language \"$language\" is not supported.");
}
}

$this->interactiveStartStdout("Importing translations ...");

$category = pathinfo($source, PATHINFO_FILENAME);
$messages = [];

while (($row = fgetcsv($file)) !== false) {
foreach ($row as $key => $value) {
if ($key === 0) {
$source = trim($value);
$messages[Yii::$app->sourceLanguage][$source] = '';
} else {
$messages[$languages[$key]][$source] = trim($value);
}
}
}

fclose($file);

foreach ($messages as $language => $translations) {
$filename = "{$this->config['messagePath']}/$language/$category.php";

if (file_exists($filename)) {
$existing = require $filename;
$translations = [...$existing, ...$translations];
}

if ($this->config['sort']) {
ksort($translations);
}

$array = VarDumper::export($translations);
$content = <<<EOD
<?php
{$this->config['phpFileHeader']}{$this->config['phpDocBlock']}
return $array;
EOD;

FileHelper::createDirectory(dirname($filename));

if (file_put_contents($filename, $content, LOCK_EX) === false) {
$this->interactiveDoneStdout(false);
return ExitCode::UNSPECIFIED_ERROR;
}
}

$this->interactiveDoneStdout();
return ExitCode::OK;
}

protected function getDefaultConfigPath(): ?string
{
$file = Yii::getAlias('@messages/config.php');
return is_file($file) ? $file : null;
}
}
13 changes: 1 addition & 12 deletions src/messages/config.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,13 @@
'sourcePath' => dirname(__DIR__, 1),
'messagePath' => __DIR__,
'languages' => ['de', 'en-US', 'zh-CN', 'zh-TW', 'fr', 'pt'],
'ignoreCategories' => [
'anakin',
'cms',
'config',
'hotspot',
'media',
'newsletter',
'shopify',
'yii',
],
'ignoreCategories' => ['yii'],
'overwrite' => true,
'removeUnused' => true,
'only' => ['*.php'],
'format' => 'php',
'sort' => true,
'except' => [
'config',
'messages',
'tests',
],
];
3 changes: 1 addition & 2 deletions src/messages/de/skeleton.php
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@
'Password reset' => 'Passwort zurücksetzen',
'Permission' => 'Benutzerrecht',
'Permission assigned' => 'Benutzerrecht erteilt',
'Permission denied' => 'Zugriff verweigert',
'Permission denied.' => 'Zugriff verweigert',
'Permission revoked' => 'Benutzerrecht entzogen',
'Permission {permission} assigned' => 'Benutzerrecht {permission} erteilt',
'Permission {permission} revoked' => 'Benutzerrecht {permission} entzogen',
Expand Down Expand Up @@ -210,7 +210,6 @@
'The redirect rule was created.' => 'Die Weiterleitung wurde erstellt. ',
'The redirect rule was deleted.' => 'Die Weiterleitung wurde gelöscht. ',
'The redirect rule was updated.' => 'Die Weiterleitung wurde aktualisiert.',
'The requested page was not found' => 'Die angeforderte Seite wurde nicht gefunden',
'The selected redirect rules were deleted.' => 'Die ausgewählten Weiterleitungen wurden gelöscht.',
'The site ownership could not be transferred' => 'Der Webseitenbesitzer konnte nicht geändert werden',
'The user cannot be deleted.' => 'Der Benutzer kann nicht gelöscht werden.',
Expand Down
3 changes: 1 addition & 2 deletions src/messages/en-US/skeleton.php
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@
'Password reset' => '',
'Permission' => '',
'Permission assigned' => '',
'Permission denied' => '',
'Permission denied.' => '',
'Permission revoked' => '',
'Permission {permission} assigned' => '',
'Permission {permission} revoked' => '',
Expand Down Expand Up @@ -210,7 +210,6 @@
'The redirect rule was created.' => '',
'The redirect rule was deleted.' => '',
'The redirect rule was updated.' => '',
'The requested page was not found' => '',
'The selected redirect rules were deleted.' => '',
'The site ownership could not be transferred' => '',
'The user cannot be deleted.' => '',
Expand Down
3 changes: 1 addition & 2 deletions src/messages/fr/skeleton.php
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@
'Password reset' => '',
'Permission' => '',
'Permission assigned' => '',
'Permission denied' => '',
'Permission denied.' => '',
'Permission revoked' => '',
'Permission {permission} assigned' => '',
'Permission {permission} revoked' => '',
Expand Down Expand Up @@ -210,7 +210,6 @@
'The redirect rule was created.' => '',
'The redirect rule was deleted.' => '',
'The redirect rule was updated.' => '',
'The requested page was not found' => '',
'The selected redirect rules were deleted.' => '',
'The site ownership could not be transferred' => '',
'The user cannot be deleted.' => '',
Expand Down
3 changes: 1 addition & 2 deletions src/messages/pt/skeleton.php
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@
'Password reset' => '',
'Permission' => '',
'Permission assigned' => '',
'Permission denied' => '',
'Permission denied.' => '',
'Permission revoked' => '',
'Permission {permission} assigned' => '',
'Permission {permission} revoked' => '',
Expand Down Expand Up @@ -210,7 +210,6 @@
'The redirect rule was created.' => '',
'The redirect rule was deleted.' => '',
'The redirect rule was updated.' => '',
'The requested page was not found' => '',
'The selected redirect rules were deleted.' => '',
'The site ownership could not be transferred' => '',
'The user cannot be deleted.' => '',
Expand Down
3 changes: 1 addition & 2 deletions src/messages/zh-CN/skeleton.php
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@
'Password reset' => '',
'Permission' => '',
'Permission assigned' => '',
'Permission denied' => '',
'Permission denied.' => '',
'Permission revoked' => '',
'Permission {permission} assigned' => '',
'Permission {permission} revoked' => '',
Expand Down Expand Up @@ -210,7 +210,6 @@
'The redirect rule was created.' => '',
'The redirect rule was deleted.' => '',
'The redirect rule was updated.' => '',
'The requested page was not found' => '',
'The selected redirect rules were deleted.' => '',
'The site ownership could not be transferred' => '',
'The user cannot be deleted.' => '',
Expand Down
3 changes: 1 addition & 2 deletions src/messages/zh-TW/skeleton.php
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@
'Password reset' => '',
'Permission' => '',
'Permission assigned' => '',
'Permission denied' => '',
'Permission denied.' => '',
'Permission revoked' => '',
'Permission {permission} assigned' => '',
'Permission {permission} revoked' => '',
Expand Down Expand Up @@ -210,7 +210,6 @@
'The redirect rule was created.' => '',
'The redirect rule was deleted.' => '',
'The redirect rule was updated.' => '',
'The requested page was not found' => '',
'The selected redirect rules were deleted.' => '',
'The site ownership could not be transferred' => '',
'The user cannot be deleted.' => '',
Expand Down
4 changes: 2 additions & 2 deletions src/web/ErrorAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ protected function getExceptionName(): string
protected function getExceptionMessage(): string
{
return parent::getExceptionMessage() ?: match ($this->getExceptionCode()) {
403 => Yii::t('skeleton', 'Permission denied'),
404 => Yii::t('skeleton', 'The requested page was not found'),
403 => Yii::t('skeleton', 'Permission denied.'),
404 => Yii::t('yii', 'Page not found.'),
default => Yii::t('yii', 'Error'),
};
}
Expand Down
Loading

0 comments on commit 4f49e48

Please sign in to comment.