1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
use Dimsav\Translatable\Test\Model\Food; |
4
|
|
|
use Dimsav\Translatable\Test\Model\Person; |
5
|
|
|
use Dimsav\Translatable\Test\Model\Country; |
6
|
|
|
use Dimsav\Translatable\Test\Model\CountryStrict; |
7
|
|
|
use Dimsav\Translatable\Test\Model\CountryWithCustomLocaleKey; |
8
|
|
|
use Dimsav\Translatable\Test\Model\CountryWithCustomTranslationModel; |
9
|
|
|
|
10
|
|
|
class TranslatableTest extends TestsBase |
11
|
|
|
{ |
12
|
|
|
public function test_it_finds_the_default_translation_class() |
13
|
|
|
{ |
14
|
|
|
$country = new Country(); |
15
|
|
|
$this->assertEquals( |
16
|
|
|
'Dimsav\Translatable\Test\Model\CountryTranslation', |
17
|
|
|
$country->getTranslationModelNameDefault()); |
18
|
|
|
} |
19
|
|
|
|
20
|
|
|
public function test_it_finds_the_translation_class_with_namespace_set() |
21
|
|
|
{ |
22
|
|
|
$this->app->make('config')->set('translatable.translation_model_namespace', 'App\Models\Translations'); |
23
|
|
|
$country = new Country(); |
24
|
|
|
$this->assertEquals( |
25
|
|
|
'App\Models\Translations\CountryTranslation', |
26
|
|
|
$country->getTranslationModelNameDefault()); |
27
|
|
|
} |
28
|
|
|
|
29
|
|
|
public function test_it_finds_the_translation_class_with_suffix_set() |
30
|
|
|
{ |
31
|
|
|
App::make('config')->set('translatable.translation_suffix', 'Trans'); |
32
|
|
|
$country = new Country(); |
33
|
|
|
$this->assertEquals( |
34
|
|
|
'Dimsav\Translatable\Test\Model\CountryTrans', |
35
|
|
|
$country->getTranslationModelName()); |
36
|
|
|
} |
37
|
|
|
|
38
|
|
|
public function test_it_returns_custom_TranslationModelName() |
39
|
|
|
{ |
40
|
|
|
$country = new Country(); |
41
|
|
|
|
42
|
|
|
$this->assertEquals( |
43
|
|
|
$country->getTranslationModelNameDefault(), |
44
|
|
|
$country->getTranslationModelName() |
45
|
|
|
); |
46
|
|
|
|
47
|
|
|
$country->translationModel = 'MyAwesomeCountryTranslation'; |
48
|
|
|
$this->assertEquals( |
49
|
|
|
'MyAwesomeCountryTranslation', |
50
|
|
|
$country->getTranslationModelName() |
51
|
|
|
); |
52
|
|
|
} |
53
|
|
|
|
54
|
|
|
public function test_it_returns_relation_key() |
55
|
|
|
{ |
56
|
|
|
$country = new Country(); |
57
|
|
|
$this->assertEquals('country_id', $country->getRelationKey()); |
58
|
|
|
|
59
|
|
|
$country->translationForeignKey = 'my_awesome_key'; |
60
|
|
|
$this->assertEquals('my_awesome_key', $country->getRelationKey()); |
61
|
|
|
} |
62
|
|
|
|
63
|
|
|
public function test_it_returns_the_translation() |
64
|
|
|
{ |
65
|
|
|
/** @var Country $country */ |
66
|
|
|
$country = Country::whereCode('gr')->first(); |
67
|
|
|
|
68
|
|
|
$englishTranslation = $country->translate('el'); |
69
|
|
|
$this->assertEquals('Ελλάδα', $englishTranslation->name); |
70
|
|
|
|
71
|
|
|
$englishTranslation = $country->translate('en'); |
72
|
|
|
$this->assertEquals('Greece', $englishTranslation->name); |
73
|
|
|
|
74
|
|
|
$this->app->setLocale('el'); |
75
|
|
|
$englishTranslation = $country->translate(); |
76
|
|
|
$this->assertEquals('Ελλάδα', $englishTranslation->name); |
77
|
|
|
|
78
|
|
|
$this->app->setLocale('en'); |
79
|
|
|
$englishTranslation = $country->translate(); |
80
|
|
|
$this->assertEquals('Greece', $englishTranslation->name); |
81
|
|
|
} |
82
|
|
|
|
83
|
|
|
public function test_it_returns_the_translation_with_accessor() |
84
|
|
|
{ |
85
|
|
|
/** @var Country $country */ |
86
|
|
|
$country = Country::whereCode('gr')->first(); |
87
|
|
|
|
88
|
|
|
$this->assertEquals('Ελλάδα', $country->{'name:el'}); |
89
|
|
|
$this->assertEquals('Greece', $country->{'name:en'}); |
90
|
|
|
} |
91
|
|
|
|
92
|
|
|
public function test_it_returns_null_when_the_locale_doesnt_exist() |
93
|
|
|
{ |
94
|
|
|
/** @var Country $country */ |
95
|
|
|
$country = Country::whereCode('gr')->first(); |
96
|
|
|
|
97
|
|
|
$this->assertSame(null, $country->{'name:unknown-locale'}); |
98
|
|
|
} |
99
|
|
|
|
100
|
|
View Code Duplication |
public function test_it_saves_translations() |
|
|
|
|
101
|
|
|
{ |
102
|
|
|
$country = Country::whereCode('gr')->first(); |
103
|
|
|
|
104
|
|
|
$country->name = '1234'; |
105
|
|
|
$country->save(); |
106
|
|
|
|
107
|
|
|
$country = Country::whereCode('gr')->first(); |
108
|
|
|
$this->assertEquals('1234', $country->name); |
109
|
|
|
} |
110
|
|
|
|
111
|
|
|
public function test_it_saves_translations_with_mutator() |
112
|
|
|
{ |
113
|
|
|
$country = Country::whereCode('gr')->first(); |
114
|
|
|
|
115
|
|
|
$country->{'name:en'} = '1234'; |
116
|
|
|
$country->{'name:el'} = '5678'; |
117
|
|
|
$country->save(); |
118
|
|
|
|
119
|
|
|
$country = Country::whereCode('gr')->first(); |
120
|
|
|
|
121
|
|
|
$this->app->setLocale('en'); |
122
|
|
|
$translation = $country->translate(); |
123
|
|
|
$this->assertEquals('1234', $translation->name); |
124
|
|
|
|
125
|
|
|
$this->app->setLocale('el'); |
126
|
|
|
$translation = $country->translate(); |
127
|
|
|
$this->assertEquals('5678', $translation->name); |
128
|
|
|
} |
129
|
|
|
|
130
|
|
|
public function test_it_does_not_lazy_load_translations_when_updating_non_translated_attributes() |
131
|
|
|
{ |
132
|
|
|
DB::enableQueryLog(); |
133
|
|
|
|
134
|
|
|
$country = Country::create(['code' => 'be']); |
135
|
|
|
$this->assertFalse($country->relationLoaded('translations')); |
136
|
|
|
$this->assertCount(1, DB::getQueryLog()); |
137
|
|
|
|
138
|
|
|
DB::flushQueryLog(); |
139
|
|
|
|
140
|
|
|
$country->update(['code' => 'de']); |
141
|
|
|
$this->assertFalse($country->relationLoaded('translations')); |
142
|
|
|
$this->assertCount(1, DB::getQueryLog()); |
143
|
|
|
|
144
|
|
|
DB::flushQueryLog(); |
145
|
|
|
|
146
|
|
|
$country->update(['name' => 'Germany']); |
147
|
|
|
$this->assertTrue($country->relationLoaded('translations')); |
148
|
|
|
$this->assertCount(2, DB::getQueryLog()); |
149
|
|
|
|
150
|
|
|
DB::disableQueryLog(); |
151
|
|
|
} |
152
|
|
|
|
153
|
|
|
public function test_it_uses_default_locale_to_return_translations() |
154
|
|
|
{ |
155
|
|
|
$country = Country::whereCode('gr')->first(); |
156
|
|
|
|
157
|
|
|
$country->translate('el')->name = 'abcd'; |
158
|
|
|
|
159
|
|
|
$this->app->setLocale('el'); |
160
|
|
|
$this->assertEquals('abcd', $country->name); |
161
|
|
|
$country->save(); |
162
|
|
|
|
163
|
|
|
$country = Country::whereCode('gr')->first(); |
164
|
|
|
$this->assertEquals('abcd', $country->translate('el')->name); |
165
|
|
|
} |
166
|
|
|
|
167
|
|
|
public function test_it_creates_translations() |
168
|
|
|
{ |
169
|
|
|
$country = new Country(); |
170
|
|
|
$country->code = 'be'; |
171
|
|
|
$country->save(); |
172
|
|
|
|
173
|
|
|
$country = Country::whereCode('be')->first(); |
174
|
|
|
$country->name = 'Belgium'; |
175
|
|
|
$country->save(); |
176
|
|
|
|
177
|
|
|
$country = Country::whereCode('be')->first(); |
178
|
|
|
$this->assertEquals('Belgium', $country->name); |
179
|
|
|
} |
180
|
|
|
|
181
|
|
View Code Duplication |
public function test_it_creates_translations_using_the_shortcut() |
|
|
|
|
182
|
|
|
{ |
183
|
|
|
$country = new Country(); |
184
|
|
|
$country->code = 'be'; |
185
|
|
|
$country->name = 'Belgium'; |
186
|
|
|
$country->save(); |
187
|
|
|
|
188
|
|
|
$country = Country::whereCode('be')->first(); |
189
|
|
|
$this->assertEquals('Belgium', $country->name); |
190
|
|
|
} |
191
|
|
|
|
192
|
|
|
public function test_it_creates_translations_using_mass_assignment() |
193
|
|
|
{ |
194
|
|
|
$data = [ |
195
|
|
|
'code' => 'be', |
196
|
|
|
'name' => 'Belgium', |
197
|
|
|
]; |
198
|
|
|
$country = Country::create($data); |
199
|
|
|
$this->assertEquals('be', $country->code); |
200
|
|
|
$this->assertEquals('Belgium', $country->name); |
201
|
|
|
} |
202
|
|
|
|
203
|
|
|
public function test_it_creates_translations_using_mass_assignment_and_locales() |
204
|
|
|
{ |
205
|
|
|
$data = [ |
206
|
|
|
'code' => 'be', |
207
|
|
|
'en' => ['name' => 'Belgium'], |
208
|
|
|
'fr' => ['name' => 'Belgique'], |
209
|
|
|
]; |
210
|
|
|
$country = Country::create($data); |
211
|
|
|
$this->assertEquals('be', $country->code); |
212
|
|
|
$this->assertEquals('Belgium', $country->translate('en')->name); |
213
|
|
|
$this->assertEquals('Belgique', $country->translate('fr')->name); |
214
|
|
|
|
215
|
|
|
$country = Country::whereCode('be')->first(); |
216
|
|
|
$this->assertEquals('Belgium', $country->translate('en')->name); |
217
|
|
|
$this->assertEquals('Belgique', $country->translate('fr')->name); |
218
|
|
|
} |
219
|
|
|
|
220
|
|
|
public function test_it_skips_mass_assignment_if_attributes_non_fillable() |
221
|
|
|
{ |
222
|
|
|
$this->expectException(Illuminate\Database\Eloquent\MassAssignmentException::class); |
223
|
|
|
$data = [ |
224
|
|
|
'code' => 'be', |
225
|
|
|
'en' => ['name' => 'Belgium'], |
226
|
|
|
'fr' => ['name' => 'Belgique'], |
227
|
|
|
]; |
228
|
|
|
$country = CountryStrict::create($data); |
229
|
|
|
$this->assertEquals('be', $country->code); |
230
|
|
|
$this->assertNull($country->translate('en')); |
231
|
|
|
$this->assertNull($country->translate('fr')); |
232
|
|
|
} |
233
|
|
|
|
234
|
|
|
public function test_it_returns_if_object_has_translation() |
235
|
|
|
{ |
236
|
|
|
$country = Country::find(1); |
237
|
|
|
$this->assertTrue($country->hasTranslation('en')); |
238
|
|
|
$this->assertFalse($country->hasTranslation('abc')); |
239
|
|
|
} |
240
|
|
|
|
241
|
|
|
public function test_it_returns_default_translation() |
242
|
|
|
{ |
243
|
|
|
App::make('config')->set('translatable.fallback_locale', 'de'); |
244
|
|
|
|
245
|
|
|
$country = Country::find(1); |
246
|
|
|
$this->assertSame($country->getTranslation('ch', true)->name, 'Griechenland'); |
247
|
|
|
$this->assertSame($country->translateOrDefault('ch')->name, 'Griechenland'); |
248
|
|
|
$this->assertSame($country->getTranslation('ch', false), null); |
249
|
|
|
|
250
|
|
|
$this->app->setLocale('ch'); |
251
|
|
|
$this->assertSame($country->translateOrDefault()->name, 'Griechenland'); |
252
|
|
|
} |
253
|
|
|
|
254
|
|
|
public function test_fallback_option_in_config_overrides_models_fallback_option() |
255
|
|
|
{ |
256
|
|
|
App::make('config')->set('translatable.fallback_locale', 'de'); |
257
|
|
|
|
258
|
|
|
$country = Country::find(1); |
259
|
|
|
$this->assertEquals($country->getTranslation('ch', true)->locale, 'de'); |
260
|
|
|
|
261
|
|
|
$country->useTranslationFallback = false; |
262
|
|
|
$this->assertEquals($country->getTranslation('ch', true)->locale, 'de'); |
263
|
|
|
|
264
|
|
|
$country->useTranslationFallback = true; |
265
|
|
|
$this->assertEquals($country->getTranslation('ch')->locale, 'de'); |
266
|
|
|
|
267
|
|
|
$country->useTranslationFallback = false; |
268
|
|
|
$this->assertSame($country->getTranslation('ch'), null); |
269
|
|
|
} |
270
|
|
|
|
271
|
|
|
public function test_configuration_defines_if_fallback_is_used() |
272
|
|
|
{ |
273
|
|
|
App::make('config')->set('translatable.fallback_locale', 'de'); |
274
|
|
|
App::make('config')->set('translatable.use_fallback', true); |
275
|
|
|
|
276
|
|
|
$country = Country::find(1); |
277
|
|
|
$this->assertEquals($country->getTranslation('ch')->locale, 'de'); |
278
|
|
|
} |
279
|
|
|
|
280
|
|
|
public function test_useTranslationFallback_overrides_configuration() |
281
|
|
|
{ |
282
|
|
|
App::make('config')->set('translatable.fallback_locale', 'de'); |
283
|
|
|
App::make('config')->set('translatable.use_fallback', true); |
284
|
|
|
$country = Country::find(1); |
285
|
|
|
$country->useTranslationFallback = false; |
286
|
|
|
$this->assertSame($country->getTranslation('ch'), null); |
287
|
|
|
} |
288
|
|
|
|
289
|
|
|
public function test_it_returns_null_if_fallback_is_not_defined() |
290
|
|
|
{ |
291
|
|
|
App::make('config')->set('translatable.fallback_locale', 'ch'); |
292
|
|
|
|
293
|
|
|
$country = Country::find(1); |
294
|
|
|
$this->assertSame($country->getTranslation('pl', true), null); |
295
|
|
|
} |
296
|
|
|
|
297
|
|
|
public function test_it_fills_a_non_default_language_with_fallback_set() |
298
|
|
|
{ |
299
|
|
|
App::make('config')->set('translatable.fallback_locale', 'en'); |
300
|
|
|
|
301
|
|
|
$country = new Country(); |
302
|
|
|
$country->fill([ |
303
|
|
|
'code' => 'gr', |
304
|
|
|
'en' => ['name' => 'Greece'], |
305
|
|
|
'de' => ['name' => 'Griechenland'], |
306
|
|
|
]); |
307
|
|
|
|
308
|
|
|
$this->assertEquals($country->translate('en')->name, 'Greece'); |
309
|
|
|
} |
310
|
|
|
|
311
|
|
|
public function test_it_creates_a_new_translation() |
312
|
|
|
{ |
313
|
|
|
App::make('config')->set('translatable.fallback_locale', 'en'); |
314
|
|
|
|
315
|
|
|
$country = Country::create(['code' => 'gr']); |
316
|
|
|
$country->getNewTranslation('en')->name = 'Greece'; |
317
|
|
|
$country->save(); |
318
|
|
|
|
319
|
|
|
$this->assertEquals($country->translate('en')->name, 'Greece'); |
320
|
|
|
} |
321
|
|
|
|
322
|
|
|
public function test_the_locale_key_is_locale_by_default() |
323
|
|
|
{ |
324
|
|
|
$country = Country::find(1); |
325
|
|
|
$this->assertEquals($country->getLocaleKey(), 'locale'); |
326
|
|
|
} |
327
|
|
|
|
328
|
|
|
public function test_the_locale_key_can_be_overridden_in_configuration() |
329
|
|
|
{ |
330
|
|
|
App::make('config')->set('translatable.locale_key', 'language_id'); |
331
|
|
|
|
332
|
|
|
$country = Country::find(1); |
333
|
|
|
$this->assertEquals($country->getLocaleKey(), 'language_id'); |
334
|
|
|
} |
335
|
|
|
|
336
|
|
|
public function test_the_locale_key_can_be_customized_per_model() |
337
|
|
|
{ |
338
|
|
|
$country = CountryWithCustomLocaleKey::find(1); |
339
|
|
|
$this->assertEquals($country->getLocaleKey(), 'language_id'); |
340
|
|
|
} |
341
|
|
|
|
342
|
|
|
public function test_the_translation_model_can_be_customized() |
343
|
|
|
{ |
344
|
|
|
$country = CountryWithCustomTranslationModel::create([ |
345
|
|
|
'code' => 'es', |
346
|
|
|
'name:en' => 'Spain', |
347
|
|
|
'name:de' => 'Spanien', |
348
|
|
|
]); |
349
|
|
|
$this->assertTrue($country->exists()); |
350
|
|
|
$this->assertEquals($country->translate('en')->name, 'Spain'); |
351
|
|
|
$this->assertEquals($country->translate('de')->name, 'Spanien'); |
352
|
|
|
} |
353
|
|
|
|
354
|
|
|
public function test_it_reads_the_configuration() |
355
|
|
|
{ |
356
|
|
|
$this->assertEquals(App::make('config')->get('translatable.translation_suffix'), 'Translation'); |
357
|
|
|
} |
358
|
|
|
|
359
|
|
|
public function test_getting_translation_does_not_create_translation() |
360
|
|
|
{ |
361
|
|
|
$country = Country::with('translations')->find(1); |
|
|
|
|
362
|
|
|
$translation = $country->getTranslation('abc', false); |
363
|
|
|
$this->assertSame($translation, null); |
364
|
|
|
} |
365
|
|
|
|
366
|
|
|
public function test_getting_translated_field_does_not_create_translation() |
367
|
|
|
{ |
368
|
|
|
$this->app->setLocale('en'); |
369
|
|
|
$country = new Country(['code' => 'pl']); |
370
|
|
|
$country->save(); |
371
|
|
|
|
372
|
|
|
$country->name; |
373
|
|
|
|
374
|
|
|
$this->assertSame($country->getTranslation('en'), null); |
375
|
|
|
} |
376
|
|
|
|
377
|
|
|
public function test_if_locales_are_not_defined_throw_exception() |
378
|
|
|
{ |
379
|
|
|
$this->expectException(Dimsav\Translatable\Exception\LocalesNotDefinedException::class); |
380
|
|
|
|
381
|
|
|
$this->app->config->set('translatable.locales', []); |
382
|
|
|
new Country(['code' => 'pl']); |
383
|
|
|
} |
384
|
|
|
|
385
|
|
|
public function test_it_has_methods_that_return_always_a_translation() |
386
|
|
|
{ |
387
|
|
|
$country = Country::find(1)->first(); |
388
|
|
|
$this->assertSame('abc', $country->translateOrNew('abc')->locale); |
389
|
|
|
|
390
|
|
|
$this->app->setLocale('xyz'); |
391
|
|
|
$this->assertSame('xyz', $country->translateOrNew()->locale); |
392
|
|
|
} |
393
|
|
|
|
394
|
|
|
public function test_it_returns_if_attribute_is_translated() |
395
|
|
|
{ |
396
|
|
|
$country = new Country(); |
397
|
|
|
|
398
|
|
|
$this->assertTrue($country->isTranslationAttribute('name')); |
399
|
|
|
$this->assertFalse($country->isTranslationAttribute('some-field')); |
400
|
|
|
} |
401
|
|
|
|
402
|
|
|
public function test_config_overrides_apps_locale() |
403
|
|
|
{ |
404
|
|
|
$country = Country::find(1); |
405
|
|
|
App::make('config')->set('translatable.locale', 'de'); |
406
|
|
|
|
407
|
|
|
$this->assertSame('Griechenland', $country->name); |
408
|
|
|
} |
409
|
|
|
|
410
|
|
|
public function test_locales_as_array_keys_are_properly_detected() |
411
|
|
|
{ |
412
|
|
|
$this->app->config->set('translatable.locales', ['en' => ['US', 'GB']]); |
413
|
|
|
|
414
|
|
|
$data = [ |
415
|
|
|
'en' => ['name' => 'French fries'], |
416
|
|
|
'en-US' => ['name' => 'American french fries'], |
417
|
|
|
'en-GB' => ['name' => 'Chips'], |
418
|
|
|
]; |
419
|
|
|
$frenchFries = Food::create($data); |
420
|
|
|
|
421
|
|
|
$this->assertSame('French fries', $frenchFries->getTranslation('en')->name); |
422
|
|
|
$this->assertSame('Chips', $frenchFries->getTranslation('en-GB')->name); |
423
|
|
|
$this->assertSame('American french fries', $frenchFries->getTranslation('en-US')->name); |
424
|
|
|
} |
425
|
|
|
|
426
|
|
|
public function test_locale_separator_can_be_configured() |
427
|
|
|
{ |
428
|
|
|
$this->app->config->set('translatable.locales', ['en' => ['GB']]); |
429
|
|
|
$this->app->config->set('translatable.locale_separator', '_'); |
430
|
|
|
$data = [ |
431
|
|
|
'en_GB' => ['name' => 'Chips'], |
432
|
|
|
]; |
433
|
|
|
$frenchFries = Food::create($data); |
434
|
|
|
|
435
|
|
|
$this->assertSame('Chips', $frenchFries->getTranslation('en_GB')->name); |
436
|
|
|
} |
437
|
|
|
|
438
|
|
|
public function test_fallback_for_country_based_locales() |
439
|
|
|
{ |
440
|
|
|
$this->app->config->set('translatable.use_fallback', true); |
441
|
|
|
$this->app->config->set('translatable.fallback_locale', 'fr'); |
442
|
|
|
$this->app->config->set('translatable.locales', ['en' => ['US', 'GB'], 'fr']); |
443
|
|
|
$this->app->config->set('translatable.locale_separator', '-'); |
444
|
|
|
$data = [ |
445
|
|
|
'id' => 1, |
446
|
|
|
'fr' => ['name' => 'frites'], |
447
|
|
|
'en-GB' => ['name' => 'chips'], |
448
|
|
|
'en' => ['name' => 'french fries'], |
449
|
|
|
]; |
450
|
|
|
Food::create($data); |
451
|
|
|
$fries = Food::find(1); |
452
|
|
|
$this->assertSame('french fries', $fries->getTranslation('en-US')->name); |
453
|
|
|
} |
454
|
|
|
|
455
|
|
|
public function test_fallback_for_country_based_locales_with_no_base_locale() |
456
|
|
|
{ |
457
|
|
|
$this->app->config->set('translatable.use_fallback', true); |
458
|
|
|
$this->app->config->set('translatable.fallback_locale', 'en'); |
459
|
|
|
$this->app->config->set('translatable.locales', ['pt' => ['PT', 'BR'], 'en']); |
460
|
|
|
$this->app->config->set('translatable.locale_separator', '-'); |
461
|
|
|
$data = [ |
462
|
|
|
'id' => 1, |
463
|
|
|
'en' => ['name' => 'chips'], |
464
|
|
|
'pt-PT' => ['name' => 'batatas fritas'], |
465
|
|
|
]; |
466
|
|
|
Food::create($data); |
467
|
|
|
$fries = Food::find(1); |
468
|
|
|
$this->assertSame('chips', $fries->getTranslation('pt-BR')->name); |
469
|
|
|
} |
470
|
|
|
|
471
|
|
|
public function test_to_array_and_fallback_with_country_based_locales_enabled() |
472
|
|
|
{ |
473
|
|
|
$this->app->config->set('translatable.locale', 'en-GB'); |
474
|
|
|
$this->app->config->set('translatable.use_fallback', true); |
475
|
|
|
$this->app->config->set('translatable.fallback_locale', 'fr'); |
476
|
|
|
$this->app->config->set('translatable.locales', ['en' => ['GB'], 'fr']); |
477
|
|
|
$this->app->config->set('translatable.locale_separator', '-'); |
478
|
|
|
$data = [ |
479
|
|
|
'id' => 1, |
480
|
|
|
'fr' => ['name' => 'frites'], |
481
|
|
|
]; |
482
|
|
|
Food::create($data); |
483
|
|
|
$fritesArray = Food::find(1)->toArray(); |
484
|
|
|
$this->assertSame('frites', $fritesArray['name']); |
485
|
|
|
} |
486
|
|
|
|
487
|
|
|
public function test_it_skips_translations_in_to_array_when_config_is_set() |
488
|
|
|
{ |
489
|
|
|
$this->app->config->set('translatable.to_array_always_loads_translations', false); |
490
|
|
|
$greece = Country::whereCode('gr')->first()->toArray(); |
491
|
|
|
$this->assertFalse(isset($greece['name'])); |
492
|
|
|
} |
493
|
|
|
|
494
|
|
|
public function test_it_returns_translations_in_to_array_when_config_is_set_but_translations_are_loaded() |
495
|
|
|
{ |
496
|
|
|
$this->app->config->set('translatable.to_array_always_loads_translations', false); |
497
|
|
|
$greece = Country::whereCode('gr')->with('translations')->first()->toArray(); |
498
|
|
|
$this->assertTrue(isset($greece['name'])); |
499
|
|
|
} |
500
|
|
|
|
501
|
|
|
public function test_it_should_mutate_the_translated_attribute_if_a_mutator_is_set_on_model() |
502
|
|
|
{ |
503
|
|
|
$person = new Person(['name' => 'john doe']); |
504
|
|
|
$person->save(); |
505
|
|
|
$person = Person::find(1); |
506
|
|
|
$this->assertEquals('John doe', $person->name); |
507
|
|
|
} |
508
|
|
|
|
509
|
|
|
public function test_it_deletes_all_translations() |
510
|
|
|
{ |
511
|
|
|
$country = Country::whereCode('gr')->first(); |
512
|
|
|
$this->assertSame(4, count($country->translations)); |
513
|
|
|
|
514
|
|
|
$country->deleteTranslations(); |
515
|
|
|
|
516
|
|
|
$this->assertSame(0, count($country->translations)); |
517
|
|
|
$country = Country::whereCode('gr')->first(); |
518
|
|
|
$this->assertSame(0, count($country->translations)); |
519
|
|
|
} |
520
|
|
|
|
521
|
|
|
public function test_it_deletes_translations_for_given_locales() |
522
|
|
|
{ |
523
|
|
|
$country = Country::whereCode('gr')->with('translations')->first(); |
524
|
|
|
$count = count($country->translations); |
525
|
|
|
|
526
|
|
|
$country->deleteTranslations('fr'); |
527
|
|
|
|
528
|
|
|
$this->assertSame($count - 1, count($country->translations)); |
529
|
|
|
$country = Country::whereCode('gr')->with('translations')->first(); |
530
|
|
|
$this->assertSame($count - 1, count($country->translations)); |
531
|
|
|
$this->assertSame(null, $country->translate('fr')); |
532
|
|
|
} |
533
|
|
|
|
534
|
|
|
public function test_passing_an_empty_array_should_not_delete_translations() |
535
|
|
|
{ |
536
|
|
|
$country = Country::whereCode('gr')->with('translations')->first(); |
537
|
|
|
$count = count($country->translations); |
538
|
|
|
|
539
|
|
|
$country->deleteTranslations([]); |
540
|
|
|
|
541
|
|
|
$country = Country::whereCode('gr')->with('translations')->first(); |
542
|
|
|
$this->assertSame($count, count($country->translations)); |
543
|
|
|
} |
544
|
|
|
|
545
|
|
|
public function test_fill_with_translation_key() |
546
|
|
|
{ |
547
|
|
|
$country = new Country(); |
548
|
|
|
$country->fill([ |
549
|
|
|
'code' => 'tr', |
550
|
|
|
'name:en' => 'Turkey', |
551
|
|
|
'name:de' => 'Türkei', |
552
|
|
|
]); |
553
|
|
|
$this->assertEquals($country->translate('en')->name, 'Turkey'); |
554
|
|
|
$this->assertEquals($country->translate('de')->name, 'Türkei'); |
555
|
|
|
|
556
|
|
|
$country->save(); |
557
|
|
|
$country = Country::whereCode('tr')->first(); |
558
|
|
|
$this->assertEquals($country->translate('en')->name, 'Turkey'); |
559
|
|
|
$this->assertEquals($country->translate('de')->name, 'Türkei'); |
560
|
|
|
} |
561
|
|
|
|
562
|
|
|
public function test_it_uses_the_default_locale_from_the_model() |
563
|
|
|
{ |
564
|
|
|
$country = new Country(); |
565
|
|
|
$country->fill([ |
566
|
|
|
'code' => 'tn', |
567
|
|
|
'name:en' => 'Tunisia', |
568
|
|
|
'name:fr' => 'Tunisie', |
569
|
|
|
]); |
570
|
|
|
$this->assertEquals($country->name, 'Tunisia'); |
571
|
|
|
$country->setDefaultLocale('fr'); |
572
|
|
|
$this->assertEquals($country->name, 'Tunisie'); |
573
|
|
|
|
574
|
|
|
$country->setDefaultLocale(null); |
575
|
|
|
$country->save(); |
576
|
|
|
$country = Country::whereCode('tn')->first(); |
577
|
|
|
$this->assertEquals($country->name, 'Tunisia'); |
578
|
|
|
$country->setDefaultLocale('fr'); |
579
|
|
|
$this->assertEquals($country->name, 'Tunisie'); |
580
|
|
|
} |
581
|
|
|
|
582
|
|
|
public function test_replicate_entity() |
583
|
|
|
{ |
584
|
|
|
$apple = new Food(); |
585
|
|
|
$apple->fill([ |
586
|
|
|
'name:fr' => 'Pomme', |
587
|
|
|
'name:en' => 'Apple', |
588
|
|
|
'name:de' => 'Apfel', |
589
|
|
|
]); |
590
|
|
|
$apple->save(); |
591
|
|
|
|
592
|
|
|
$replicatedApple = $apple->replicateWithTranslations(); |
593
|
|
|
$this->assertNotSame($replicatedApple->id, $apple->id); |
594
|
|
|
$this->assertEquals($replicatedApple->translate('fr')->name, $apple->translate('fr')->name); |
595
|
|
|
$this->assertEquals($replicatedApple->translate('en')->name, $apple->translate('en')->name); |
596
|
|
|
$this->assertEquals($replicatedApple->translate('de')->name, $apple->translate('de')->name); |
597
|
|
|
} |
598
|
|
|
|
599
|
|
|
public function test_getTranslationsArray() |
600
|
|
|
{ |
601
|
|
|
Country::create([ |
602
|
|
|
'code' => 'tn', |
603
|
|
|
'name:en' => 'Tunisia', |
604
|
|
|
'name:fr' => 'Tunisie', |
605
|
|
|
'name:de' => 'Tunesien', |
606
|
|
|
]); |
607
|
|
|
|
608
|
|
|
/** @var Country $country */ |
609
|
|
|
$country = Country::where('code', 'tn')->first(); |
610
|
|
|
|
611
|
|
|
$this->assertSame([ |
612
|
|
|
'de' => ['name' => 'Tunesien'], |
613
|
|
|
'en' => ['name' => 'Tunisia'], |
614
|
|
|
'fr' => ['name' => 'Tunisie'], |
615
|
|
|
], $country->getTranslationsArray()); |
616
|
|
|
} |
617
|
|
|
|
618
|
|
|
public function test_fill_when_locale_key_unknown() |
619
|
|
|
{ |
620
|
|
|
config(['translatable.locales' => ['en']]); |
621
|
|
|
|
622
|
|
|
$country = new Country(); |
623
|
|
|
$country->fill([ |
624
|
|
|
'code' => 'ua', |
625
|
|
|
'en' => ['name' => 'Ukraine'], |
626
|
|
|
'ua' => ['name' => 'Україна'], // "ua" is unknown, so must be ignored |
627
|
|
|
]); |
628
|
|
|
|
629
|
|
|
$modelTranslations = []; |
630
|
|
|
|
631
|
|
View Code Duplication |
foreach ($country->translations as $translation) { |
|
|
|
|
632
|
|
|
foreach ($country->translatedAttributes as $attr) { |
633
|
|
|
$modelTranslations[$translation->locale][$attr] = $translation->{$attr}; |
634
|
|
|
} |
635
|
|
|
} |
636
|
|
|
|
637
|
|
|
$expectedTranslations = [ |
638
|
|
|
'en' => ['name' => 'Ukraine'], |
639
|
|
|
]; |
640
|
|
|
|
641
|
|
|
$this->assertEquals($modelTranslations, $expectedTranslations); |
642
|
|
|
} |
643
|
|
|
|
644
|
|
|
public function test_fill_with_translation_key_when_locale_key_unknown() |
645
|
|
|
{ |
646
|
|
|
config(['translatable.locales' => ['en']]); |
647
|
|
|
|
648
|
|
|
$country = new Country(); |
649
|
|
|
$country->fill([ |
650
|
|
|
'code' => 'ua', |
651
|
|
|
'name:en' => 'Ukraine', |
652
|
|
|
'name:ua' => 'Україна', // "ua" is unknown, so must be ignored |
653
|
|
|
]); |
654
|
|
|
|
655
|
|
|
$modelTranslations = []; |
656
|
|
|
|
657
|
|
View Code Duplication |
foreach ($country->translations as $translation) { |
|
|
|
|
658
|
|
|
foreach ($country->translatedAttributes as $attr) { |
659
|
|
|
$modelTranslations[$translation->locale][$attr] = $translation->{$attr}; |
660
|
|
|
} |
661
|
|
|
} |
662
|
|
|
|
663
|
|
|
$expectedTranslations = [ |
664
|
|
|
'en' => ['name' => 'Ukraine'], |
665
|
|
|
]; |
666
|
|
|
|
667
|
|
|
$this->assertEquals($modelTranslations, $expectedTranslations); |
668
|
|
|
} |
669
|
|
|
|
670
|
|
|
public function test_it_uses_fallback_locale_if_default_is_empty() |
671
|
|
|
{ |
672
|
|
|
App::make('config')->set('translatable.use_fallback', true); |
673
|
|
|
App::make('config')->set('translatable.use_property_fallback', true); |
674
|
|
|
App::make('config')->set('translatable.fallback_locale', 'en'); |
675
|
|
|
$country = new Country(); |
676
|
|
|
$country->fill([ |
677
|
|
|
'code' => 'tn', |
678
|
|
|
'name:en' => 'Tunisia', |
679
|
|
|
'name:fr' => '', |
680
|
|
|
]); |
681
|
|
|
$this->app->setLocale('en'); |
682
|
|
|
$this->assertEquals('Tunisia', $country->name); |
683
|
|
|
$this->app->setLocale('fr'); |
684
|
|
|
$this->assertEquals('Tunisia', $country->name); |
685
|
|
|
} |
686
|
|
|
|
687
|
|
|
public function test_it_always_uses_value_when_fallback_not_available() |
688
|
|
|
{ |
689
|
|
|
App::make('config')->set('translatable.fallback_locale', 'it'); |
690
|
|
|
App::make('config')->set('translatable.use_fallback', true); |
691
|
|
|
|
692
|
|
|
$country = new Country(); |
693
|
|
|
$country->fill([ |
694
|
|
|
'code' => 'gr', |
695
|
|
|
'en' => ['name' => ''], |
696
|
|
|
'de' => ['name' => 'Griechenland'], |
697
|
|
|
]); |
698
|
|
|
|
699
|
|
|
// verify translated attributed is correctly returned when empty (non-existing fallback is ignored) |
700
|
|
|
$this->app->setLocale('en'); |
701
|
|
|
$this->assertEquals('', $country->getAttribute('name')); |
702
|
|
|
|
703
|
|
|
$this->app->setLocale('de'); |
704
|
|
|
$this->assertEquals('Griechenland', $country->getAttribute('name')); |
705
|
|
|
} |
706
|
|
|
|
707
|
|
|
public function test_translation_with_multiconnection() |
708
|
|
|
{ |
709
|
|
|
$this->migrate('mysql2'); |
710
|
|
|
|
711
|
|
|
// Add country & translation in second db |
712
|
|
|
$country = new Country(); |
713
|
|
|
$country->setConnection('mysql2'); |
714
|
|
|
$country->code = 'sg'; |
715
|
|
|
$country->{'name:sg'} = 'Singapore'; |
716
|
|
|
$this->assertTrue($country->save()); |
717
|
|
|
|
718
|
|
|
$countryId = $country->id; |
719
|
|
|
|
720
|
|
|
// Verify added country & translation in second db |
721
|
|
|
$country = new Country(); |
722
|
|
|
$country->setConnection('mysql2'); |
723
|
|
|
$sgCountry2 = $country->newQuery()->find($countryId); |
724
|
|
|
$this->assertEquals('Singapore', $sgCountry2->translate('sg')->name); |
725
|
|
|
|
726
|
|
|
// Verify added country not in default db |
727
|
|
|
$country = new Country(); |
728
|
|
|
$country->setConnection('mysql'); |
729
|
|
|
$sgCountry1 = $country->newQuery()->where('code', 'sg')->get(); |
730
|
|
|
$this->assertEmpty($sgCountry1); |
731
|
|
|
|
732
|
|
|
// Verify added translation not in default db |
733
|
|
|
$country = new Country(); |
734
|
|
|
$country->setConnection('mysql'); |
735
|
|
|
$sgCountry1 = $country->newQuery()->find($countryId); |
736
|
|
|
$this->assertEmpty($sgCountry1->translate('sg')); |
737
|
|
|
} |
738
|
|
|
|
739
|
|
|
public function test_empty_translated_attribute() |
740
|
|
|
{ |
741
|
|
|
$country = Country::whereCode('gr')->first(); |
742
|
|
|
$this->app->setLocale('invalid'); |
743
|
|
|
$this->assertSame(null, $country->name); |
744
|
|
|
} |
745
|
|
|
|
746
|
|
|
public function test_numeric_translated_attribute() |
747
|
|
|
{ |
748
|
|
|
$this->app->config->set('translatable.fallback_locale', 'de'); |
749
|
|
|
$this->app->config->set('translatable.use_fallback', true); |
750
|
|
|
|
751
|
|
|
$city = new class extends \Dimsav\Translatable\Test\Model\City { |
752
|
|
|
protected $fillable = [ |
753
|
|
|
'country_id', |
754
|
|
|
]; |
755
|
|
|
protected $table = 'cities'; |
756
|
|
|
public $translationModel = \Dimsav\Translatable\Test\Model\CityTranslation::class; |
757
|
|
|
public $translationForeignKey = 'city_id'; |
758
|
|
|
|
759
|
|
|
protected function isEmptyTranslatableAttribute(string $key, $value): bool |
760
|
|
|
{ |
761
|
|
|
if ($key === 'name') { |
762
|
|
|
return is_null($value); |
763
|
|
|
} |
764
|
|
|
|
765
|
|
|
return empty($value); |
766
|
|
|
} |
767
|
|
|
}; |
768
|
|
|
$city->fill([ |
769
|
|
|
'country_id' => Country::first()->getKey(), |
770
|
|
|
'en' => ['name' => '0'], |
771
|
|
|
'de' => ['name' => '1'], |
772
|
|
|
'fr' => ['name' => null], |
773
|
|
|
]); |
774
|
|
|
$city->save(); |
775
|
|
|
|
776
|
|
|
$this->app->setLocale('en'); |
777
|
|
|
$this->assertSame('0', $city->name); |
778
|
|
|
|
779
|
|
|
$this->app->setLocale('fr'); |
780
|
|
|
$this->assertSame('1', $city->name); |
781
|
|
|
} |
782
|
|
|
} |
783
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.