diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index b290c1f..0ca8b51 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1 +1 @@ -github: cdruc +github: druc diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 57a1d69..92ccbc6 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,11 +1,11 @@ blank_issues_enabled: false contact_links: - name: Ask a question - url: https://github.com/cdruc/laravel-langscanner/discussions/new?category=q-a + url: https://github.com/druc/laravel-langscanner/discussions/new?category=q-a about: Ask the community for help - name: Request a feature - url: https://github.com/cdruc/laravel-langscanner/discussions/new?category=ideas + url: https://github.com/druc/laravel-langscanner/discussions/new?category=ideas about: Share ideas for new features - name: Report a bug - url: https://github.com/cdruc/laravel-langscanner/issues/new + url: https://github.com/druc/laravel-langscanner/issues/new about: Report a reproducable bug diff --git a/LICENSE.md b/LICENSE.md index 3dbfd62..541ff07 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) cdruc +Copyright (c) druc Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 8d8d01e..1f43871 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # laravel-langscanner -[![Latest Version on Packagist](https://img.shields.io/packagist/v/cdruc/laravel-langscanner.svg?style=flat-square)](https://packagist.org/packages/cdruc/laravel-langscanner) -[![Total Downloads](https://img.shields.io/packagist/dt/cdruc/laravel-langscanner.svg?style=flat-square)](https://packagist.org/packages/cdruc/laravel-langscanner) +[![Latest Version on Packagist](https://img.shields.io/packagist/v/druc/laravel-langscanner.svg?style=flat-square)](https://packagist.org/packages/druc/laravel-langscanner) +[![Total Downloads](https://img.shields.io/packagist/dt/druc/laravel-langscanner.svg?style=flat-square)](https://packagist.org/packages/druc/laravel-langscanner) ## Usage @@ -16,7 +16,7 @@ php artisan langscanner You can install the package via composer: ```bash -composer require cdruc/laravel-langscanner +composer require druc/laravel-langscanner ``` ## Credits diff --git a/composer.json b/composer.json index 5a008c8..9aec182 100644 --- a/composer.json +++ b/composer.json @@ -1,11 +1,11 @@ { - "name": "cdruc/laravel-langscanner", + "name": "druc/laravel-langscanner", "description": "Scan missing language translations.", "keywords": [ - "cdruc", + "druc", "laravel-langscanner" ], - "homepage": "https://github.com/cdruc/laravel-langscanner", + "homepage": "https://github.com/druc/laravel-langscanner", "license": "MIT", "authors": [ { @@ -29,12 +29,12 @@ }, "autoload": { "psr-4": { - "Cdruc\\Langscanner\\": "src" + "Druc\\Langscanner\\": "src" } }, "autoload-dev": { "psr-4": { - "Cdruc\\Langscanner\\Tests\\": "tests" + "Druc\\Langscanner\\Tests\\": "tests" } }, "scripts": { @@ -47,7 +47,7 @@ "extra": { "laravel": { "providers": [ - "Cdruc\\Langscanner\\LangscannerServiceProvider" + "Druc\\Langscanner\\LangscannerServiceProvider" ] } }, diff --git a/config/langscanner.php b/config/langscanner.php index cebc01d..cabef49 100644 --- a/config/langscanner.php +++ b/config/langscanner.php @@ -29,7 +29,7 @@ | Which directories to scan for missing translations. | */ - 'scan_paths' => [app_path(), resource_path()], + 'paths' => [app_path(), resource_path()], /* |-------------------------------------------------------------------------- @@ -39,7 +39,7 @@ | Which directories to exclude when scanning for missing translations. | */ - 'scan_excluded_paths' => [], + 'excluded_paths' => [], /* |-------------------------------------------------------------------------- @@ -50,4 +50,14 @@ | */ 'excluded_languages' => ['en'], + + /* + |-------------------------------------------------------------------------- + | Languages path + |-------------------------------------------------------------------------- + | + | Where are the language .json files located + | + */ + 'languages_path' => resource_path('lang'), ]; diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 6fd04bb..df4f684 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -19,7 +19,7 @@ verbose="true" > - + tests diff --git a/src/Commands/LangscannerCommand.php b/src/Commands/LangscannerCommand.php index d5fe5fb..5ae5702 100644 --- a/src/Commands/LangscannerCommand.php +++ b/src/Commands/LangscannerCommand.php @@ -1,68 +1,56 @@ langscanner = $langscanner; - } - - /** - * Execute the console command. - * - * @return mixed - * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException - */ public function handle() { - $missingTranslations = $this->langscanner->missingTranslations(); - - if (empty($missingTranslations)) { - return $this->info("No missing translations were detected."); - } - + $headers = ["Language", "Key", "Path"]; $rows = []; - // set some headers for the table of results - $headers = ["Language", "Type", "Group", "Key"]; - - // iterate over each of the missing languages - foreach ($missingTranslations as $language => $types) { - // iterate over each of the file types (json or array) - foreach ($types as $type => $keys) { - // iterate over each of the keys - foreach ($keys as $key => $value) { - // populate the array with the relevant data to fill the table - foreach ($value as $k => $v) { - $rows[] = [$language, $type, $key, $k]; - } - } + $languages = new RequiredLanguages( + new Filesystem, + config('langscanner.languages_path'), + config('langscanner.excluded_languages') + ); + + $requiredTranslations = new RequiredTranslations( + new Filesystem, + config('langscanner.paths'), + config('langscanner.excluded_paths'), + config('langscanner.translation_methods') + ); + + foreach ($languages->toArray() as $language) { + $missingTranslations = new MissingTranslations( + $requiredTranslations, + new ExistingTranslations( + new Filesystem, + config('langscanner.languages_path'), + $language + ) + ); + + foreach ($missingTranslations->toArray() as $key => $path) { + $rows[] = [$language, $key, $path]; } + + (new FileTranslations(config('langscanner.languages_path')."/$language.json")) + ->update($missingTranslations); } - // render the table of results $this->table($headers, $rows); } } diff --git a/src/ExistingTranslations.php b/src/ExistingTranslations.php new file mode 100644 index 0000000..cdd5459 --- /dev/null +++ b/src/ExistingTranslations.php @@ -0,0 +1,31 @@ +disk = $disk; + $this->language = $language; + $this->languagesPath = $languagesPath; + } + + public function toArray(): array + { + $translationFiles = new Collection($this->disk->allFiles($this->languagesPath)); + + return $translationFiles->filter(function ($file) { + return strpos($file, "{$this->language}.json"); + })->flatMap(function ($file) { + return json_decode($this->disk->get($file), true); + })->toArray(); + } +} diff --git a/src/FileTranslations.php b/src/FileTranslations.php new file mode 100644 index 0000000..1cbe328 --- /dev/null +++ b/src/FileTranslations.php @@ -0,0 +1,27 @@ +path = $path; + } + + public function update(MissingTranslations $missingTranslations) + { + $existingTranslations = file_get_contents($this->path); + $existingTranslations = json_decode($existingTranslations, true); + + // Sets keys to an empty string: ['needs translation' => '', etc] + $unfilledTranslations = array_fill_keys(array_keys($missingTranslations->toArray()), ''); + + $mergedTranslations = array_merge($existingTranslations, $unfilledTranslations); + $mergedTranslations = json_encode($mergedTranslations, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); + + file_put_contents($this->path, $mergedTranslations); + } +} diff --git a/src/Langscanner.php b/src/Langscanner.php deleted file mode 100644 index 0b2a4e3..0000000 --- a/src/Langscanner.php +++ /dev/null @@ -1,222 +0,0 @@ -disk = $disk; - $this->languageFilesPath = $languageFilesPath; - $this->scanner = $scanner; - $this->excludedLanguages = $excludedLanguages; - } - - /** - * @return array - * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException - */ - public function missingTranslations(): array - { - $missingTranslations = []; - - foreach ($this->languages() as $language => $name) { - $missing = $this->missingTranslationsFor($language); - - if (! empty($missing)) { - $missingTranslations[$language] = $missing; - } - } - - return $missingTranslations; - } - - /** - * Get all translations for a particular language. - * - * @param string $language - * @return \Illuminate\Support\Collection - * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException - */ - private function translationsFor(string $language): Collection - { - return Collection::make([ - 'group' => $this->groupTranslationsFor($language), - 'single' => $this->singleTranslationsFor($language), - ]); - } - - /** - * Get all of the single translations for a given language. - * - * @param string $language - * @return Collection - */ - private function singleTranslationsFor(string $language): Collection - { - $files = new Collection($this->disk->allFiles($this->languageFilesPath)); - - return $files->filter(function ($file) use ($language) { - return strpos($file, "{$language}.json"); - })->flatMap(function ($file) { - return [ - $this->prefix($file) => new Collection(json_decode($this->disk->get($file), true)), - ]; - }); - } - - private function prefix($file, $default = 'single'): string - { - if (Str::contains($file->getPathname(), 'vendor')) { - $vendor = Str::before(Str::after($file->getPathname(), 'vendor' . DIRECTORY_SEPARATOR), DIRECTORY_SEPARATOR); - - return "{$vendor}::{$default}"; - } - - return $default; - } - - /** - * Get all of the group translations for a given language. - * - * @param string $language - * @return Collection - * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException - */ - private function groupTranslationsFor(string $language): Collection - { - return $this->groupFilesFor($language) - ->mapWithKeys(function ($file) { - return [ - $this->prefix($file, $file->getBasename('.php')) => new Collection(Arr::dot($this->disk->getRequire($file->getPathname()))), - ]; - }); - } - - /** - * Get all the group files for a given language. - * - * @param string $language - * @return Collection - */ - private function groupFilesFor(string $language): Collection - { - $groups = new Collection($this->disk->allFiles("{$this->languageFilesPath}" . DIRECTORY_SEPARATOR . "{$language}")); - // namespaced files reside in the vendor directory so we'll grab these - // the `getVendorGroupFileFor` method - $groups = $groups->merge($this->vendorGroupFilesFor($language)); - - return $groups; - } - - /** - * Get all the vendor group files for a given language. - * - * @param string $language - * @return Collection - */ - private function vendorGroupFilesFor(string $language): Collection - { - if (! $this->disk->exists("{$this->languageFilesPath}" . DIRECTORY_SEPARATOR . 'vendor')) { - return Collection::make([]); - } - - $vendorGroups = []; - foreach ($this->disk->directories("{$this->languageFilesPath}" . DIRECTORY_SEPARATOR . 'vendor') as $vendor) { - $vendor = Arr::last(explode(DIRECTORY_SEPARATOR, $vendor)); - if (! $this->disk->exists("{$this->languageFilesPath}" . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . "{$vendor}" . DIRECTORY_SEPARATOR . "{$language}")) { - array_push($vendorGroups, []); - } else { - array_push($vendorGroups, $this->disk->allFiles("{$this->languageFilesPath}" . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . "{$vendor}" . DIRECTORY_SEPARATOR . "{$language}")); - } - } - - return new Collection(Arr::flatten($vendorGroups)); - } - - /** - * Find all of the translations in the app without translation for a given language. - * - * @param string $language - * @return array - * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException - */ - private function missingTranslationsFor(string $language): array - { - return $this->arrayDiffAssocRecursive( - $this->scanner->translations(), - $this->translationsFor($language) - ); - } - - /** - * Get all languages from the application. - * - * @return Collection - */ - private function languages(): Collection - { - // Parse the language files path for directories and json files - $directories = Collection::make($this->disk->directories($this->languageFilesPath)) - ->mapWithKeys(function ($directory) { - $language = basename($directory); - - return [$language => $language]; - })->filter(function ($language) { - // at the moment, we're not supporting vendor specific translations - return $language != 'vendor'; - }); - - $files = Collection::make($this->disk->files($this->languageFilesPath)) - ->filter(function ($file) { - return $file->getExtension() === 'json'; - })->mapWithKeys(function ($file) { - $language = Str::replaceLast('.json', '', $file->getBasename()); - - return [$language => $language]; - }); - - $languages = $files->merge($directories); - - return $languages->except($this->excludedLanguages); - } - - /** - * @param $arrayOne - * @param $arrayTwo - * @return array - */ - private function arrayDiffAssocRecursive($arrayOne, $arrayTwo): array - { - $difference = []; - - foreach ($arrayOne as $key => $value) { - if (is_array($value) || $value instanceof Collection) { - if (! isset($arrayTwo[$key])) { - $difference[$key] = $value; - } elseif (! (is_array($arrayTwo[$key]) || $arrayTwo[$key] instanceof Collection)) { - $difference[$key] = $value; - } else { - $new_diff = $this->arrayDiffAssocRecursive($value, $arrayTwo[$key]); - if ($new_diff != false) { - $difference[$key] = $new_diff; - } - } - } elseif (! isset($arrayTwo[$key])) { - $difference[$key] = $value; - } - } - - return $difference; - } -} diff --git a/src/LangscannerServiceProvider.php b/src/LangscannerServiceProvider.php index 7da2989..161d3bb 100644 --- a/src/LangscannerServiceProvider.php +++ b/src/LangscannerServiceProvider.php @@ -1,16 +1,15 @@ hasConfigFile() ->hasCommand(LangscannerCommand::class); } - - /** - * @throws \Spatie\LaravelPackageTools\Exceptions\InvalidPackage - */ - public function register(): LangscannerServiceProvider - { - parent::register(); - - $this->app->singleton(TranslationsScanner::class, function () { - $config = $this->app['config']['langscanner']; - - return new TranslationsScanner(new Filesystem, $config['scan_paths'], $config['scan_excluded_paths'], $config['translation_methods']); - }); - - $this->app->singleton(Langscanner::class, function () { - return new Langscanner( - new Filesystem(), - $this->app['path.lang'], - $this->app[TranslationsScanner::class], - $this->app['config']['langscanner']['excluded_languages'] - ); - }); - - return $this; - } } diff --git a/src/MissingTranslations.php b/src/MissingTranslations.php new file mode 100644 index 0000000..8f566e7 --- /dev/null +++ b/src/MissingTranslations.php @@ -0,0 +1,30 @@ +requiredTranslations = $requiredTranslations; + $this->existingTranslations = $existingTranslations; + } + + public function toArray(): array + { + $requiredTranslations = $this->requiredTranslations->toArray(); + $existingTranslations = $this->existingTranslations->toArray(); + $missing = []; + + foreach ($requiredTranslations as $key => $value) { + if (empty($existingTranslations[$key])) { + $missing[$key] = $value; + } + } + + return $missing; + } +} diff --git a/src/RequiredLanguages.php b/src/RequiredLanguages.php new file mode 100644 index 0000000..60e869e --- /dev/null +++ b/src/RequiredLanguages.php @@ -0,0 +1,33 @@ +disk = $disk; + $this->languagesPath = $languagesPath; + $this->excludedLanguages = $excludedLanguages; + } + + public function toArray(): array + { + return Collection::make($this->disk->files($this->languagesPath)) + ->filter(function ($file) { + return $file->getExtension() === 'json'; + })->map(function ($file) { + return Str::replaceLast('.json', '', $file->getBasename()); + })->filter(function ($lang) { + return !in_array($lang, $this->excludedLanguages); + })->values()->toArray(); + } +} diff --git a/src/RequiredTranslations.php b/src/RequiredTranslations.php new file mode 100644 index 0000000..a737250 --- /dev/null +++ b/src/RequiredTranslations.php @@ -0,0 +1,76 @@ +disk = $disk; + $this->paths = $paths; + $this->excludedPaths = $excludedPaths; + $this->translationMethods = $translationMethods; + } + + public function toArray(): array + { + if (isset($this->translations)) { + return $this->translations; + } + + $pattern = + // See https://regex101.com/r/jS5fX0/5 + '[^\w]'. // Must not start with any alphanum or _ + '(?)'. // Must not start with -> + '('.implode('|', $this->translationMethods).')'.// Must start with one of the functions + "\(".// Match opening parentheses + "[\'\"]".// Match " or ' + '('.// Start a new group to match: + '.*'.// Must start with group + ')'.// Close group + "[\'\"]".// Closing quote + "[\),]" // Close parentheses or new parameter + ; + + $results = []; + foreach ($this->files() as $file) { + if (preg_match_all("/$pattern/siuU", $file->getContents(), $matches)) { + foreach ($matches[2] as $key) { + if (!empty($key)) { + $results[$key] = $file->getFilename(); + } + } + } + } + + return $this->translations = $results; + } + + private function files(): array + { + $files = $this->disk->allFiles($this->paths); + + foreach ($files as $i => $file) { + foreach ($this->excludedPaths as $path) { + if (Str::startsWith($file->getPathName(), $path)) { + unset($files[$i]); + } + } + } + + return $files; + } +} diff --git a/src/TranslationsScanner.php b/src/TranslationsScanner.php deleted file mode 100644 index 5bd3987..0000000 --- a/src/TranslationsScanner.php +++ /dev/null @@ -1,96 +0,0 @@ -disk = $disk; - $this->paths = $paths; - $this->excludedPaths = $excludedPaths; - $this->translationMethods = $translationMethods; - } - - /** - * Scan all the files in the provided $scanPath for translations. - * - * @return array - */ - public function translations(): array - { - if (isset($this->translations)) { - return $this->translations; - } - - $results = ['single' => [], 'group' => []]; - - // This has been derived from a combination of the following: - // * Laravel Language Manager GUI from Mohamed Said (https://github.com/themsaid/laravel-langman-gui) - // * Laravel 5 Translation Manager from Barry vd. Heuvel (https://github.com/barryvdh/laravel-translation-manager) - $matchingPattern = - // See https://regex101.com/r/jS5fX0/5 - '[^\w]'. // Must not start with any alphanum or _ - '(?)'. // Must not start with -> - '(' . implode('|', $this->translationMethods) . ')' .// Must start with one of the functions - "\(".// Match opening parentheses - "[\'\"]".// Match " or ' - '('.// Start a new group to match: - '.+'.// Must start with group - ')'.// Close group - "[\'\"]".// Closing quote - "[\),]" // Close parentheses or new parameter - ; - - foreach ($this->files() as $file) { - if (preg_match_all("/$matchingPattern/siU", $file->getContents(), $matches)) { - foreach ($matches[2] as $key) { - if (preg_match("/(^[a-zA-Z0-9:_-]+([.][^\1)\ ]+)+$)/siU", $key, $arrayMatches)) { - [$file, $k] = explode('.', $arrayMatches[0], 2); - $results['group'][$file][$k] = ''; - - continue; - } else { - $results['single']['single'][$key] = ''; - } - } - } - } - - return $this->translations = $results; - } - - /** - * @return array - */ - private function files(): array - { - $files = $this->disk->allFiles($this->paths); - - foreach ($files as $i => $file) { - foreach ($this->excludedPaths as $path) { - if (Str::startsWith($file->getPathName(), $path)) { - unset($files[$i]); - } - } - } - - return $files; - } -} diff --git a/tests/ExistingTranslationsTest.php b/tests/ExistingTranslationsTest.php new file mode 100644 index 0000000..bbaa5c9 --- /dev/null +++ b/tests/ExistingTranslationsTest.php @@ -0,0 +1,24 @@ +assertEquals([ + "Hello" => "Hello", + "What's up" => "What's up!" + ], $existingTranslations->toArray()); + } +} diff --git a/tests/FileTranslationsTest.php b/tests/FileTranslationsTest.php new file mode 100644 index 0000000..9d698af --- /dev/null +++ b/tests/FileTranslationsTest.php @@ -0,0 +1,32 @@ +createMock(MissingTranslations::class); + $missingTranslations->method('toArray') + ->willReturn([ + "Missing translation" => "app.blade.php" + ]); + + $fileTranslations = new FileTranslations($path); + $fileTranslations->update($missingTranslations); + + $updatedTranslations = json_decode(file_get_contents($path), true); + + $this->assertEquals("", $updatedTranslations["Missing translation"]); + + // Restore original content + file_put_contents($path, $originalContent); + } +} diff --git a/tests/MissingTranslationsTest.php b/tests/MissingTranslationsTest.php new file mode 100644 index 0000000..936ea94 --- /dev/null +++ b/tests/MissingTranslationsTest.php @@ -0,0 +1,33 @@ +createMock(RequiredTranslations::class); + $requiredTranslations->method('toArray') + ->willReturn([ + "This will go in the JSON array" => "__.txt", + "lang.first_match" => "alt_lang.txt", + ]); + + $existingTranslations = $this->createMock(ExistingTranslations::class); + $existingTranslations->method("toArray") + ->willReturn([ + "lang.first_match" => "This translation exists so...", + ]); + + $missingTranslations = new MissingTranslations($requiredTranslations, $existingTranslations); + + $this->assertEquals([ + "This will go in the JSON array" => "__.txt", + ], $missingTranslations->toArray()); + } +} diff --git a/tests/RequiredLanguagesTest.php b/tests/RequiredLanguagesTest.php new file mode 100644 index 0000000..26ba971 --- /dev/null +++ b/tests/RequiredLanguagesTest.php @@ -0,0 +1,21 @@ +assertEquals(['es'], $requiredLanguages->toArray()); + } +} diff --git a/tests/RequiredTranslationsTest.php b/tests/RequiredTranslationsTest.php new file mode 100644 index 0000000..6216982 --- /dev/null +++ b/tests/RequiredTranslationsTest.php @@ -0,0 +1,31 @@ +assertEquals([ + 'This will go in the JSON array' => '__.txt', + 'lang.first_match' => 'alt_lang.txt', + 'lang_get.first' => 'lang_get.txt', + 'lang_get.second' => 'lang_get.txt', + 'trans.first_match' => 'trans.txt', + 'trans' => 'trans.txt', + 'trans.third_match' => 'trans.txt', + 'trans_choice.with_params' => 'trans_choice.txt', + ], $requiredTranslations->toArray()); + } +} diff --git a/tests/TestCase.php b/tests/TestCase.php index 9fd0df9..9d77652 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -1,8 +1,8 @@ translations(); - - $this->assertEquals([ - 'single' => [ - 'single' => ['This will go in the JSON array' => '', 'trans' => ''], - ], - 'group' => [ - 'lang' => [ - 'first_match' => '', - ], - 'lang_get' => ['first' => '', 'second' => ''], - 'trans' => ['first_match' => '', 'third_match' => ''], - 'trans_choice' => ['with_params' => ''], - ], - ], $matches); - $this->assertCount(2, $matches); - } - - protected function getEnvironmentSetUp($app) - { - $app['config']->set('langscanner.scan_paths', [__DIR__ . '/fixtures/scan-tests']); - $app['config']->set('langscanner.translation_methods', ['__', 'trans', 'trans_choice', '@lang', 'Lang::get']); - } -} diff --git a/tests/fixtures/lang/en/test.php b/tests/fixtures/lang/en/test.php deleted file mode 100644 index bd0b8ab..0000000 --- a/tests/fixtures/lang/en/test.php +++ /dev/null @@ -1,6 +0,0 @@ - 'Hello', - 'whats_up' => 'What\'s up!', -]; diff --git a/tests/fixtures/lang/es.json b/tests/fixtures/lang/es.json new file mode 100644 index 0000000..a1a9632 --- /dev/null +++ b/tests/fixtures/lang/es.json @@ -0,0 +1,5 @@ +{ + "Hello": "Hello", + "What's up": "What's up!", + "Missing translation": "" +} \ No newline at end of file diff --git a/tests/fixtures/lang/es/.gitignore b/tests/fixtures/lang/es/.gitignore deleted file mode 100644 index e69de29..0000000 diff --git a/tests/fixtures/scan-tests/__.txt b/tests/fixtures/test-files/__.txt similarity index 100% rename from tests/fixtures/scan-tests/__.txt rename to tests/fixtures/test-files/__.txt diff --git a/tests/fixtures/scan-tests/alt_lang.txt b/tests/fixtures/test-files/alt_lang.txt similarity index 100% rename from tests/fixtures/scan-tests/alt_lang.txt rename to tests/fixtures/test-files/alt_lang.txt diff --git a/tests/fixtures/scan-tests/lang_get.txt b/tests/fixtures/test-files/lang_get.txt similarity index 100% rename from tests/fixtures/scan-tests/lang_get.txt rename to tests/fixtures/test-files/lang_get.txt diff --git a/tests/fixtures/scan-tests/trans.txt b/tests/fixtures/test-files/trans.txt similarity index 100% rename from tests/fixtures/scan-tests/trans.txt rename to tests/fixtures/test-files/trans.txt diff --git a/tests/fixtures/scan-tests/trans_choice.txt b/tests/fixtures/test-files/trans_choice.txt similarity index 100% rename from tests/fixtures/scan-tests/trans_choice.txt rename to tests/fixtures/test-files/trans_choice.txt