Commit f605508b by Qiang Xue

Merge pull request #2822 from lucianobaraglia/gii-translatable-strings

Proposal: GII generate strings for I18N
parents 914d37ab 1d7f4854
...@@ -47,6 +47,15 @@ abstract class Generator extends Model ...@@ -47,6 +47,15 @@ abstract class Generator extends Model
* The value of this property is internally managed by this class. * The value of this property is internally managed by this class.
*/ */
public $template; public $template;
/**
* @var boolean whether the strings will be generated using `Yii::t()` or normal strings.
*/
public $enableI18N = false;
/**
* @var string the message category used by `Yii::t()` when `$enableI18N` is `true`.
* Defaults to `app`.
*/
public $messageCategory = 'app';
/** /**
* @return string name of the code generator * @return string name of the code generator
...@@ -76,6 +85,17 @@ abstract class Generator extends Model ...@@ -76,6 +85,17 @@ abstract class Generator extends Model
} }
/** /**
* @inheritdoc
*/
public function attributeLabels()
{
return [
'enableI18N' => 'Enable I18N',
'messageCategory' => 'Message Category',
];
}
/**
* Returns a list of code template files that are required. * Returns a list of code template files that are required.
* Derived classes usually should override this method if they require the existence of * Derived classes usually should override this method if they require the existence of
* certain template files. * certain template files.
...@@ -95,7 +115,7 @@ abstract class Generator extends Model ...@@ -95,7 +115,7 @@ abstract class Generator extends Model
*/ */
public function stickyAttributes() public function stickyAttributes()
{ {
return ['template']; return ['template', 'enableI18N', 'messageCategory'];
} }
/** /**
...@@ -106,7 +126,11 @@ abstract class Generator extends Model ...@@ -106,7 +126,11 @@ abstract class Generator extends Model
*/ */
public function hints() public function hints()
{ {
return []; return [
'enableI18N' => 'This indicates whether the generator should generate strings using <code>Yii::t()</code> method.
Set this to <code>true</code> if you are planning to make your application translatable.',
'messageCategory' => 'This is the category used by <code>Yii::t()</code> in case you enable I18N.',
];
} }
/** /**
...@@ -359,6 +383,16 @@ abstract class Generator extends Model ...@@ -359,6 +383,16 @@ abstract class Generator extends Model
} }
/** /**
* Checks if message category is not empty when I18N is enabled.
*/
public function validateMessageCategory()
{
if ($this->enableI18N && empty($this->messageCategory)) {
$this->addError('messageCategory', "Message Category cannot be blank.");
}
}
/**
* @param string $value the attribute to be validated * @param string $value the attribute to be validated
* @return boolean whether the value is a reserved PHP keyword. * @return boolean whether the value is a reserved PHP keyword.
*/ */
...@@ -448,4 +482,38 @@ abstract class Generator extends Model ...@@ -448,4 +482,38 @@ abstract class Generator extends Model
return in_array(strtolower($value), $keywords, true); return in_array(strtolower($value), $keywords, true);
} }
/**
* Generates a string depending on enableI18N property
* @param string $string the text be generated
* @param array $placeholders the placeholders to use by `Yii::t()`
*/
public function generateString($string = '', $placeholders = [])
{
$string = addslashes($string);
if ($this->enableI18N) {
// If there are placeholders, use them
if (!empty($placeholders)) {
$search = ['array (', ')'];
$replace = ['[', ']'];
$ph = ', ' . str_replace($search, $replace, var_export($placeholders, true));
} else {
$ph = '';
}
$str = "Yii::t('" . $this->messageCategory . "', '" . $string . "'" . $ph . ")";
} else {
// No I18N, replace placeholders by real words, if any
if (!empty($placeholders)) {
$phKeys = array_map(function($word) {
return '{' . $word . '}';
}, array_keys($placeholders));
$phValues = array_values($placeholders);
$str = "'" . str_replace($phKeys, $phValues, $string) . "'";
} else {
// No placeholders, just the given string
$str = "'" . $string . "'";
}
}
return $str;
}
} }
...@@ -111,10 +111,15 @@ yii.gii = (function ($) { ...@@ -111,10 +111,15 @@ yii.gii = (function ($) {
initConfirmationCheckboxes(); initConfirmationCheckboxes();
// model generator: hide class name input when table name input contains * // model generator: hide class name input when table name input contains *
$('#model-generator #generator-tablename').on('change',function () { $('#model-generator #generator-tablename').change(function () {
$('#model-generator .field-generator-modelclass').toggle($(this).val().indexOf('*') == -1); $('#model-generator .field-generator-modelclass').toggle($(this).val().indexOf('*') == -1);
}).change(); }).change();
// CRUD generator: hide messageCategory when I18N is disabled
$('#crud-generator #generator-enablei18n').change(function () {
$('#crud-generator .field-generator-messagecategory').toggle($(this).is(':checked'));
}).change();
// hide Generate button if any input is changed // hide Generate button if any input is changed
$('.default-view .form-group input,select,textarea').change(function () { $('.default-view .form-group input,select,textarea').change(function () {
$('.default-view-results,.default-view-files').hide(); $('.default-view-results,.default-view-files').hide();
......
...@@ -71,6 +71,8 @@ class Generator extends \yii\gii\Generator ...@@ -71,6 +71,8 @@ class Generator extends \yii\gii\Generator
[['indexWidgetType'], 'in', 'range' => ['grid', 'list']], [['indexWidgetType'], 'in', 'range' => ['grid', 'list']],
[['modelClass'], 'validateModelClass'], [['modelClass'], 'validateModelClass'],
[['moduleID'], 'validateModuleID'], [['moduleID'], 'validateModuleID'],
[['enableI18N'], 'boolean'],
[['messageCategory'], 'validateMessageCategory', 'skipOnEmpty' => false],
]); ]);
} }
...@@ -94,7 +96,7 @@ class Generator extends \yii\gii\Generator ...@@ -94,7 +96,7 @@ class Generator extends \yii\gii\Generator
*/ */
public function hints() public function hints()
{ {
return [ return array_merge(parent::hints(), [
'modelClass' => 'This is the ActiveRecord class associated with the table that CRUD will be built upon. 'modelClass' => 'This is the ActiveRecord class associated with the table that CRUD will be built upon.
You should provide a fully qualified class name, e.g., <code>app\models\Post</code>.', You should provide a fully qualified class name, e.g., <code>app\models\Post</code>.',
'controllerClass' => 'This is the name of the controller class to be generated. You should 'controllerClass' => 'This is the name of the controller class to be generated. You should
...@@ -107,7 +109,7 @@ class Generator extends \yii\gii\Generator ...@@ -107,7 +109,7 @@ class Generator extends \yii\gii\Generator
You may choose either <code>GridView</code> or <code>ListView</code>', You may choose either <code>GridView</code> or <code>ListView</code>',
'searchModelClass' => 'This is the name of the search model class to be generated. You should provide a fully 'searchModelClass' => 'This is the name of the search model class to be generated. You should provide a fully
qualified namespaced class name, e.g., <code>app\models\search\PostSearch</code>.', qualified namespaced class name, e.g., <code>app\models\search\PostSearch</code>.',
]; ]);
} }
/** /**
...@@ -123,7 +125,7 @@ class Generator extends \yii\gii\Generator ...@@ -123,7 +125,7 @@ class Generator extends \yii\gii\Generator
*/ */
public function stickyAttributes() public function stickyAttributes()
{ {
return ['baseControllerClass', 'moduleID', 'indexWidgetType']; return array_merge(parent::stickyAttributes(), ['baseControllerClass', 'moduleID', 'indexWidgetType']);
} }
/** /**
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
use yii\helpers\StringHelper; use yii\helpers\StringHelper;
/** /**
* This is the template for generating a CRUD controller class file. * This is the template for generating CRUD search class of the specified model.
* *
* @var yii\web\View $this * @var yii\web\View $this
* @var yii\gii\generators\crud\Generator $generator * @var yii\gii\generators\crud\Generator $generator
...@@ -49,7 +49,7 @@ class <?= $searchModelClass ?> extends Model ...@@ -49,7 +49,7 @@ class <?= $searchModelClass ?> extends Model
{ {
return [ return [
<?php foreach ($labels as $name => $label): ?> <?php foreach ($labels as $name => $label): ?>
<?= "'$name' => '" . addslashes($label) . "',\n" ?> <?= "'$name' => " . $generator->generateString($label) . ",\n" ?>
<?php endforeach; ?> <?php endforeach; ?>
]; ];
} }
......
...@@ -36,7 +36,7 @@ use yii\widgets\ActiveForm; ...@@ -36,7 +36,7 @@ use yii\widgets\ActiveForm;
echo " <?= " . $generator->generateActiveField($attribute) . " ?>\n\n"; echo " <?= " . $generator->generateActiveField($attribute) . " ?>\n\n";
} ?> } ?>
<div class="form-group"> <div class="form-group">
<?= "<?= " ?>Html::submitButton($model->isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?> <?= "<?= " ?>Html::submitButton($model->isNewRecord ? <?= $generator->generateString('Create') ?> : <?= $generator->generateString('Update') ?>, ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
</div> </div>
<?= "<?php " ?>ActiveForm::end(); ?> <?= "<?php " ?>ActiveForm::end(); ?>
......
...@@ -39,8 +39,8 @@ foreach ($generator->getColumnNames() as $attribute) { ...@@ -39,8 +39,8 @@ foreach ($generator->getColumnNames() as $attribute) {
} }
?> ?>
<div class="form-group"> <div class="form-group">
<?= "<?= " ?>Html::submitButton('Search', ['class' => 'btn btn-primary']) ?> <?= "<?= " ?>Html::submitButton(<?= $generator->generateString('Search') ?>, ['class' => 'btn btn-primary']) ?>
<?= "<?= " ?>Html::resetButton('Reset', ['class' => 'btn btn-default']) ?> <?= "<?= " ?>Html::resetButton(<?= $generator->generateString('Reset') ?>, ['class' => 'btn btn-default']) ?>
</div> </div>
<?= "<?php " ?>ActiveForm::end(); ?> <?= "<?php " ?>ActiveForm::end(); ?>
......
...@@ -18,8 +18,8 @@ use yii\helpers\Html; ...@@ -18,8 +18,8 @@ use yii\helpers\Html;
* @var <?= ltrim($generator->modelClass, '\\') ?> $model * @var <?= ltrim($generator->modelClass, '\\') ?> $model
*/ */
$this->title = 'Create <?= Inflector::camel2words(StringHelper::basename($generator->modelClass)) ?>'; $this->title = <?= $generator->generateString('Create {modelClass}', ['modelClass' => Inflector::camel2words(StringHelper::basename($generator->modelClass))]) ?>;
$this->params['breadcrumbs'][] = ['label' => '<?= Inflector::pluralize(Inflector::camel2words(StringHelper::basename($generator->modelClass))) ?>', 'url' => ['index']]; $this->params['breadcrumbs'][] = ['label' => <?= $generator->generateString(Inflector::pluralize(Inflector::camel2words(StringHelper::basename($generator->modelClass)))) ?>, 'url' => ['index']];
$this->params['breadcrumbs'][] = $this->title; $this->params['breadcrumbs'][] = $this->title;
?> ?>
<div class="<?= Inflector::camel2id(StringHelper::basename($generator->modelClass)) ?>-create"> <div class="<?= Inflector::camel2id(StringHelper::basename($generator->modelClass)) ?>-create">
......
...@@ -23,7 +23,7 @@ use <?= $generator->indexWidgetType === 'grid' ? "yii\\grid\\GridView" : "yii\\w ...@@ -23,7 +23,7 @@ use <?= $generator->indexWidgetType === 'grid' ? "yii\\grid\\GridView" : "yii\\w
* @var <?= ltrim($generator->searchModelClass, '\\') ?> $searchModel * @var <?= ltrim($generator->searchModelClass, '\\') ?> $searchModel
*/ */
$this->title = '<?= Inflector::pluralize(Inflector::camel2words(StringHelper::basename($generator->modelClass))) ?>'; $this->title = <?= $generator->generateString(Inflector::pluralize(Inflector::camel2words(StringHelper::basename($generator->modelClass)))) ?>;
$this->params['breadcrumbs'][] = $this->title; $this->params['breadcrumbs'][] = $this->title;
?> ?>
<div class="<?= Inflector::camel2id(StringHelper::basename($generator->modelClass)) ?>-index"> <div class="<?= Inflector::camel2id(StringHelper::basename($generator->modelClass)) ?>-index">
...@@ -33,7 +33,7 @@ $this->params['breadcrumbs'][] = $this->title; ...@@ -33,7 +33,7 @@ $this->params['breadcrumbs'][] = $this->title;
<?= "<?php " . ($generator->indexWidgetType === 'grid' ? "// " : "") ?>echo $this->render('_search', ['model' => $searchModel]); ?> <?= "<?php " . ($generator->indexWidgetType === 'grid' ? "// " : "") ?>echo $this->render('_search', ['model' => $searchModel]); ?>
<p> <p>
<?= "<?= " ?>Html::a('Create <?= Inflector::camel2words(StringHelper::basename($generator->modelClass)) ?>', ['create'], ['class' => 'btn btn-success']) ?> <?= "<?= " ?>Html::a(<?= $generator->generateString('Create {modelClass}', ['modelClass' => Inflector::camel2words(StringHelper::basename($generator->modelClass))]) ?>, ['create'], ['class' => 'btn btn-success']) ?>
</p> </p>
<?php if ($generator->indexWidgetType === 'grid'): ?> <?php if ($generator->indexWidgetType === 'grid'): ?>
......
...@@ -20,10 +20,10 @@ use yii\helpers\Html; ...@@ -20,10 +20,10 @@ use yii\helpers\Html;
* @var <?= ltrim($generator->modelClass, '\\') ?> $model * @var <?= ltrim($generator->modelClass, '\\') ?> $model
*/ */
$this->title = 'Update <?= Inflector::camel2words(StringHelper::basename($generator->modelClass)) ?>: ' . $model-><?= $generator->getNameAttribute() ?>; $this->title = <?= $generator->generateString('Update {modelClass}: ', ['modelClass' => Inflector::camel2words(StringHelper::basename($generator->modelClass))]) ?> . $model-><?= $generator->getNameAttribute() ?>;
$this->params['breadcrumbs'][] = ['label' => '<?= Inflector::pluralize(Inflector::camel2words(StringHelper::basename($generator->modelClass))) ?>', 'url' => ['index']]; $this->params['breadcrumbs'][] = ['label' => <?= $generator->generateString(Inflector::pluralize(Inflector::camel2words(StringHelper::basename($generator->modelClass)))) ?>, 'url' => ['index']];
$this->params['breadcrumbs'][] = ['label' => $model-><?= $generator->getNameAttribute() ?>, 'url' => ['view', <?= $urlParams ?>]]; $this->params['breadcrumbs'][] = ['label' => $model-><?= $generator->getNameAttribute() ?>, 'url' => ['view', <?= $urlParams ?>]];
$this->params['breadcrumbs'][] = 'Update'; $this->params['breadcrumbs'][] = <?= $generator->generateString('Update') ?>;
?> ?>
<div class="<?= Inflector::camel2id(StringHelper::basename($generator->modelClass)) ?>-update"> <div class="<?= Inflector::camel2id(StringHelper::basename($generator->modelClass)) ?>-update">
......
...@@ -22,7 +22,7 @@ use yii\widgets\DetailView; ...@@ -22,7 +22,7 @@ use yii\widgets\DetailView;
*/ */
$this->title = $model-><?= $generator->getNameAttribute() ?>; $this->title = $model-><?= $generator->getNameAttribute() ?>;
$this->params['breadcrumbs'][] = ['label' => '<?= Inflector::pluralize(Inflector::camel2words(StringHelper::basename($generator->modelClass))) ?>', 'url' => ['index']]; $this->params['breadcrumbs'][] = ['label' => <?= $generator->generateString(Inflector::pluralize(Inflector::camel2words(StringHelper::basename($generator->modelClass)))) ?>, 'url' => ['index']];
$this->params['breadcrumbs'][] = $this->title; $this->params['breadcrumbs'][] = $this->title;
?> ?>
<div class="<?= Inflector::camel2id(StringHelper::basename($generator->modelClass)) ?>-view"> <div class="<?= Inflector::camel2id(StringHelper::basename($generator->modelClass)) ?>-view">
...@@ -30,11 +30,11 @@ $this->params['breadcrumbs'][] = $this->title; ...@@ -30,11 +30,11 @@ $this->params['breadcrumbs'][] = $this->title;
<h1><?= "<?= " ?>Html::encode($this->title) ?></h1> <h1><?= "<?= " ?>Html::encode($this->title) ?></h1>
<p> <p>
<?= "<?= " ?>Html::a('Update', ['update', <?= $urlParams ?>], ['class' => 'btn btn-primary']) ?> <?= "<?= " ?>Html::a(<?= $generator->generateString('Update') ?>, ['update', <?= $urlParams ?>], ['class' => 'btn btn-primary']) ?>
<?= "<?= " ?>Html::a('Delete', ['delete', <?= $urlParams ?>], [ <?= "<?= " ?>Html::a(<?= $generator->generateString('Delete') ?>, ['delete', <?= $urlParams ?>], [
'class' => 'btn btn-danger', 'class' => 'btn btn-danger',
'data' => [ 'data' => [
'confirm' => Yii::t('app', 'Are you sure you want to delete this item?'), 'confirm' => <?= $generator->generateString('Are you sure you want to delete this item?') ?>,
'method' => 'post', 'method' => 'post',
], ],
]) ?> ]) ?>
......
...@@ -14,3 +14,5 @@ echo $form->field($generator, 'indexWidgetType')->dropDownList([ ...@@ -14,3 +14,5 @@ echo $form->field($generator, 'indexWidgetType')->dropDownList([
'grid' => 'GridView', 'grid' => 'GridView',
'list' => 'ListView', 'list' => 'ListView',
]); ]);
echo $form->field($generator, 'enableI18N')->checkbox();
echo $form->field($generator, 'messageCategory');
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