Skip to content

Commit

Permalink
Add support for generating a baseline file (#5)
Browse files Browse the repository at this point in the history
* Add support for generating a baseline file

* wip

* wip
  • Loading branch information
dmason30 authored Oct 9, 2023
1 parent 8e578d5 commit 8b5a372
Show file tree
Hide file tree
Showing 21 changed files with 282 additions and 9 deletions.
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,19 @@ $ php artisan translation:unused
+--------+----------------------+-----------------------------------------------+
```

You can generate a baseline file which will be used to ignore specific keys with the
`--generate-baseline` or `-b` command options:

```sh
$ php artisan translation:unused --generate-baseline

INFO Baseline file written with 5 unused translation keys.

$ php artisan translation:unused

INFO No unused translations found!
```

## Roadmap
- [x] Supports JSON and PHP translation files
- You can enable / disable file types in the config
Expand Down
12 changes: 12 additions & 0 deletions config/translation-linter.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,18 @@
],

'unused' => [
/*
|--------------------------------------------------------------------------
| Baseline file
|--------------------------------------------------------------------------
|
| This is the location of the baseline file that is used to ignore specific
| translation keys. You can generate this file by using the `--generate-baseline`
| option when running the command.
|
*/
'baseline' => base_path('translations.unused.baseline.json'),

/*
|--------------------------------------------------------------------------
| Output Fields
Expand Down
3 changes: 3 additions & 0 deletions pint.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
{
"preset": "laravel",
"exclude": [
"workbench"
],
"rules": {
"single_line_empty_body": true
}
Expand Down
19 changes: 19 additions & 0 deletions src/Collections/BaselineCollection.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace Fidum\LaravelTranslationLinter\Collections;

use Illuminate\Support\Collection;

class BaselineCollection extends Collection
{
public function shouldReport(string $locale, string $key): bool
{
$ignoredKeys = $this->get($locale) ?: [];

if (in_array($key, $ignoredKeys, true)) {
return false;
}

return true;
}
}
8 changes: 8 additions & 0 deletions src/Collections/ResultObjectCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@ public function reset(): void
$this->items = [];
}

public function toBaseLineJson(): string
{
return $this
->groupBy('locale')
->map(fn (ResultObjectCollection $collection) => $collection->pluck('namespaceHintedKey')->values())
->toJson(JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
}

public function toCommandTableOutputArray(FieldCollectionContract $fields): array
{
$only = $fields->enabled()->toArray();
Expand Down
23 changes: 21 additions & 2 deletions src/Commands/UnusedCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,39 @@
use Fidum\LaravelTranslationLinter\Contracts\Collections\UnusedFieldCollection;
use Fidum\LaravelTranslationLinter\Contracts\Collections\UnusedFilterCollection;
use Fidum\LaravelTranslationLinter\Contracts\Linters\UnusedTranslationLinter;
use Fidum\LaravelTranslationLinter\Filters\IgnoreKeysFromUnusedBaselineFileFilter;
use Fidum\LaravelTranslationLinter\Writers\UnusedBaselineFileWriter;
use Illuminate\Console\Command;

class UnusedCommand extends Command
{
public $signature = 'translation:unused';
public $signature = 'translation:unused
{--b|generate-baseline : Generate a baseline file from the unused keys.}';

public $description = 'Finds unused language keys.';

public function handle(
UnusedBaselineFileWriter $writer,
UnusedFieldCollection $fields,
UnusedFilterCollection $filters,
UnusedTranslationLinter $linter,
): int {
$results = $linter->execute()->whereShouldReport($filters);
$baseline = (bool) $this->option('generate-baseline');
$results = $linter->execute();

if ($baseline) {
$results = $results->whereShouldReport($filters);

$writer->execute($results);

$this->components->info("Baseline file written with {$results->count()} unused translation keys.");

return self::SUCCESS;
}

$filters->push(IgnoreKeysFromUnusedBaselineFileFilter::class);

$results = $results->whereShouldReport($filters);

if ($results->isEmpty()) {
$this->components->info('No unused translations found!');
Expand Down
2 changes: 2 additions & 0 deletions src/Contracts/Collections/FilterCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,7 @@

interface FilterCollection extends Arrayable, Enumerable
{
public function push(...$values);

public function shouldReport(ResultObject $object): bool;
}
2 changes: 2 additions & 0 deletions src/Contracts/Collections/ResultObjectCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ interface ResultObjectCollection extends Arrayable, Enumerable
{
public function reset(): void;

public function toBaseLineJson(): string;

public function toCommandTableOutputArray(FieldCollectionContract $fields): array;

public function whereShouldReport(FilterCollectionContract $filters): self;
Expand Down
10 changes: 10 additions & 0 deletions src/Contracts/Readers/UnusedBaselineFileReader.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace Fidum\LaravelTranslationLinter\Contracts\Readers;

use Fidum\LaravelTranslationLinter\Collections\BaselineCollection;

interface UnusedBaselineFileReader
{
public function execute(): BaselineCollection;
}
10 changes: 10 additions & 0 deletions src/Contracts/Writers/UnusedBaselineFileWriter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace Fidum\LaravelTranslationLinter\Contracts\Writers;

use Fidum\LaravelTranslationLinter\Contracts\Collections\ResultObjectCollection;

interface UnusedBaselineFileWriter
{
public function execute(ResultObjectCollection $results);
}
19 changes: 19 additions & 0 deletions src/Filters/IgnoreKeysFromUnusedBaselineFileFilter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace Fidum\LaravelTranslationLinter\Filters;

use Fidum\LaravelTranslationLinter\Contracts\Filters\Filter;
use Fidum\LaravelTranslationLinter\Contracts\Readers\UnusedBaselineFileReader;
use Fidum\LaravelTranslationLinter\Data\ResultObject;

class IgnoreKeysFromUnusedBaselineFileFilter implements Filter
{
public function __construct(protected UnusedBaselineFileReader $reader) {}

public function shouldReport(ResultObject $object): bool
{
return $this->reader
->execute()
->shouldReport($object->locale, $object->namespaceHintedKey);
}
}
22 changes: 22 additions & 0 deletions src/LaravelTranslationLinterServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
use Fidum\LaravelTranslationLinter\Contracts\Parsers\ApplicationFileParser as ApplicationFileParserContract;
use Fidum\LaravelTranslationLinter\Contracts\Readers\ApplicationFileReader as ApplicationFileReaderContract;
use Fidum\LaravelTranslationLinter\Contracts\Readers\LanguageFileReader as LanguageFileReaderContract;
use Fidum\LaravelTranslationLinter\Contracts\Readers\UnusedBaselineFileReader as UnusedBaselineFileReaderContract;
use Fidum\LaravelTranslationLinter\Contracts\Writers\UnusedBaselineFileWriter as UnusedBaselineFileWriterContract;
use Fidum\LaravelTranslationLinter\Factories\LanguageKeyFactory;
use Fidum\LaravelTranslationLinter\Factories\LanguageNamespaceKeyFactory;
use Fidum\LaravelTranslationLinter\Finders\ApplicationFileFinder;
Expand All @@ -28,6 +30,8 @@
use Fidum\LaravelTranslationLinter\Parsers\ApplicationFileParser;
use Fidum\LaravelTranslationLinter\Readers\ApplicationFileReader;
use Fidum\LaravelTranslationLinter\Readers\LanguageFileReader;
use Fidum\LaravelTranslationLinter\Readers\UnusedBaselineFileReader;
use Fidum\LaravelTranslationLinter\Writers\UnusedBaselineFileWriter;
use Illuminate\Contracts\Support\DeferrableProvider;
use Illuminate\Foundation\Application;
use Spatie\LaravelPackageTools\Package;
Expand Down Expand Up @@ -63,6 +67,10 @@ public function registeringPackage()

$this->app->bind(ApplicationFileReaderContract::class, ApplicationFileReader::class);

$this->app->when(ApplicationFileParser::class)
->needs('$functions')
->giveConfig('translation-linter.lang.functions');

$this->app->bind(LanguageFileFinderContract::class, LanguageFileFinder::class);

$this->app->bind(LanguageFileReaderContract::class, LanguageFileReader::class);
Expand All @@ -80,6 +88,18 @@ public function registeringPackage()

$this->app->bind(ResultObjectCollectionContract::class, ResultObjectCollection::class);

$this->app->scoped(UnusedBaselineFileReaderContract::class, UnusedBaselineFileReader::class);

$this->app->when(UnusedBaselineFileReader::class)
->needs('$file')
->giveConfig('translation-linter.unused.baseline');

$this->app->bind(UnusedBaselineFileWriterContract::class, UnusedBaselineFileWriter::class);

$this->app->when(UnusedBaselineFileWriter::class)
->needs('$file')
->giveConfig('translation-linter.unused.baseline');

$this->app->bind(UnusedFieldCollectionContract::class, function (Application $app) {
return UnusedFieldCollection::wrap($app->make('config')->get('translation-linter.unused.fields'));
});
Expand Down Expand Up @@ -108,6 +128,8 @@ public function provides()
LanguageNamespaceFinderContract::class,
LanguageNamespaceKeyFactoryContract::class,
ResultObjectCollectionContract::class,
UnusedBaselineFileReaderContract::class,
UnusedBaselineFileWriterContract::class,
UnusedFieldCollectionContract::class,
UnusedFilterCollectionContract::class,
UnusedTranslationLinterContract::class,
Expand Down
32 changes: 32 additions & 0 deletions src/Readers/UnusedBaselineFileReader.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace Fidum\LaravelTranslationLinter\Readers;

use Fidum\LaravelTranslationLinter\Collections\BaselineCollection;
use Fidum\LaravelTranslationLinter\Contracts\Readers\UnusedBaselineFileReader as UnusedBaselineFileReaderContract;
use Illuminate\Filesystem\Filesystem;

class UnusedBaselineFileReader implements UnusedBaselineFileReaderContract
{
protected array $decoded = [];

public function __construct(
protected Filesystem $filesystem,
protected string $file,
) {}

public function execute(): BaselineCollection
{
if ($this->decoded) {
return BaselineCollection::wrap($this->decoded);
}

if ($this->filesystem->exists($this->file)) {
$contents = $this->filesystem->get($this->file);

$this->decoded = json_decode($contents, true);
}

return BaselineCollection::wrap($this->decoded);
}
}
23 changes: 23 additions & 0 deletions src/Writers/UnusedBaselineFileWriter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

namespace Fidum\LaravelTranslationLinter\Writers;

use Fidum\LaravelTranslationLinter\Contracts\Collections\ResultObjectCollection;
use Fidum\LaravelTranslationLinter\Contracts\Writers\UnusedBaselineFileWriter as UnusedBaselineFileWriterContract;
use Illuminate\Filesystem\Filesystem;

class UnusedBaselineFileWriter implements UnusedBaselineFileWriterContract
{
public function __construct(
protected Filesystem $filesystem,
protected string $file,
) {}

public function execute(ResultObjectCollection $results)
{
$this->filesystem->put(
$this->file,
$results->toBaseLineJson(),
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

INFO Baseline file written with 36 unused translation keys.

Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"en": [
"Unused Vendor PHP Class",
"Unused Vendor Blade File",
"Unused Vendor Vue Component",
"example::example.unused",
"example::example.blade.choice.unused",
"example::example.blade.lang.unused",
"example::example.vue.unused",
"example::folder/example.unused",
"example::folder/example.blade.choice.unused",
"example::folder/example.blade.lang.unused",
"example::folder/example.vue.unused",
"Unused PHP Class",
"Unused Blade File",
"Unused Vue Component",
"example.unused",
"example.blade.choice.unused",
"example.blade.lang.unused",
"example.vue.unused",
"folder/example.unused",
"folder/example.blade.choice.unused",
"folder/example.blade.lang.unused",
"folder/example.vue.unused"
],
"de": [
"Unused Vendor PHP Class",
"Unused Vendor Blade File",
"Unused Vendor Vue Component",
"Unused PHP Class",
"Unused Blade File",
"Unused Vue Component",
"example.unused",
"example.blade.choice.unused",
"example.blade.lang.unused",
"example.vue.unused",
"folder/example.unused",
"folder/example.blade.choice.unused",
"folder/example.blade.lang.unused",
"folder/example.vue.unused"
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

INFO No unused translations found!

Loading

0 comments on commit 8b5a372

Please sign in to comment.