Skip to content

Commit 0c8834a

Browse files
authored
Merge pull request #99 from RichWeber/patch-1
Improve TranslateBehavior saving
2 parents 93901a8 + 3908312 commit 0c8834a

File tree

2 files changed

+97
-11
lines changed

2 files changed

+97
-11
lines changed

README.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,17 @@ class Category extends \yii\db\ActiveRecord {
420420

421421
* With behavior (since 1.5.3):
422422

423-
**Note:** This will replace the model's original attribute values!
423+
This behavior does the following:
424+
- Replaces the specified attributes with translations after the model is loaded.
425+
- Saves the attribute values as:
426+
1. Source messages, if the current language is the source language.
427+
2. Translations, if the current language is different from the source language.
428+
This way the value stored in database is not overwritten with the translation.
429+
430+
**Note**: If the model should be saved as translation, but the source message does not exist yet in the database
431+
then the message is saved as the source message whether the current language is the source language or not.
432+
To avoid this scan the database for existing messages when using the behavior first, and only save new records
433+
when the current language is the source language.
424434

425435
```php
426436
namespace common\models;

behaviors/TranslateBehavior.php

Lines changed: 86 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,23 @@
66
use yii\db\BaseActiveRecord;
77
use yii\behaviors\AttributeBehavior;
88
use lajax\translatemanager\helpers\Language;
9+
use lajax\translatemanager\models\LanguageSource;
10+
use lajax\translatemanager\models\LanguageTranslate;
911

1012
/**
11-
* TranslateManager Database translate behavior.
13+
* Behavior that translates the model attributes, and saves the changes into database.
14+
*
15+
* This behavior does the following:
16+
* - Replaces the specified attributes with translations after the model is loaded.
17+
* - Saves the attribute values as:
18+
* 1. Source messages, if the current language is the source language.
19+
* 2. Translations, if the current language is different from the source language.
20+
* This way the value stored in database is not overwritten with the translation.
21+
*
22+
* **Note**: If the model should be saved as translation, but the source message does not exist yet in the database
23+
* then the message is saved as the source message whether the current language is the source language or not.
24+
* To avoid this scan the database for existing messages when using the behavior first, and only save new records
25+
* when the current language is the source language.
1226
*
1327
* Installation:
1428
*
@@ -45,6 +59,11 @@ class TranslateBehavior extends AttributeBehavior
4559
*/
4660
public $category = 'database';
4761

62+
/**
63+
* @var BaseActiveRecord the owner model of this behavior
64+
*/
65+
public $owner;
66+
4867
/**
4968
* @inheritdoc
5069
*/
@@ -68,31 +87,88 @@ public function events()
6887
}
6988

7089
/**
71-
* Translates a message to the specified language.
90+
* Translates the attributes to the current language.
7291
*
7392
* @param \yii\base\Event $event
7493
*/
7594
public function translateAttributes($event)
7695
{
77-
/* @var $owner BaseActiveRecord */
78-
$owner = $this->owner;
7996
foreach ($this->translateAttributes as $attribute) {
80-
$owner->{$attribute} = Yii::t($this->category, $owner->attributes[$attribute]);
97+
$this->owner->{$attribute} = Yii::t($this->category, $this->owner->attributes[$attribute]);
8198
}
8299
}
83100

84101
/**
85-
* Saveing new language element by category.
102+
* Saves new language element by category.
86103
*
87104
* @param \yii\base\Event $event
88105
*/
89106
public function saveAttributes($event)
90107
{
91-
/* @var $owner BaseActiveRecord */
92-
$owner = $this->owner;
108+
$isAppInSourceLanguage = Yii::$app->sourceLanguage === Yii::$app->language;
109+
93110
foreach ($this->translateAttributes as $attribute) {
94-
if ($owner->isAttributeChanged($attribute)) {
95-
Language::saveMessage($owner->attributes[$attribute], $this->category);
111+
if (!$this->owner->isAttributeChanged($attribute)) {
112+
continue;
113+
}
114+
115+
if ($isAppInSourceLanguage || !$this->saveAttributeValueAsTranslation($attribute)) {
116+
Language::saveMessage($this->owner->attributes[$attribute], $this->category);
117+
}
118+
}
119+
}
120+
121+
/**
122+
* @param string $attribute The name of the attribute.
123+
*
124+
* @return bool Whether the translation is saved.
125+
*/
126+
private function saveAttributeValueAsTranslation($attribute)
127+
{
128+
$sourceMessage = $this->owner->getOldAttribute($attribute);
129+
$translatedMessage = $this->owner->attributes[$attribute];
130+
131+
// Restore the original value, so it won't be replaced with the translation in the database.
132+
$this->owner->{$attribute} = $sourceMessage;
133+
134+
$translateSource = $this->findSourceMessage($sourceMessage);
135+
if (!$translateSource) {
136+
return false; // The source does not exist, the message cannot be saved as translation.
137+
}
138+
139+
$translation = new LanguageTranslate();
140+
foreach ($translateSource->languageTranslates as $tmpTranslate) {
141+
if ($tmpTranslate->language === Yii::$app->language) {
142+
$translation = $tmpTranslate;
143+
break;
144+
}
145+
}
146+
147+
if ($translation->isNewRecord) {
148+
$translation->id = $translateSource->id;
149+
$translation->language = Yii::$app->language;
150+
}
151+
152+
$translation->translation = $translatedMessage;
153+
$translation->save();
154+
155+
return true;
156+
}
157+
158+
/**
159+
* Finds the source record with case sensitive match.
160+
*
161+
* @param string $message
162+
*
163+
* @return LanguageSource|null Null if the source is not found.
164+
*/
165+
private function findSourceMessage($message)
166+
{
167+
$sourceMessages = LanguageSource::findAll(['message' => $message, 'category' => $this->category]);
168+
169+
foreach ($sourceMessages as $source) {
170+
if ($source->message === $message) {
171+
return $source;
96172
}
97173
}
98174
}

0 commit comments

Comments
 (0)