Skip to content

Commit 718767e

Browse files
committed
feat: add locale-specific translation functionality with tests
1 parent 7fb2eae commit 718767e

File tree

2 files changed

+88
-11
lines changed

2 files changed

+88
-11
lines changed

src/Traits/TranslatableTrait.php

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ trait TranslatableTrait
1111
{
1212
private $cachedTranslationModels;
1313

14+
private $locale;
15+
1416
public function __get($key)
1517
{
1618
if ($this->isRelation($key)) {
@@ -37,6 +39,23 @@ public function translations(): MorphMany
3739
return $this->morphMany(Translation::class, 'translatable');
3840
}
3941

42+
/**
43+
* Sets the locale for the current model instance.
44+
*
45+
* This method allows you to specify a locale for the model, which will be used when retrieving
46+
* translated attributes.
47+
*
48+
* @param string $locale the locale to set for the model
49+
*
50+
* @return $this the current model instance, for method chaining
51+
*/
52+
public function withLocale(string $locale): self
53+
{
54+
$this->locale = $locale;
55+
56+
return $this;
57+
}
58+
4059
/**
4160
* Retrieves the list of attributes that are translatable for the current model.
4261
*
@@ -54,6 +73,15 @@ protected function getTranslatableAttributes()
5473
return null;
5574
}
5675

76+
private function popTranslationLocale(): string
77+
{
78+
$locale = $this->locale ?? app()->getLocale();
79+
80+
$this->locale = null; // reset the current locale
81+
82+
return $locale;
83+
}
84+
5785
/**
5886
* Retrieves the translation for the given attribute key, if the attribute is translatable.
5987
*
@@ -103,7 +131,7 @@ private function getCachedTranslations(): Collection
103131
}
104132

105133
// If not cached or not found for current locale, fetch and cache translations
106-
return $this->cachedTranslationModels = $this->fetchAndCacheTranslations(app()->getLocale());
134+
return $this->cachedTranslationModels = $this->fetchTranslations($this->popTranslationLocale());
107135
}
108136

109137
/**
@@ -113,19 +141,19 @@ private function getCachedTranslations(): Collection
113141
*/
114142
private function hasTranslationsForCurrentLocale(): bool
115143
{
116-
$locale = app()->getLocale();
144+
$locale = $this->popTranslationLocale();
117145

118146
return null !== $this->cachedTranslationModels->firstWhere('locale', $locale);
119147
}
120148

121149
/**
122-
* Fetches and caches the translation models for the given locale.
150+
* Fetches the translation models for the given locale.
123151
*
124152
* @param string $locale the locale to fetch translations for
125153
*
126154
* @return Collection the collection of translation models
127155
*/
128-
private function fetchAndCacheTranslations(string $locale): Collection
156+
private function fetchTranslations(string $locale): Collection
129157
{
130158
return $this->translation()->locale($locale)->get();
131159
}

tests/TranslationModelTest.php

Lines changed: 56 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,6 @@
99
use Jetcod\Laravel\Translation\Test\Stubs\Post;
1010
use Orchestra\Testbench\TestCase as PHPUnitTestCase;
1111

12-
/**
13-
* @internal
14-
*
15-
* @coversNothing
16-
*/
1712
class TranslationModelTest extends PHPUnitTestCase
1813
{
1914
use RefreshDatabase;
@@ -81,7 +76,7 @@ public function testItReturnsOriginalTextWhenNoTranslationIsAvailable()
8176

8277
public function testItTranslatesOnlyTranslatableAttributes()
8378
{
84-
$post = new class() extends Post {
79+
$post = new class extends Post {
8580
protected const TRANSLATABLE_ATTRIBUTES = 'name';
8681
};
8782
$post->id = 1;
@@ -129,7 +124,7 @@ public function testItTranslatesAttributesImmediatelyAfterSwitchingLocale()
129124

130125
public function testItTranslatesAllAttributesIfNoTranslatableAttributesAreDefined()
131126
{
132-
$post = new class() extends Post {
127+
$post = new class extends Post {
133128
protected function getTranslatableAttributes()
134129
{
135130
return null;
@@ -190,6 +185,60 @@ public function testItReturnsTranslationsCollection()
190185
}
191186
}
192187

188+
public function testItCanGetTranslationForDefinedLocale()
189+
{
190+
$post = new Post();
191+
$post->id = 1;
192+
$post->name = 'original text goes here';
193+
194+
$post->translation()->saveMany([
195+
new Translation([
196+
'locale' => 'fr_FR',
197+
'key' => 'name',
198+
'value' => 'un texte va ici',
199+
]),
200+
]);
201+
202+
$this->assertEquals('un texte va ici', $post->withLocale('fr_FR')->name);
203+
}
204+
205+
public function testItResetsDefinedLocaleForEachRequest()
206+
{
207+
$post = new Post();
208+
$post->id = 1;
209+
$post->name = 'original text goes here';
210+
211+
$post->translation()->saveMany([
212+
new Translation([
213+
'locale' => 'fr_FR',
214+
'key' => 'name',
215+
'value' => 'un texte va ici',
216+
]),
217+
]);
218+
219+
$this->assertEquals('un texte va ici', $post->withLocale('fr_FR')->name);
220+
$this->assertEquals('original text goes here', $post->name);
221+
}
222+
223+
public function testChangingApplicationLocaleDoesNotAffectTranslationIfLocaleIsSet()
224+
{
225+
$post = new Post();
226+
$post->id = 1;
227+
$post->name = 'original text goes here';
228+
229+
$post->translation()->saveMany([
230+
new Translation([
231+
'locale' => 'fr_FR',
232+
'key' => 'name',
233+
'value' => 'un texte va ici',
234+
]),
235+
]);
236+
237+
app()->setLocale('ja_JP');
238+
$this->assertEquals('un texte va ici', $post->withLocale('fr_FR')->name);
239+
$this->assertEquals('ja_JP', app()->getLocale());
240+
}
241+
193242
protected function getPackageProviders($app)
194243
{
195244
return [TranslationServiceProvider::class];

0 commit comments

Comments
 (0)