From 80c5ff1db3ebcc6009e5a10914a32ee38bde414d Mon Sep 17 00:00:00 2001 From: "Morten D. Hansen" Date: Wed, 2 Mar 2022 19:53:59 +0100 Subject: [PATCH 1/3] Command to rebuild translations cache --- .../DatabaseTranslationsCacheCommand.php | 56 +++++++++++++++++++ src/DatabaseTranslationsServiceProvider.php | 5 ++ tests/Feature/DatabaseTranslationsTest.php | 28 ++++++++++ tests/Feature/DbTransTest.php | 34 ----------- 4 files changed, 89 insertions(+), 34 deletions(-) create mode 100644 src/Console/DatabaseTranslationsCacheCommand.php delete mode 100644 tests/Feature/DbTransTest.php diff --git a/src/Console/DatabaseTranslationsCacheCommand.php b/src/Console/DatabaseTranslationsCacheCommand.php new file mode 100644 index 0000000..87c1b37 --- /dev/null +++ b/src/Console/DatabaseTranslationsCacheCommand.php @@ -0,0 +1,56 @@ +unique('group')->pluck('group'); + $locales = DatabaseLangItem::all('locale')->unique('locale')->pluck('locale'); + + // build cache keys + + foreach ($groups as $group) { + foreach ($locales as $locale) { + \Cache::forget(DbTrans::getCacheKey($group, $locale)); + DbTrans::getDatabaseTranslations($group, $locale); + } + } + + return self::SUCCESS; + } + + public function buildCacheKeys() + { + return $cacheKeys; + } +} \ No newline at end of file diff --git a/src/DatabaseTranslationsServiceProvider.php b/src/DatabaseTranslationsServiceProvider.php index e34be8d..b8de06a 100644 --- a/src/DatabaseTranslationsServiceProvider.php +++ b/src/DatabaseTranslationsServiceProvider.php @@ -4,6 +4,7 @@ use Illuminate\Translation\FileLoader; use Illuminate\Translation\TranslationServiceProvider; +use MortenDHansen\LaravelDatabaseTranslations\Console\DatabaseTranslationsCacheCommand; class DatabaseTranslationsServiceProvider extends TranslationServiceProvider { @@ -61,6 +62,10 @@ public function boot() $this->publishes([ __DIR__ . '/../config/translations-database.php' => config_path('translations-database.php'), ]); + + $this->commands([ + DatabaseTranslationsCacheCommand::class + ]); } } } \ No newline at end of file diff --git a/tests/Feature/DatabaseTranslationsTest.php b/tests/Feature/DatabaseTranslationsTest.php index 1f08c45..99dfa27 100644 --- a/tests/Feature/DatabaseTranslationsTest.php +++ b/tests/Feature/DatabaseTranslationsTest.php @@ -182,6 +182,34 @@ public function itHandlesOtherLanguage() $this->assertDatabaseHas('database_lang_items', ['group' => '*', 'locale' => 'de', 'key' => 'salad']); } + /** + * @test + * @return void + */ + public function commandRebuildsCache() + { + // create translations in two languages + __('salad.tomato'); + __('burger'); + + app()->setLocale('de'); + + __('salad.tomato'); + __('pasta'); + + // Change content of a translation without triggering events (should not be cached) + DatabaseLangItem::where('locale', 'de')->where('key', 'tomato')->update(['value' => 'schnitzel']); + $this->assertTrue(\Cache::has(DbTrans::getCacheKey('salad', 'de'))); + $this->assertNull(\Cache::get(DbTrans::getCacheKey('salad', 'de'))['tomato']); + $this->assertDatabaseHas('database_lang_items', + ['group' => 'salad', 'locale' => 'de', 'key' => 'tomato', 'value' => 'schnitzel']); + + // rebuild cache - now cache should be aligned with db + $this->artisan('dbtrans:cache-rebuild'); + $this->assertTrue(\Cache::has(DbTrans::getCacheKey('salad', 'de'))); + $this->assertEquals('schnitzel', \Cache::get(DbTrans::getCacheKey('salad', 'de'))['tomato']); + } + // // /** // * @test diff --git a/tests/Feature/DbTransTest.php b/tests/Feature/DbTransTest.php deleted file mode 100644 index 23731f3..0000000 --- a/tests/Feature/DbTransTest.php +++ /dev/null @@ -1,34 +0,0 @@ -getCacheKey('some', 'en'); -// $this->assertEquals(config('translations-database.cache-prefix') . '.en.some', $cacheKey); -// } -// -// /** -// * @test -// * @return void -// */ -// public function itCreateAndCashes() -// { -// app('dbtrans')->createLanguageItem('*', 'testkey', 'en'); -// $this->assertDatabaseHas('database_lang_items', ['group' => '*', 'key' => 'testkey', 'locale' => 'en']); -// $this->assertArrayHasKey('testkey', app('dbtrans')->getDatabaseTranslations('*', 'en')); -// -// $key = app('dbtrans')->getCacheKey('*', 'en'); -// $this->assertArrayHasKey('testkey', cache()->get($key)); -// } -//} \ No newline at end of file From 23d57d0e3865ced6e24db7a38428d3d00e13cbb2 Mon Sep 17 00:00:00 2001 From: "Morten D. Hansen" Date: Wed, 2 Mar 2022 19:55:43 +0100 Subject: [PATCH 2/3] format was annoying --- tests/Feature/DatabaseTranslationsTest.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/Feature/DatabaseTranslationsTest.php b/tests/Feature/DatabaseTranslationsTest.php index 99dfa27..96fd526 100644 --- a/tests/Feature/DatabaseTranslationsTest.php +++ b/tests/Feature/DatabaseTranslationsTest.php @@ -201,8 +201,12 @@ public function commandRebuildsCache() DatabaseLangItem::where('locale', 'de')->where('key', 'tomato')->update(['value' => 'schnitzel']); $this->assertTrue(\Cache::has(DbTrans::getCacheKey('salad', 'de'))); $this->assertNull(\Cache::get(DbTrans::getCacheKey('salad', 'de'))['tomato']); - $this->assertDatabaseHas('database_lang_items', - ['group' => 'salad', 'locale' => 'de', 'key' => 'tomato', 'value' => 'schnitzel']); + $this->assertDatabaseHas('database_lang_items', [ + 'group' => 'salad', + 'locale' => 'de', + 'key' => 'tomato', + 'value' => 'schnitzel' + ]); // rebuild cache - now cache should be aligned with db $this->artisan('dbtrans:cache-rebuild'); From 66b4123842f0429ee2f6dc466bad5c0ea2ca8311 Mon Sep 17 00:00:00 2001 From: "Morten D. Hansen" Date: Wed, 2 Mar 2022 20:11:51 +0100 Subject: [PATCH 3/3] reapply tests --- src/DatabaseTranslationsTranslator.php | 6 +- tests/Feature/DatabaseTranslationsTest.php | 339 +++++++++------------ 2 files changed, 144 insertions(+), 201 deletions(-) diff --git a/src/DatabaseTranslationsTranslator.php b/src/DatabaseTranslationsTranslator.php index 895bcb5..9a6942b 100644 --- a/src/DatabaseTranslationsTranslator.php +++ b/src/DatabaseTranslationsTranslator.php @@ -59,7 +59,7 @@ public function get($key, array $replace = [], $locale = null, $fallback = true) // The key was parsed, item place will be null if key is ungrouped if (!isset($item)) { - $item = $group; + $item = $group == '*' ? $key : $group; $group = '*'; } @@ -75,6 +75,10 @@ public function get($key, array $replace = [], $locale = null, $fallback = true) public function createMissingKey($group, $item, $locale) { + // That's not a key + if ($item === '*') { + return; + } DbTrans::createLanguageItem($group, $item, $locale); $this->loaded = []; $this->loadedFromDb = []; diff --git a/tests/Feature/DatabaseTranslationsTest.php b/tests/Feature/DatabaseTranslationsTest.php index 96fd526..f58a61f 100644 --- a/tests/Feature/DatabaseTranslationsTest.php +++ b/tests/Feature/DatabaseTranslationsTest.php @@ -214,206 +214,145 @@ public function commandRebuildsCache() $this->assertEquals('schnitzel', \Cache::get(DbTrans::getCacheKey('salad', 'de'))['tomato']); } -// -// /** -// * @test -// * @return void -// */ -// public function itLoadsTranslationFromDatabaseInDifferentLocales() -// { -// $this->addTranslationFile(['salad' => 'blue']); -// $this->addTranslationFile(['salad' => 'schwarz'], 'de'); -// DatabaseLangItem::factory()->create([ -// 'group' => '*', -// 'key' => 'salad', -// 'value' => 'green', -// 'locale' => 'en' -// ]); -// DatabaseLangItem::factory()->create([ -// 'group' => '*', -// 'key' => 'salad', -// 'value' => 'schwarz', -// 'locale' => 'de' -// ]); -// -// $this->assertEquals('green', __('salad')); -// -// app()->setLocale('de'); -// -// $this->assertEquals('schwarz', __('salad')); -// } -// -// /** -// * @test -// * @return void -// */ -// public function itLoadsTranslationFromFile() -// { -// // file says salad is blue -// $this->addTranslationFile(['salad' => 'blue']); -// $this->assertEquals('blue', __('salad')); -// } -// -// /** -// * @test -// * @return void -// */ -// public function ifTranslationIsBothInDatabaseAndFilesDatabaseWins() -// { -// // file says salad is blue -// $this->addTranslationFile(['salad' => 'blue']); -// $this->assertEquals('blue', __('salad')); -// -// $this->assertDatabaseHas('database_lang_items', ['group' => '*', 'locale' => 'en', 'key' => 'salad']); -// $langLine = DatabaseLangItem::where('key', 'salad')->first(); -// $langLine->value = 'green'; -// $langLine->save(); -// $this->assertEquals('green', __('salad')); -// } -// -// /** -// * @test -// * @return void -// */ -// public function itLoadsGroupedTranslationFromFile() -// { -// $this->assertEquals('The password is incorrect.', __('validation.current_password')); -// } -// -// /** -// * @test -// * @return void -// */ -// public function ifGroupedTranslationIsBothInDatabaseAndFilesDatabaseWins() -// { -// DatabaseLangItem::factory()->create([ -// 'key' => 'current_password', -// 'value' => 'Database has a different opinion!', -// 'group' => 'validation', -// 'locale' => 'en' -// ]); -// $this->assertDatabaseHas('database_lang_items', [ -// 'group' => 'validation', -// 'locale' => 'en', -// 'key' => 'current_password' -// ]); -// -// $this->assertEquals('Database has a different opinion!', __('validation.current_password')); -// } -// -// /** -// * @test -// * @return void -// */ -// public function itTakesTranslationFromFileIfDatabaseHasEmptyValue() -// { -// $this->addTranslationFile(['salad' => 'blue']); -// -// DatabaseLangItem::factory()->create([ -// 'key' => 'salad', -// 'group' => '*', -// 'value' => null, -// 'locale' => 'en' -// ]); -// -// $this->assertEquals('blue', __('salad')); -// $this->assertDatabaseHas('database_lang_items', ['key' => 'salad', 'locale' => 'en']); -// } -// -// /** -// * @test -// * @return void -// */ -// public function itCreatesMissingGroupedKeysButDoesNotReturnEmptyValues() -// { -// $translated = __('validation.current_password'); -// $this->assertDatabaseHas('database_lang_items', ['group' => 'validation', 'key' => 'current_password']); -// } -// -// /** -// * @test -// * @return void -// */ -// public function itCreatesMissingKeysButDoesNotReturnEmptyValues() -// { -// $translated = __('current_password'); -// $this->assertDatabaseHas('database_lang_items', ['group' => '*', 'key' => 'current_password']); -// } -// /** -// * @test -// * @return void -// */ -// public function itCreatesMissingKeysInDifferentLocales() -// { -// $translated = __('color'); -// $this->assertDatabaseHas('database_lang_items', ['group' => '*', 'key' => 'color', 'locale' => 'en']); -// -// app()->setLocale('de'); -// -// $translated = __('color'); -// $this->assertDatabaseHas('database_lang_items', ['group' => '*', 'key' => 'color', 'locale' => 'de']); -// -// } -// -// /** -// * @test -// * @return void -// */ -// public function loaderReturnsItemsWhichHasValue() -// { -// DatabaseLangItem::create([ -// 'group' => '*', -// 'locale' => 'en', -// 'key' => 'somekey' -// ]); -// -// DatabaseLangItem::create([ -// 'group' => '*', -// 'locale' => 'en', -// 'key' => 'someotherkey', -// 'value' => 'withvalue' -// ]); -// -// $loader = new DatabaseTranslationsLoader(); -// $result = $loader->getDbTranslations('*', 'en'); -// $this->assertCount(1, $result); -// $this->assertCount(2, $loader->dbTranslations['*']['en']); -// $this->assertArrayNotHasKey('somekey', $result); -// $this->assertArrayHasKey('someotherkey', $result); -// } -// -// /** -// * @test -// * @return void -// */ -// public function itFiguresOutMixedCaseKeys() -// { -// $key = app('dbtrans')->getCacheKey('*', 'en'); -// __('Im an annoying Key!'); -// $this->assertDatabaseHas('database_lang_items', ['group' => '*', 'key' => 'Im an annoying Key!', 'locale' => 'en']); -// $line = DatabaseLangItem::where('key', 'Im an annoying Key!')->first(); -// $line->value = 'blabla'; -// $line->save(); -// cache()->forget($key); -// $this->assertEquals('blabla', __('Im an annoying Key!')); -// } -// -// /** -// * @test -// * @return void -// */ -// public function itFiguresOutMixedCaseGroupedKeys() -// { -// __('metallica.Im an annoying Key!'); -// $this->assertDatabaseHas('database_lang_items', -// ['group' => 'metallica', 'key' => 'Im an annoying Key!', 'locale' => 'en']); -// $line = DatabaseLangItem::where('key', 'Im an annoying Key!')->where('group', 'metallica')->first(); -// $line->value = 'blabla'; -// $line->save(); -// cache()->forget(DbTrans::getCacheKey('metalica', 'en')); -// -// $this->assertEquals('blabla', __('metallica.Im an annoying Key!')); -// } + /** + * @test + * @return void + */ + public function itLoadsTranslationFromDatabaseInDifferentLocales() + { + $this->addTranslationFile(['salad' => 'blue']); + $this->addTranslationFile(['salad' => 'schwarz'], 'de'); + DatabaseLangItem::factory()->create([ + 'group' => '*', + 'key' => 'salad', + 'value' => 'green', + 'locale' => 'en' + ]); + DatabaseLangItem::factory()->create([ + 'group' => '*', + 'key' => 'salad', + 'value' => 'schwarz', + 'locale' => 'de' + ]); + + $this->assertEquals('green', __('salad')); + + app()->setLocale('de'); + + $this->assertEquals('schwarz', __('salad')); + } + + /** + * @test + * @return void + */ + public function itLoadsTranslationFromFile() + { + // file says salad is blue + $this->addTranslationFile(['salad' => 'blue']); + $this->assertEquals('blue', __('salad')); + } + + /** + * @test + * @return void + */ + public function ifTranslationIsBothInDatabaseAndFilesDatabaseWins() + { + // file says salad is blue + $this->addTranslationFile(['salad' => 'blue']); + $this->assertEquals('blue', __('salad')); + + $this->assertDatabaseHas('database_lang_items', ['group' => '*', 'locale' => 'en', 'key' => 'salad']); + $langLine = DatabaseLangItem::where('key', 'salad')->first(); + $langLine->value = 'green'; + $langLine->save(); + $this->assertEquals('green', __('salad')); + } + + /** + * @test + * @return void + */ + public function itLoadsGroupedTranslationFromFile() + { + $this->assertEquals('The password is incorrect.', __('validation.current_password')); + } + + /** + * @test + * @return void + */ + public function ifGroupedTranslationIsBothInDatabaseAndFilesDatabaseWins() + { + DatabaseLangItem::factory()->create([ + 'key' => 'current_password', + 'value' => 'Database has a different opinion!', + 'group' => 'validation', + 'locale' => 'en' + ]); + $this->assertDatabaseHas('database_lang_items', [ + 'group' => 'validation', + 'locale' => 'en', + 'key' => 'current_password' + ]); + + $this->assertEquals('Database has a different opinion!', __('validation.current_password')); + } + + /** + * @test + * @return void + */ + public function itTakesTranslationFromFileIfDatabaseHasEmptyValue() + { + $this->addTranslationFile(['salad' => 'blue']); + + DatabaseLangItem::factory()->create([ + 'key' => 'salad', + 'group' => '*', + 'value' => null, + 'locale' => 'en' + ]); + + $this->assertEquals('blue', __('salad')); + $this->assertDatabaseHas('database_lang_items', ['key' => 'salad', 'locale' => 'en']); + } + + /** + * @test + * @return void + */ + public function itCreatesMissingGroupedKeysButDoesNotReturnEmptyValues() + { + __('validation.current_password'); + $this->assertDatabaseHas('database_lang_items', ['group' => 'validation', 'key' => 'current_password']); + } + + /** + * @test + * @return void + */ + public function itCreatesMissingKeysButDoesNotReturnEmptyValues() + { + __('current_password'); + $this->assertDatabaseHas('database_lang_items', ['group' => '*', 'key' => 'current_password']); + } + + /** + * @test + * @return void + */ + public function itCreatesMissingKeysInDifferentLocales() + { + __('color'); + $this->assertDatabaseHas('database_lang_items', ['group' => '*', 'key' => 'color', 'locale' => 'en']); + + app()->setLocale('de'); + + __('color'); + $this->assertDatabaseHas('database_lang_items', ['group' => '*', 'key' => 'color', 'locale' => 'de']); + } } \ No newline at end of file