diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 1a52013..1a1358a 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -10,14 +10,14 @@ jobs: matrix: os: [ ubuntu-latest, windows-latest ] php: [ 7.2.5, 8.0 ] - laravel: [ 6.*, 8.*, 9.0 ] + laravel: [ 6.*, 8.*, ^9.33 ] testbench: [ ^4.0, ^6.6, ^7.0 ] stability: [ prefer-lowest, prefer-stable ] exclude: - php: 7.2.5 laravel: 8.* - php: 7.2.5 - laravel: 9.0 + laravel: ^9.33 - php: 7.2.5 testbench: ^6.6 - php: 7.2.5 @@ -30,9 +30,9 @@ jobs: testbench: ^4.0 - laravel: 8.* testbench: ^7.0 - - laravel: 9.0 + - laravel: ^9.33 testbench: ^4.0 - - laravel: 9.0 + - laravel: ^9.33 testbench: ^6.6 name: php-${{ matrix.php }} - laravel-${{ matrix.laravel }} - testbench-${{ matrix.testbench }} - ${{ matrix.stability }} - ${{ matrix.os }} diff --git a/README.md b/README.md index 30330d6..995ee81 100644 --- a/README.md +++ b/README.md @@ -142,6 +142,13 @@ In this case translation strings will be generated for the language specified in > Note: Strings you have already translated will not be overwritten. +### Remove Missing Keys + +By default, the strings inside the locale files will be preserved even if they are not present the next time you run the localize command. +If you want to remove those keys that are not present in your files anymore you can append the --remove-missing option to the localize command. +``` bash +php artisan localize --remove-missing +``` ### Key Sorting By default, the strings generated inside those JSON files will be sorted alphabetically by their keys. diff --git a/src/Collections/DefaultKeyCollection.php b/src/Collections/DefaultKeyCollection.php index 4cebbd0..8040745 100644 --- a/src/Collections/DefaultKeyCollection.php +++ b/src/Collections/DefaultKeyCollection.php @@ -24,4 +24,13 @@ public function merge($items): self { return parent::merge(Arr::dot($items)); } + + /** + * @param mixed $items + * @return static + */ + public function intersectByKeys($items): self + { + return new self(collect(Arr::dot($this))->intersectByKeys($items)); + } } diff --git a/src/Commands/LocalizeCommand.php b/src/Commands/LocalizeCommand.php index 2592cfb..d245caf 100644 --- a/src/Commands/LocalizeCommand.php +++ b/src/Commands/LocalizeCommand.php @@ -16,7 +16,7 @@ class LocalizeCommand extends Command * * @var string */ - protected $signature = 'localize {lang?}'; + protected $signature = 'localize {lang?} {--remove-missing}'; /** * The console command description. @@ -53,7 +53,12 @@ public function handle(Localizator $localizator, Parser $parser): int $progressBar->setMessage("Localizing {$locale}..."); foreach ($this->getTypes() as $type) { - $localizator->localize($parser->getKeys($locale, $type), $type, $locale); + $localizator->localize( + $parser->getKeys($locale, $type), + $type, + $locale, + $this->option('remove-missing') + ); } $progressBar->advance(); diff --git a/src/Services/Localizator.php b/src/Services/Localizator.php index ab9373e..5bcc785 100644 --- a/src/Services/Localizator.php +++ b/src/Services/Localizator.php @@ -14,9 +14,9 @@ class Localizator * @param string $locale * @return void */ - public function localize(Translatable $keys, string $type, string $locale): void + public function localize(Translatable $keys, string $type, string $locale, bool $removeMissing): void { - $this->getWriter($type)->put($locale, $this->collect($keys, $type, $locale)); + $this->getWriter($type)->put($locale, $this->collect($keys, $type, $locale, $removeMissing)); } /** @@ -25,13 +25,15 @@ public function localize(Translatable $keys, string $type, string $locale): void * @param string $locale * @return Translatable */ - protected function collect(Translatable $keys, string $type, string $locale): Translatable + protected function collect(Translatable $keys, string $type, string $locale, bool $removeMissing): Translatable { return $keys - ->merge($this->getCollector($type)->getTranslated($locale)) - ->when(config('localizator.sort'), function (Translatable $keyCollection) { - return $keyCollection->sortAlphabetically(); - }); + ->merge($this->getCollector($type)->getTranslated($locale) + ->when($removeMissing, function (Translatable $keyCollection) use ($keys) { + return $keyCollection->intersectByKeys($keys); + }))->when(config('localizator.sort'), function (Translatable $keyCollection) { + return $keyCollection->sortAlphabetically(); + }); } /** diff --git a/tests/LocalizatorTest.php b/tests/LocalizatorTest.php index 788c6b9..8c80be5 100644 --- a/tests/LocalizatorTest.php +++ b/tests/LocalizatorTest.php @@ -295,4 +295,42 @@ public function testIntTranslationNestedKeysAreBeingSavedAsStrings(): void $this->assertSame(preg_replace('/\r\n|\r|\n/', "\n", $expected), $contents); } + + public function testRemoveMissingKeys(): void + { + self::flushDirectories('lang', 'views'); + + $this->createTestDefaultLangFile([ + 'missingstring' => 'Missing', + 'name' => 'Name', + ], 'app', 'en'); + $this->createTestJsonLangFile([ + 'Login' => 'Login', + 'Missing' => 'Missing', + ], 'en'); + + $enDefaultContents = $this->getDefaultLangContents('en', 'app'); + $enJsonContents = $this->getJsonLangContents('en'); + self::assertSame(['missingstring' => 'Missing', 'name' => 'Name'], $enDefaultContents); + self::assertSame(['Login' => 'Login', 'Missing' => 'Missing'], $enJsonContents); + + $this->createTestView("{{ __('Login') }} {{ __('app.name') }}"); + + // Run the command with the option to remove keys/strings that are not present anymore + $this->artisan('localize en --remove-missing') + ->assertExitCode(0); + + // Do created locale files exist? + self::assertDefaultLangFilesExist('en', ['app']); + self::assertJsonLangFilesExist('en'); + + // Do their contents match the expected results? + $enDefaultContents = $this->getDefaultLangContents('en', 'app'); + $enJsonContents = $this->getJsonLangContents('en'); + self::assertSame(['name' => 'Name'], $enDefaultContents); + self::assertSame(['Login' => 'Login'], $enJsonContents); + + // Cleanup. + self::flushDirectories('lang', 'views'); + } } diff --git a/tests/TestCase.php b/tests/TestCase.php index ee32597..a320b19 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -23,17 +23,6 @@ public function setUp(): void parent::setUp(); } - /** - * This method is called after the last test of this test class is run. - * - * @return void - */ - public static function tearDownAfterClass(): void - { - // Flush one last time after all tests have finished running. - self::flushDirectories('lang', 'views'); - } - /** * Get package providers. *