Skip to content

Commit c39028e

Browse files
committed
bugfix: loading all translations of a model as a collection
1 parent 105c5be commit c39028e

File tree

2 files changed

+88
-14
lines changed

2 files changed

+88
-14
lines changed

src/Traits/TranslatableTrait.php

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,25 @@
22

33
namespace Jetcod\Laravel\Translation\Traits;
44

5-
use Illuminate\Database\Eloquent\Model;
65
use Illuminate\Database\Eloquent\Relations\MorphMany;
76
use Illuminate\Database\Eloquent\Relations\MorphOne;
7+
use Illuminate\Support\Collection;
88
use Jetcod\Laravel\Translation\Models\Translation;
99

1010
trait TranslatableTrait
1111
{
12-
private $cachedModel;
12+
private $cachedTranslationModels;
1313

1414
public function __get($key)
1515
{
1616
if ($this->isRelation($key)) {
1717
return $this->getRelationValue($key);
1818
}
1919

20-
// Check if the attribute is translatable
21-
if ($translation = $this->getTranslation($key)) {
22-
return $translation;
20+
// Check if the attribute translation exists
21+
$translation = $this->getTranslation($key);
22+
if ($translation instanceof Translation) {
23+
return $translation->value;
2324
}
2425

2526
// Fallback to the default behavior
@@ -37,9 +38,12 @@ public function translations(): MorphMany
3738
}
3839

3940
/**
40-
* Returns translatable attribute(s).
41+
* Retrieves the list of attributes that are translatable for the current model.
4142
*
42-
* @return null|array|string
43+
* If the `TRANSLATABLE_ATTRIBUTES` constant is defined on the model, it will be returned.
44+
* Otherwise, `null` will be returned, indicating that all attributes are translatable.
45+
*
46+
* @return null|array the list of translatable attributes, or `null` if all attributes are translatable
4347
*/
4448
protected function getTranslatableAttributes()
4549
{
@@ -50,19 +54,31 @@ protected function getTranslatableAttributes()
5054
return null;
5155
}
5256

53-
private function getTranslation(string $key): ?string
57+
/**
58+
* Retrieves the translation for the given attribute key, if the attribute is translatable.
59+
*
60+
* @param string $key the attribute key to retrieve the translation for
61+
*
62+
* @return null|Translation the translation model, or null if the attribute is not translatable
63+
*/
64+
private function getTranslation(string $key): ?Translation
5465
{
5566
if ($this->isTranslatableAttribute($key)) {
56-
$model = $this->getCachedModel();
67+
$collection = $this->getCachedTranslations();
5768

58-
if ($model instanceof Model) {
59-
return $key == $model->key ? $model->value : null;
60-
}
69+
return $collection->firstWhere('key', $key);
6170
}
6271

6372
return null;
6473
}
6574

75+
/**
76+
* Determines whether the given attribute key is a translatable attribute.
77+
*
78+
* @param string $key the attribute key to check
79+
*
80+
* @return bool `true` if the attribute is translatable, `false` otherwise
81+
*/
6682
private function isTranslatableAttribute(string $key): bool
6783
{
6884
$translatables = $this->getTranslatableAttributes();
@@ -74,8 +90,13 @@ private function isTranslatableAttribute(string $key): bool
7490
return is_array($translatables) ? in_array($key, $translatables) : $key == $translatables;
7591
}
7692

77-
private function getCachedModel()
93+
/**
94+
* Retrieves the cached translation models for the current locale.
95+
*
96+
* @return Collection the collection of translation models
97+
*/
98+
private function getCachedTranslations(): Collection
7899
{
79-
return $this->cachedModel = $this->cachedModel ?: $this->translation()->locale(app()->getLocale())->first();
100+
return $this->cachedTranslationModels = $this->cachedTranslationModels ?: $this->translation()->locale(app()->getLocale())->get();
80101
}
81102
}

tests/TranslationModelTest.php

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,59 @@ public function testItReturnsOriginalTextWhenNoTranslationIsAvailable()
7979
$this->assertEquals('original text goes here', $post->name);
8080
}
8181

82+
public function testItTranslatesOnlyTranslatableAttributes()
83+
{
84+
$post = new class() extends Post {
85+
protected const TRANSLATABLE_ATTRIBUTES = 'name';
86+
};
87+
$post->id = 1;
88+
$post->name = 'original text goes here';
89+
$post->body = 'some text goes here';
90+
91+
$post->translation()->saveMany([
92+
new Translation([
93+
'locale' => 'fr_FR',
94+
'key' => 'name',
95+
'value' => 'un texte va ici',
96+
]),
97+
]);
98+
99+
app()->setLocale('fr_FR');
100+
$this->assertEquals('un texte va ici', $post->name);
101+
$this->assertEquals('some text goes here', $post->body);
102+
}
103+
104+
public function testItTranslatesAllAttributesIfNoTranslatableAttributesAreDefined()
105+
{
106+
$post = new class() extends Post {
107+
protected function getTranslatableAttributes()
108+
{
109+
return null;
110+
}
111+
};
112+
$post->id = 1;
113+
$post->name = 'some text goes here';
114+
$post->body = 'another text goes here';
115+
116+
app()->setLocale('fr_FR');
117+
$post->translation()->saveMany([
118+
new Translation([
119+
'locale' => 'fr_FR',
120+
'key' => 'name',
121+
'value' => 'un texte va ici',
122+
]),
123+
new Translation([
124+
'locale' => 'fr_FR',
125+
'key' => 'body',
126+
'value' => 'un autre texte va ici',
127+
]),
128+
]);
129+
130+
app()->setLocale('fr_FR');
131+
$this->assertEquals('un texte va ici', $post->name);
132+
$this->assertEquals('un autre texte va ici', $post->body);
133+
}
134+
82135
public function testItReturnsTranslationsCollection()
83136
{
84137
$post = new Post();

0 commit comments

Comments
 (0)