Translation works fine on related models inside modal forms when saving record for the first time, but not on update...
+1
I can confirm this. to reproduce use a controller that uses:
$implements = ['Backend\Behaviors\RelationController']
and configure the related model. if this model imlements 'RainLab.Translate.Behaviors.TranslatableModel' the translated values are only set when creating the related model, on updates only the default language values are saved.
If the same model is used in a normal form controller, everything works as expected.
Same here. Model attributes translations of my related model are never updated.
If anyone has the time to look into a fix for this issue, that would be welcome. Otherwise this will have to wait until we have time to take a deeper look into the problem.
Thanks for the report!
it's not a fix for the issue.
But to make it work, paste in your related model
public function afterSave()
{
if (post("RLTranslate")) {
foreach (post("RLTranslate") as $key => $value) {
$data = json_encode($value);
$obj = Db::table("rainlab_translate_attributes")
->where("locale", $key)
->where("model_id", $this->id)
->where("model_type", get_class($this->model));
if ($obj->count() > 0) {
$obj->update(["attribute_data" => $data]);
}
}
}
}
I probably opened the same issue. #242 +1
Thanks @shiftaltd I made a trait for the modal. If the model is used in a modal, you can use translations. Fix is tested for normal strings and repeaters.
For now I added this inside my own plugin, but it could be added to the translate plugin under traits
<?php
namespace AuthorName\ExamplePlugin\Traits;
use Illuminate\Support\Facades\DB;
/**
* Trait that can be imported into modals who have modals and need to be translated.
*
* Trait TranslatableModal
* @package AuthorName\ExamplePlugin
*/
trait TranslatableModal
{
/**
* Method that saves the translation data of modal.
* TODO: Try to integrate this in translate plugin.
*
* @uses DB
*/
public function afterSave()
{
if (post("RLTranslate")) {
foreach (post("RLTranslate") as $key => $value) {
$data = json_encode($value);
$obj = Db::table("rainlab_translate_attributes")
->where("locale", $key)
->where("model_id", $this->id)
->where("model_type", get_class($this->model));
// If the translate object exist in database update it
if ($obj->count() > 0) {
$obj->update(["attribute_data" => $data]);
}
}
}
}
}
Edit: There should be another solution that doesn't use the afterSave method
I experiment the same issue.
Thx @getrightnl and @shiftaltd for the temp fix.
Can someone provide a PR with an official fix to this please?
Thanks for this quick fix @shiftaltd
I experienced some issues with this solution.
Save modal (relation) and then save main record. The main record values will override the relation attributes.
This will not work when relation is already created and we apply the fix. We must remove it and add it again to work as expected.
I came up with this code if someone experience the same issues:
<?php
namespace AuthorName\ExamplePlugin\Traits;
use Illuminate\Support\Facades\DB;
/**
* Trait TranslatableRelation
* @package AuthorName\ExamplePlugin\Traits
*/
trait TranslatableRelation
{
/**
* This is a temporary fix until
* https://github.com/rainlab/translate-plugin/issues/209
* is resolved.
*/
protected function setTranslatableAttributes()
{
if ( ! post('RLTranslate')) {
return;
}
foreach (post("RLTranslate") as $key => $value) {
$data = collect($value)->intersectByKeys(array_flip($this->translatable));
$obj = DB::table("rainlab_translate_attributes")
->where("locale", $key)
->where("model_id", $this->id)
->where("model_type", get_class($this->model));
if ($obj->count() > 0) {
$obj->update(["attribute_data" => $data->toJson()]);
} else {
DB::table('rainlab_translate_attributes')
->insert([
'locale' => $key,
'model_id' => $this->id,
'model_type' => get_class($this->model),
'attribute_data' => $data->toJson(),
]
);
}
}
}
}
@mplodowski How does this work? For some reason, adding this to a modal does not work. It doesn't get called.
Related model must implement behavior:
public $implement = ['@RainLab.Translate.Behaviors.TranslatableModel'];
and then use this trait.
This trait was created some time ago and I don't know if it still works as expected.
I had to call the setTranslatableFields in afterSave to make it work with build 435. Maybe the method's name changed internally?
<?php
namespace Vendor\Plugin\Classes\Traits;
use Illuminate\Support\Facades\DB;
/**
* @see https://github.com/rainlab/translate-plugin/issues/209#issuecomment-362088300
*/
trait TranslatableRelation
{
/**
* This is a temporary fix until
* https://github.com/rainlab/translate-plugin/issues/209
* is resolved.
*/
protected function setTranslatableFields()
{
if ( ! post('RLTranslate')) {
return;
}
foreach (post('RLTranslate') as $key => $value) {
$data = collect($value)->intersectByKeys(array_flip($this->translatable));
$obj = DB::table('rainlab_translate_attributes')
->where('locale', $key)
->where('model_id', $this->id)
->where('model_type', get_class($this));
if ($obj->count() > 0) {
$obj->update(['attribute_data' => $data->toJson()]);
continue;
}
DB::table('rainlab_translate_attributes')
->insert([
'locale' => $key,
'model_id' => $this->id,
'model_type' => get_class($this),
'attribute_data' => $data->toJson(),
]
);
}
}
public function afterSave()
{
$this->setTranslatableFields();
}
}
This worked for me, almost like @tobias-kuendig but I had to remove the returns or only the first language was saved
EDITED: index fields (for example slugs) now work
<?php namespace Vendor\Plugin\Traits;
use Illuminate\Support\Facades\DB;
/**
* @see https://github.com/rainlab/translate-plugin/issues/209#issuecomment-362088300
*/
trait TranslatableRelation
{
/**
* This is a temporary fix until
* https://github.com/rainlab/translate-plugin/issues/209
* is resolved.
*/
protected function setTranslatableFields()
{
if ( ! post('RLTranslate')) {
return;
}
$translatableIndexes = [];
$translatableAttributes = [];
foreach (post('RLTranslate') as $key => $value) {
foreach ($this->translatable as $translatableAttribute) {
if (isset($translatableAttribute['index'])) {
$translatableIndexes[$translatableAttribute[0]] = '';
$translatableAttributes[$translatableAttribute[0]] = '';
} else {
$translatableAttributes[$translatableAttribute] = '';
}
}
$data = collect($value)->intersectByKeys($translatableAttributes);
$indexes = collect($value)->intersectByKeys($translatableIndexes);
$obj = DB::table('rainlab_translate_attributes')
->where('locale', $key)
->where('model_id', $this->id)
->where('model_type', get_class($this->model));
if ($obj->count() > 0) {
$obj->update(['attribute_data' => $data->toJson()]);
} else {
DB::table('rainlab_translate_attributes')
->insert([
'locale' => $key,
'model_id' => $this->id,
'model_type' => get_class($this->model),
'attribute_data' => $data->toJson(),
]
);
}
foreach ($indexes as $item => $value) {
$obj = DB::table('rainlab_translate_indexes')
->where('locale', $key)
->where('model_id', $this->id)
->where('model_type', get_class($this->model))
->where('item', $item);
if ($obj->count() > 0) {
$obj->update(['value' => $value]);
} else {
DB::table('rainlab_translate_indexes')
->insert([
'locale' => $key,
'model_id' => $this->id,
'model_type' => get_class($this->model),
'item' => $item,
'value' => $value,
]
);
}
}
}
}
public function afterSave()
{
$this->setTranslatableFields();
}
}
how to implement the temporary fix, new trait ?
@sanketr43 If you are not going to translate index fields/slugs, use this trait: https://github.com/rainlab/translate-plugin/issues/209#issuecomment-400189329
Just copy it to your plugin sources, e.g. in a subfolder classes, then use it in your model.
This worked for me, almost like @tobias-kuendig but I had to remove the returns or only the first language was saved
EDITED: index fields (for example slugs) now work
<?php namespace Vendor\Plugin\Traits; use Illuminate\Support\Facades\DB; /** * @see https://github.com/rainlab/translate-plugin/issues/209#issuecomment-362088300 */ trait TranslatableRelation { /** * This is a temporary fix until * https://github.com/rainlab/translate-plugin/issues/209 * is resolved. */ protected function setTranslatableFields() { if ( ! post('RLTranslate')) { return; } $translatableIndexes = []; $translatableAttributes = []; foreach (post('RLTranslate') as $key => $value) { foreach ($this->translatable as $translatableAttribute) { if (isset($translatableAttribute['index'])) { $translatableIndexes[$translatableAttribute[0]] = ''; $translatableAttributes[$translatableAttribute[0]] = ''; } else { $translatableAttributes[$translatableAttribute] = ''; } } $data = collect($value)->intersectByKeys($translatableAttributes); $indexes = collect($value)->intersectByKeys($translatableIndexes); $obj = DB::table('rainlab_translate_attributes') ->where('locale', $key) ->where('model_id', $this->id) ->where('model_type', get_class($this->model)); if ($obj->count() > 0) { $obj->update(['attribute_data' => $data->toJson()]); } else { DB::table('rainlab_translate_attributes') ->insert([ 'locale' => $key, 'model_id' => $this->id, 'model_type' => get_class($this->model), 'attribute_data' => $data->toJson(), ] ); } foreach ($indexes as $item => $value) { $obj = DB::table('rainlab_translate_indexes') ->where('locale', $key) ->where('model_id', $this->id) ->where('model_type', get_class($this->model)) ->where('item', $item); if ($obj->count() > 0) { $obj->update(['value' => $value]); } else { DB::table('rainlab_translate_indexes') ->insert([ 'locale' => $key, 'model_id' => $this->id, 'model_type' => get_class($this->model), 'item' => $item, 'value' => $value, ] ); } } } } public function afterSave() { $this->setTranslatableFields(); } }
Thank you for you help @mariavilaro and @tobias-kuendig !
@jimcottrell @mariavilaro @munxar @osmanzeki @datune @tobias-kuendig is there an official recommended fix that we can merge in here? I keep seeing updates on this PR but I don't have time to dig into it myself. If someone can submit a PR that clearly describes the issue and explains how the changes resolve the issue without breaking anything else I'd be more than happy to merge the fix in.
Does anyone have solution to morphOne relation?
@mplodowski you could try Forum/Slack/Stackoverflow might find someone who already did it.
@mplodowski @jimcottrell @mariavilaro @munxar @osmanzeki @datune @tobias-kuendig could you guys test https://github.com/octobercms/october/pull/4193 to check if it fixes the original issue and doesn't break anything else? I'm partial to that solution if it works because it seems significantly simpler.
My usage of models with relations so far does not indicate any issues, but
this is not thorough testing.
On Wed, Mar 13, 2019 at 10:27 PM Luke Towers notifications@github.com
wrote:
@mplodowski https://github.com/mplodowski @jimcottrell
https://github.com/jimcottrell @mariavilaro
https://github.com/mariavilaro @munxar https://github.com/munxar
@osmanzeki https://github.com/osmanzeki @datune
https://github.com/datune @tobias-kuendig
https://github.com/tobias-kuendig could you guys test
octobercms/october#4193 https://github.com/octobercms/october/pull/4193
to check if it fixes the original issue and doesn't break anything else?
I'm partial to that solution if it works because it seems significantly
simpler.—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/rainlab/translate-plugin/issues/209#issuecomment-472679802,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AB65vsxWfOABtEQmrJl0GPEjiOfXTuf5ks5vWbOTgaJpZM4Lbmdz
.
--
Marc Jauvin
Register4less, Inc.
514-905-6500 x403
@mjauvin did the PR work for you then?
Yes, beautifully, much more elegant than what I did! :)
On Wed, Mar 13, 2019 at 10:43 PM Luke Towers notifications@github.com
wrote:
@mjauvin https://github.com/mjauvin did the PR work for you then?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/rainlab/translate-plugin/issues/209#issuecomment-472683009,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AB65vqyT5DvfWoZUaoXU3BSdJu99p3Jfks5vWbdugaJpZM4Lbmdz
.
--
Marc
Could you comment on the PR?
I've been able to test it right now and it works wonderfully, very nice!
It seems like this problem still exists for everything that goes through onRelationManageCreate, onRelationManagePivotCreate and onRelationManagePivotUpdate.
You can test this behaviour on our Mall demo website (login with demo/demo). Translations for property names are not saved correctly (onRelationManagePivotUpdate, https://mall.offline.swiss/backend/offline/mall/propertygroups/update/1).
When you create a new brand, its translated name is not saved as well (onRelationManageCreate, https://mall.offline.swiss/backend/offline/mall/products/update/6 -> Description -> Create Brand).
After a really quick look at this problem, it seems like similar bugfixes to @alxy's (https://github.com/octobercms/october/pull/4193) work for other methods as well:
https://github.com/OFFLINE-GmbH/october/commit/f9d8930d6b385be383c92ed33e27d438a6de8f8a
Naively replacing the $hydratedModel in the onRelationManagePivotUpdate method does not work though:
https://github.com/OFFLINE-GmbH/october/blob/f9d8930d6b385be383c92ed33e27d438a6de8f8a/modules/backend/behaviors/RelationController.php#L1354
Looking at this problem from the other end, I noticed that $this->translatableAttributes is empty in those error cases, which leads to $this->storeTranslatableData() being never called. I feel like this is the problem that needs a fix.
@tobias-kuendig Just to be sure: You replaced the $hydratedModel = $this->relationObject->where($foreignKeyName, $this->manageId)->first(); with $hydratedModel = $this->pivotWidget->model; and it doesnt work?
Looks like you're on to something! A quick test with this change seems to work:
https://github.com/OFFLINE-GmbH/october/commit/5cc91dcde4b3e2dfe20933137d8de718f837a3ad
I must have used $this->manageWidget instead of $this->pivotWidget!
https://github.com/octobercms/october/pull/4822
Looks like this is all that's needed to fix this. I'll do some testing and submit a PR.
@tobias-kuendig is #520 a duplicate of this one?
It looks like in #520 the MLText widget is not loaded (so no language selector is displayed). This issue is about the translated values from the MLText widget not being stored in the database.
@tobias-kuendig @LukeTowers I confirm the 3rd change (to onRelationPivotUpdate) does solve the problem when updating a Pivot relation in a popup widget.
I could not reproduce the one for onRelationManageCreate() though, this works for me with or without the fix when creating a brand from the product's description (I'm talking about the change below here):
https://github.com/octobercms/october/pull/4822/files#diff-63fc4fc41aa256f8d5bcfe7a37245ecfR1108-R1110
The procedure to reproduce you wrote was this:
"When you create a new brand, its translated name is not saved as well (onRelationManageCreate, https://mall.offline.swiss/backend/offline/mall/products/update/6 -> Description -> Create Brand)."
Also, the 2nd change (to onRelationManageUpdate) also fixes the issue when updating a relation model from a Popup.
So I confirm this issue is resolved by https://github.com/octobercms/october/pull/4822/files#
Most helpful comment
I had to call the
setTranslatableFieldsinafterSaveto make it work with build 435. Maybe the method's name changed internally?