diff --git a/.editorconfig b/.editorconfig
index 2e7acaf..0af7b6e 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -9,4 +9,7 @@ indent_size = 4
trim_trailing_whitespace = true
[*.md]
-trim_trailing_whitespace = false
\ No newline at end of file
+trim_trailing_whitespace = false
+
+[*.json]
+insert_final_newline = false
\ No newline at end of file
diff --git a/README.md b/README.md
index 8a66676..cc810a7 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,16 @@
-# Laravel Lang Installer
+
Laravel Lang Installer
+
+
+
+
+
+
+
+
+
+
+
+
This package helps us to quickly install the language files in a preferably fresh Laravel application.
@@ -12,11 +24,19 @@ composer require luisprmat/laravel-lang-installer --dev
## Usage
-After install a new laravel application with `Laravel >= 5.5` the package autodiscover system will register the new command `lang:add`.
+### Add new language
+After install a new laravel application with `Laravel >= 5.5` the package autodiscover system will register the new command `lang:add` and you can call with
-This command can take a unique argument (or none) that will be the short name of the language according to **ISO 15897**.
+```bash
+php artisan lang:add
+```
+where `` refers to the short name of any of the [supported languages](README.md#supported-languages)
+> ### *Warnings*
+> - **Add lang** action overwrites the language files so that you already had custom translations you could lose them.
+> - When adding a language this package first consults the `composer.json` file to copy only the translations of the supported packages that are installed ([Laravel Breeze](https://laravel.com/docs/8.x/starter-kits#laravel-breeze), [Laravel Cashier](https://laravel.com/docs/8.x/billing), [Laravel Fortify](https://laravel.com/docs/8.x/fortify) and [Laravel Jetstream](https://jetstream.laravel.com/2.x/introduction.html) are supported) `resources/lang/.json`. So it is good that you first install the supported packages that you will use and then run the command `php artisan lang:add `
+> - If this command does not receive arguments, the Spanish language [`es`] will be installed by default.
-If this command does not receive arguments, the Spanish language [`es`] will be installed by default.
+This command can take a unique argument (or none) that will be the short name of the language according to **ISO 15897**.
This command also modifies the key `locale` in the `config/app.php` file to set the default language as passed through the parameter.
@@ -51,12 +71,24 @@ php artisan lang:add pt_BR --no-default
php artisan lang:add ar --inline
```
-
+## Supported languages
+`af`, `ar`, `az`, `be`, `bg`, `bn`, `bs`, `ca`, `cs`, `cy`, `da`, `de`, `de_CH`
+, `el`, `es`, `et`, `eu`, `fa`, `fi`, `fil`, `fr`, `gl`, `he`, `hi`, `hr`, `hu`,
+`hy`, `id`, `is`, `it`, `ja`, `ka`, `kk`, `km`, `kn`, `ko`, `lt`, `lv`, `mk`, `
+mn`, `mr`, `ms`, `nb`, `ne`, `nl`, `nn`, `oc`, `pl`, `ps`, `pt`, `pt_BR`, `ro`,
+`ru`, `sc`, `si`, `sk`, `sl`, `sq`, `sr_Cyrl`, `sr_Latn`, `sr_Latn_ME`, `sv`, `s
+w`, `tg`, `th`, `tk`, `tl`, `tr`, `ug`, `uk`, `ur`, `uz_Cyrl`, `uz_Latn`, `vi`,
+`zh_CN`, `zh_HK`, `zh_TW`
## Contributing
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
-This package does not modify the translations, only copies them of [`laravel-lang/lang`](https://github.com/Laravel-Lang/lang/). So if you want to suggest changes in the translations you can make a PR to the [`laravel-lang/lang` package](https://github.com/Laravel-Lang/lang/blob/master/docs/contributing-to-dev.md)
+This package does not modify the translations, only copies them from [`laravel-lang/lang`](https://github.com/Laravel-Lang/lang/). So if you want to suggest changes in the translations you can make a PR to the [`laravel-lang/lang` package](https://github.com/Laravel-Lang/lang/blob/master/docs/contributing-to-dev.md)
## License
[MIT](LICENSE.md)
+
+## Todo
+
+- [ ] Allow merge translations instead of overwrite them.
+- [ ] Add Command `lang:update` to update translations and detect new installed packages to update their translations.
diff --git a/src/Console/InstallCommand.php b/src/Console/InstallCommand.php
index daec348..7c0d236 100644
--- a/src/Console/InstallCommand.php
+++ b/src/Console/InstallCommand.php
@@ -4,6 +4,8 @@
use Illuminate\Console\Command;
use Illuminate\Filesystem\Filesystem;
+use Illuminate\Support\Facades\File;
+use Illuminate\Support\Str;
class InstallCommand extends Command
{
@@ -13,15 +15,27 @@ class InstallCommand extends Command
protected $description = "Install translations for language 'locale' (default 'es')";
+ private array $supportedPackages = [
+ 'breeze' => 'laravel/breeze',
+ 'fortify' => 'laravel/fortify',
+ 'cashier' => 'laravel/cashier',
+ 'jetstream' => 'laravel/jetstream'
+ ];
+
public function handle()
{
$locale = (string)$this->argument('locale');
- if (!in_array($locale, $this->getLocales())) {
+ if (!in_array($locale, $this->getLocales(base_path('vendor/laravel-lang/lang/locales')))) {
$this->error("Language [{$locale}] is not supported!");
return;
}
+ if (!File::exists(base_path('composer.json'))) {
+ $this->error('composer.json not found!');
+ return;
+ }
+
(new Filesystem)->ensureDirectoryExists(resource_path("lang/{$locale}"));
copy(base_path("vendor/laravel-lang/lang/locales/{$locale}/auth.php"), resource_path("lang/{$locale}/auth.php"));
@@ -34,7 +48,14 @@ public function handle()
copy(base_path("vendor/laravel-lang/lang/locales/{$locale}/validation.php"), resource_path("lang/{$locale}/validation.php"));
}
- $this->loadJsonFile($locale);
+ $discoveredPackages = $this->discoveredPackages();
+
+ // Add 'fortify' translations if 'jetstream' is installed
+ if (in_array('jetstream', $discoveredPackages)) {
+ array_push($discoveredPackages, 'fortify');
+ }
+
+ $this->loadJsonFile($locale, $discoveredPackages);
if (!$this->option('no-default')) {
// Set config('app.locale')
@@ -43,6 +64,13 @@ public function handle()
} else {
$this->info("Language [{$locale}] installed successfully, but it isn't the default language.");
}
+
+ if (!empty($discoveredPackages)) {
+ $this->info(
+ 'Translations for ['. implode(', ', $discoveredPackages) .'] '
+ . Str::plural('package', count($discoveredPackages)) .' merged!'
+ );
+ }
}
/**
@@ -58,19 +86,40 @@ protected function pregReplaceInFile($search, $replace, $path)
file_put_contents($path, preg_replace($search, $replace, file_get_contents($path)));
}
- private function loadJsonFile($locale)
+ private function loadJsonFile($locale, $packages = [])
{
- copy(base_path("vendor/laravel-lang/lang/locales/{$locale}/{$locale}.json"), resource_path("lang/{$locale}.json"));
+ $baseSource = json_decode(File::get(base_path('vendor/laravel-lang/lang/source/en.json')));
+ $jsonLocale = json_decode(File::get(base_path("vendor/laravel-lang/lang/locales/{$locale}/{$locale}.json")), true);
+
+ $showTags = $baseSource;
+
+ foreach ($packages as $package) {
+ $showTags = array_merge(
+ $showTags,
+ json_decode(File::get(base_path("vendor/laravel-lang/lang/source/packages/{$package}.json")))
+ );
+ }
+
+ $showTags = array_unique($showTags);
+ sort($showTags);
+
+ $modify = array_filter($jsonLocale, function ($item) use ($showTags) {
+ return in_array($item, $showTags);
+ }, ARRAY_FILTER_USE_KEY);
+
+ $modifiedJson = json_encode($modify, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
+
+ File::put(resource_path("lang/{$locale}.json"), $modifiedJson);
}
/**
+ * @param string $path
* @return array
*/
- protected function getLocales(): array
+ protected function getLocales(string $path): array
{
$filesystem = new Filesystem;
- $path = base_path("vendor/laravel-lang/lang/locales");
$directories = $filesystem->directories($path);
$locales = [];
@@ -80,4 +129,24 @@ protected function getLocales(): array
}
return $locales;
}
+
+ /**
+ * Returns list of installed packages that are supported according to composer.json
+ *
+ * @return array
+ */
+ protected function discoveredPackages(): array
+ {
+ $composer = json_decode(File::get(base_path('composer.json')), true);
+
+ $jsonToCreate = array_keys(array_merge($composer['require'], $composer['require-dev']));
+
+ $packagesToInstall = array_filter($jsonToCreate, function ($package) {
+ return in_array($package, $this->supportedPackages);
+ });
+
+ return array_keys(array_filter($this->supportedPackages, function ($package) use ($packagesToInstall) {
+ return in_array($package, $packagesToInstall);
+ }));
+ }
}
diff --git a/tests/Feature/DiscoverPackagesTest.php b/tests/Feature/DiscoverPackagesTest.php
new file mode 100644
index 0000000..614ce5e
--- /dev/null
+++ b/tests/Feature/DiscoverPackagesTest.php
@@ -0,0 +1,69 @@
+app->setBasePath(__DIR__ . '/../fixtures');
+
+ File::ensureDirectoryExists(config_path());
+ File::copy(__DIR__ . '/../stubs/config/app.php', config_path('app.php'));
+ }
+
+ protected function tearDown(): void
+ {
+ parent::tearDown();
+ File::deleteDirectory(config_path());
+ File::deleteDirectory(resource_path());
+ File::delete(base_path('composer.json'));
+ }
+
+ /** @test */
+ function it_doesnt_execute_if_composer_json_doesnt_exist()
+ {
+ $this->artisan('lang:add')
+ ->expectsOutput('composer.json not found!')
+ ->assertExitCode(0);
+ }
+
+ /** @test */
+ function it_discovers_several_supported_packages_installed_from_composer_json()
+ {
+ File::put(base_path('composer.json'), $this->buildComposerWithDependencies(
+ ['"laravel/cashier": "^13.5"', '"package/other": "^2.0"'],
+ ['"laravel/breeze": "^1.4"', '"laravel/no-supported": "^1.0"']
+ ));
+
+ $command = $this->artisan('lang:add');
+ $command->expectsOutput('Translations for [breeze, cashier] packages merged!');
+ }
+
+ /** @test */
+ function it_discovers_one_supported_package_installed_from_composer_json_require_dev()
+ {
+ File::put(base_path('composer.json'), $this->buildComposerWithDependencies(
+ ['"package/other": "^2.0"'],
+ ['"laravel/breeze": "^1.4"', '"laravel/no-supported": "^1.0"']
+ ));
+
+ $command = $this->artisan('lang:add');
+ $command->expectsOutput('Translations for [breeze] package merged!');
+ }
+
+ /** @test */
+ function it_discovers_one_supported_package_installed_from_composer_json_require()
+ {
+ File::put(base_path('composer.json'), $this->buildComposerWithDependencies(
+ ['"laravel/cashier": "^13.5"']
+ ));
+
+ $command = $this->artisan('lang:add');
+ $command->expectsOutput('Translations for [cashier] package merged!');
+ }
+}
diff --git a/tests/Feature/InstallLanguageTest.php b/tests/Feature/InstallLanguageTest.php
new file mode 100644
index 0000000..109c6ff
--- /dev/null
+++ b/tests/Feature/InstallLanguageTest.php
@@ -0,0 +1,225 @@
+app->setBasePath(__DIR__ . '/../fixtures');
+
+ File::ensureDirectoryExists(config_path());
+ File::copy(__DIR__ . '/../stubs/config/app.php', config_path('app.php'));
+ File::put(base_path('composer.json'), $this->buildComposerWithDependencies(['"any/package": "^1.0"']));
+ }
+
+ protected function tearDown(): void
+ {
+ parent::tearDown();
+ File::deleteDirectory(config_path());
+ File::deleteDirectory(resource_path());
+ File::delete(base_path('composer.json'));
+ }
+
+ /** @test */
+ function it_installs_supported_language()
+ {
+ $this->assertFalse(File::exists(resource_path('lang/xx_GB')));
+ $this->assertFalse(File::exists(resource_path('lang/xx_GB/auth.php')));
+ $this->assertFalse(File::exists(resource_path('lang/xx_GB/passwords.php')));
+ $this->assertFalse(File::exists(resource_path('lang/xx_GB/pagination.php')));
+ $this->assertFalse(File::exists(resource_path('lang/xx_GB/validation.php')));
+ $this->assertFalse(File::exists(resource_path('lang/xx_GB.json')));
+
+ $this->artisan('lang:add xx_GB')
+ ->expectsOutput("Language [xx_GB] installed successfully as default.")
+ ->doesntExpectOutput("Language [es] installed successfully as default.");
+
+ $this->assertTrue(File::exists(resource_path('lang/xx_GB')));
+ $this->assertTrue(File::exists(resource_path('lang/xx_GB/auth.php')));
+ $this->assertTrue(File::exists(resource_path('lang/xx_GB/passwords.php')));
+ $this->assertTrue(File::exists(resource_path('lang/xx_GB/pagination.php')));
+ $this->assertTrue(File::exists(resource_path('lang/xx_GB/validation.php')));
+ $this->assertTrue(File::exists(resource_path('lang/xx_GB.json')));
+ }
+
+ /** @test */
+ function it_installs_supported_language_with_validation_inline()
+ {
+ $this->artisan('lang:add es --inline')
+ ->expectsOutput("Language [es] installed successfully as default.");
+
+ $this->assertStringContainsString(
+ 'El campo debe ser verdadero o falso.',
+ File::get(resource_path('lang/es/validation.php'))
+ );
+
+ $this->assertStringNotContainsString(
+ 'El campo :attribute debe tener un valor verdadero o falso.',
+ File::get(resource_path('lang/es/validation.php'))
+ );
+ }
+
+ /** @test */
+ function it_installs_spanish_language_by_default()
+ {
+ $this->artisan('lang:add')
+ ->expectsOutput("Language [es] installed successfully as default.");
+ }
+
+ /** @test */
+ function it_doesnt_install_language_if_not_supported()
+ {
+ $this->assertFalse(File::exists(resource_path('lang/no_valid')));
+ $this->artisan('lang:add no-valid')
+ ->expectsOutput("Language [no-valid] is not supported!");
+
+ $this->assertFalse(File::exists(resource_path('lang/no_valid')));
+
+ $this->artisan('lang:add es')
+ ->doesntExpectOutput("Language [es] is not supported!");
+ }
+
+ /** @test */
+ function it_modifies_config_app_locale_by_default()
+ {
+ $this->assertTrue(File::exists(config_path('app.php')));
+ $this->assertTrue(Str::contains(File::get(config_path('app.php')), "'locale' => 'en'"));
+
+ $this->artisan('lang:add xx_GB');
+
+ $this->assertTrue(File::exists(config_path('app.php')));
+ $this->assertTrue(Str::contains(File::get(config_path('app.php')), "'locale' => 'xx_GB'"));
+ $this->assertFalse(Str::contains(File::get(config_path('app.php')), "'locale' => 'en'"));
+ }
+
+ /** @test */
+ function it_doesnt_modify_config_app_locale_if_pass_no_default_option()
+ {
+ $this->assertTrue(File::exists(config_path('app.php')));
+ $this->assertTrue(Str::contains(File::get(config_path('app.php')), "'locale' => 'en'"));
+
+ $this->artisan('lang:add xx_GB --no-default');
+
+ $this->assertTrue(File::exists(config_path('app.php')));
+ $this->assertFalse(Str::contains(File::get(config_path('app.php')), "'locale' => 'xx_GB'"));
+ $this->assertTrue(Str::contains(File::get(config_path('app.php')), "'locale' => 'en'"));
+ }
+
+ /** @test */
+ function it_installs_json_locale_only_with_base_translations()
+ {
+ $this->artisan('lang:add es');
+ $expected = <<assertEquals(
+ $expected,
+ File::get(resource_path('lang/es.json'))
+ );
+
+ $this->artisan('lang:add xx_GB');
+ $expected = <<assertEquals(
+ $expected,
+ File::get(resource_path('lang/xx_GB.json'))
+ );
+ }
+
+ /** @test */
+ function it_installs_json_with_base_plus_discovered_packages_one()
+ {
+ File::put(base_path('composer.json'), $this->buildComposerWithDependencies(
+ ['"laravel/cashier": "^13.5"']
+ ));
+
+ $this->artisan('lang:add es');
+ $expected = <<assertEquals(
+ $expected,
+ File::get(resource_path('lang/es.json'))
+ );
+
+ }
+
+ /** @test */
+ function it_installs_json_with_base_plus_discovered_packages_other()
+ {
+ File::put(base_path('composer.json'), $this->buildComposerWithDependencies(
+ ['"laravel/breeze": "^1.4"']
+ ));
+
+ $this->artisan('lang:add es');
+ $expected = <<assertEquals(
+ $expected,
+ File::get(resource_path('lang/es.json'))
+ );
+
+ }
+
+ /** @test */
+ function it_installs_json_with_base_plus_discovered_packages_mixed()
+ {
+ File::put(base_path('composer.json'), $this->buildComposerWithDependencies(
+ ['"laravel/cashier": "^13.5"', '"laravel/breeze": "^1.4"']
+ ));
+
+ $this->artisan('lang:add es');
+ $expected = <<assertEquals(
+ $expected,
+ File::get(resource_path('lang/es.json'))
+ );
+
+ }
+}
diff --git a/tests/TestCase.php b/tests/TestCase.php
index 77889de..700bc88 100644
--- a/tests/TestCase.php
+++ b/tests/TestCase.php
@@ -5,7 +5,7 @@
use Luisprmat\LaravelLangInstaller\LangServiceProvider;
use Orchestra\Testbench\TestCase as BaseTestCase;
-class TestCase extends BaseTestCase
+abstract class TestCase extends BaseTestCase
{
protected function getPackageProviders($app)
{
@@ -14,10 +14,22 @@ protected function getPackageProviders($app)
];
}
- protected function getPackageAliases($app)
+ /**
+ * @param array $require
+ * @param array $requireDev
+ * @return string
+ */
+ protected function buildComposerWithDependencies(array $require = [], array $requireDev = []): string
{
- return [
- //
- ];
+ $composerString = '{"name":"luisprmat/package","require":{';
+ $composerString .= implode(',', $require);
+ $composerString .= '},"require-dev": {';
+ $composerString .= implode(',', $requireDev);
+ $composerString .= '}}';
+
+ return json_encode(
+ json_decode($composerString),
+ JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES
+ );
}
}
diff --git a/tests/Unit/PublishLanguageFilesTest.php b/tests/Unit/PublishLanguageFilesTest.php
deleted file mode 100644
index a0f5e0f..0000000
--- a/tests/Unit/PublishLanguageFilesTest.php
+++ /dev/null
@@ -1,58 +0,0 @@
-artisan('lang:add es')
- ->expectsOutput("Language [es] installed successfully as default.");
-
- $this->artisan('lang:add fr')
- ->expectsOutput("Language [fr] installed successfully as default.");
-
- $this->artisan('lang:add fr --no-default')
- ->expectsOutput("Language [fr] installed successfully, but it isn't the default language.");
- }
-
- /** @test */
- function validate_if_locale_directory_exists()
- {
- $locales = $this->getLocales();
-
- $this->artisan('lang:add no-valid')
- ->expectsOutput("Language [no-valid] is not supported!");
-
-// dd($locales);
- }
-
- /**
- * @return array
- */
- protected function getLocales(): array
- {
- $filesystem = new Filesystem;
-
- $path = __DIR__ . "/../../vendor/laravel-lang/lang/locales";
- $directories = $filesystem->directories($path);
-
- $locales = [];
-
- foreach ($directories as $directory) {
- $locales[] = $filesystem->name($directory);
- }
- return $locales;
- }
-}
diff --git a/tests/fixtures/.gitignore b/tests/fixtures/.gitignore
new file mode 100644
index 0000000..3fe1a10
--- /dev/null
+++ b/tests/fixtures/.gitignore
@@ -0,0 +1,3 @@
+*
+!vendor/*
+!.gitignore
diff --git a/tests/fixtures/vendor/laravel-lang/lang/locales/es/auth.php b/tests/fixtures/vendor/laravel-lang/lang/locales/es/auth.php
new file mode 100644
index 0000000..9a82999
--- /dev/null
+++ b/tests/fixtures/vendor/laravel-lang/lang/locales/es/auth.php
@@ -0,0 +1,5 @@
+ 'Estas credenciales no coinciden con nuestros registros.',
+];
diff --git a/tests/fixtures/vendor/laravel-lang/lang/locales/es/es.json b/tests/fixtures/vendor/laravel-lang/lang/locales/es/es.json
new file mode 100644
index 0000000..da10f38
--- /dev/null
+++ b/tests/fixtures/vendor/laravel-lang/lang/locales/es/es.json
@@ -0,0 +1,12 @@
+{
+ "Add Base": "Añadir base",
+ "Cancel both": "Cancelar ambos",
+ "Card cashier": "Tarjeta cashier",
+ "Changes Base": "Cambios base",
+ "Confirm Password breeze": "Confirmar contraseña breeze",
+ "Confirm your :amount payment cashier": "Confirme su pago de :amount cashier",
+ "If you already have an account, you may accept this invitation by clicking the button below: base": "Si ya tiene una cuenta, puede aceptar esta invitación haciendo clic en el botón de abajo: base",
+ "Log in breeze": "Iniciar sesión breeze",
+ "New :resource none": "Nuevo :resource ninguno",
+ "Whoops! all": "¡Ups! todo"
+}
\ No newline at end of file
diff --git a/tests/fixtures/vendor/laravel-lang/lang/locales/es/pagination.php b/tests/fixtures/vendor/laravel-lang/lang/locales/es/pagination.php
new file mode 100644
index 0000000..d8f0d19
--- /dev/null
+++ b/tests/fixtures/vendor/laravel-lang/lang/locales/es/pagination.php
@@ -0,0 +1,17 @@
+ 'Siguiente »',
+ 'previous' => '« Anterior',
+];
diff --git a/tests/fixtures/vendor/laravel-lang/lang/locales/es/passwords.php b/tests/fixtures/vendor/laravel-lang/lang/locales/es/passwords.php
new file mode 100644
index 0000000..7745e64
--- /dev/null
+++ b/tests/fixtures/vendor/laravel-lang/lang/locales/es/passwords.php
@@ -0,0 +1,20 @@
+ '¡Su contraseña ha sido restablecida!',
+ 'sent' => '¡Le hemos enviado por correo electrónico el enlace para restablecer su contraseña!',
+ 'throttled' => 'Por favor espere antes de intentar de nuevo.',
+ 'token' => 'El token de restablecimiento de contraseña es inválido.',
+ 'user' => 'No encontramos ningún usuario con ese correo electrónico.',
+];
diff --git a/tests/fixtures/vendor/laravel-lang/lang/locales/es/validation-inline.php b/tests/fixtures/vendor/laravel-lang/lang/locales/es/validation-inline.php
new file mode 100644
index 0000000..ca7c0f3
--- /dev/null
+++ b/tests/fixtures/vendor/laravel-lang/lang/locales/es/validation-inline.php
@@ -0,0 +1,12 @@
+ 'Debe ser una fecha anterior o igual a :date.',
+ 'between' => [
+ 'array' => 'El contenido debe tener entre :min y :max elementos.',
+ 'file' => 'Este archivo debe ser entre :min y :max kilobytes.',
+ 'numeric' => 'Este valor debe ser entre :min y :max.',
+ 'string' => 'El texto debe ser entre :min y :max caracteres.',
+ ],
+ 'boolean' => 'El campo debe ser verdadero o falso.',
+];
diff --git a/tests/fixtures/vendor/laravel-lang/lang/locales/es/validation.php b/tests/fixtures/vendor/laravel-lang/lang/locales/es/validation.php
new file mode 100644
index 0000000..ab23b4b
--- /dev/null
+++ b/tests/fixtures/vendor/laravel-lang/lang/locales/es/validation.php
@@ -0,0 +1,12 @@
+ ':attribute debe ser una fecha anterior o igual a :date.',
+ 'between' => [
+ 'array' => ':attribute tiene que tener entre :min - :max elementos.',
+ 'file' => ':attribute debe pesar entre :min - :max kilobytes.',
+ 'numeric' => ':attribute tiene que estar entre :min - :max.',
+ 'string' => ':attribute tiene que tener entre :min - :max caracteres.',
+ ],
+ 'boolean' => 'El campo :attribute debe tener un valor verdadero o falso.',
+];
diff --git a/tests/fixtures/vendor/laravel-lang/lang/locales/xx_GB/auth.php b/tests/fixtures/vendor/laravel-lang/lang/locales/xx_GB/auth.php
new file mode 100644
index 0000000..34016cd
--- /dev/null
+++ b/tests/fixtures/vendor/laravel-lang/lang/locales/xx_GB/auth.php
@@ -0,0 +1,5 @@
+ 'These credentials do not match our records.',
+];
diff --git a/tests/fixtures/vendor/laravel-lang/lang/locales/xx_GB/pagination.php b/tests/fixtures/vendor/laravel-lang/lang/locales/xx_GB/pagination.php
new file mode 100644
index 0000000..d481411
--- /dev/null
+++ b/tests/fixtures/vendor/laravel-lang/lang/locales/xx_GB/pagination.php
@@ -0,0 +1,19 @@
+ '« Previous',
+ 'next' => 'Next »',
+
+];
diff --git a/tests/fixtures/vendor/laravel-lang/lang/locales/xx_GB/passwords.php b/tests/fixtures/vendor/laravel-lang/lang/locales/xx_GB/passwords.php
new file mode 100644
index 0000000..2345a56
--- /dev/null
+++ b/tests/fixtures/vendor/laravel-lang/lang/locales/xx_GB/passwords.php
@@ -0,0 +1,22 @@
+ 'Your password has been reset!',
+ 'sent' => 'We have emailed your password reset link!',
+ 'throttled' => 'Please wait before retrying.',
+ 'token' => 'This password reset token is invalid.',
+ 'user' => "We can't find a user with that email address.",
+
+];
diff --git a/tests/fixtures/vendor/laravel-lang/lang/locales/xx_GB/validation-inline.php b/tests/fixtures/vendor/laravel-lang/lang/locales/xx_GB/validation-inline.php
new file mode 100644
index 0000000..bb32573
--- /dev/null
+++ b/tests/fixtures/vendor/laravel-lang/lang/locales/xx_GB/validation-inline.php
@@ -0,0 +1,12 @@
+ 'This must be a date before or equal to :date.',
+ 'between' => [
+ 'numeric' => 'This value must be between :min and :max.',
+ 'file' => 'This file must be between :min and :max kilobytes.',
+ 'string' => 'This string must be between :min and :max characters.',
+ 'array' => 'This content must have between :min and :max items.',
+ ],
+ 'boolean' => 'This field must be true or false.',
+];
diff --git a/tests/fixtures/vendor/laravel-lang/lang/locales/xx_GB/validation.php b/tests/fixtures/vendor/laravel-lang/lang/locales/xx_GB/validation.php
new file mode 100644
index 0000000..049dace
--- /dev/null
+++ b/tests/fixtures/vendor/laravel-lang/lang/locales/xx_GB/validation.php
@@ -0,0 +1,12 @@
+ 'The :attribute must be a date before or equal to :date.',
+ 'between' => [
+ 'numeric' => 'The :attribute must be between :min and :max.',
+ 'file' => 'The :attribute must be between :min and :max kilobytes.',
+ 'string' => 'The :attribute must be between :min and :max characters.',
+ 'array' => 'The :attribute must have between :min and :max items.',
+ ],
+ 'boolean' => 'The :attribute field must be true or false.',
+];
diff --git a/tests/fixtures/vendor/laravel-lang/lang/locales/xx_GB/xx_GB.json b/tests/fixtures/vendor/laravel-lang/lang/locales/xx_GB/xx_GB.json
new file mode 100644
index 0000000..07c8f60
--- /dev/null
+++ b/tests/fixtures/vendor/laravel-lang/lang/locales/xx_GB/xx_GB.json
@@ -0,0 +1,12 @@
+{
+ "Add Base": "Add base",
+ "Cancel both": "Cancel both",
+ "Card cashier": "Card cashier",
+ "Changes Base": "Changes base",
+ "Confirm Password breeze": "Confirm Password breeze",
+ "Confirm your :amount payment cashier": "Confirm your :amount payment cashier",
+ "If you already have an account, you may accept this invitation by clicking the button below: base": "If you already have an account, you may accept this invitation by clicking the button below: base",
+ "Log in breeze": "Log in breeze",
+ "New :resource none": "Nuevo :resource none",
+ "Whoops! all": "Whoops! all"
+}
diff --git a/tests/fixtures/vendor/laravel-lang/lang/source/en.json b/tests/fixtures/vendor/laravel-lang/lang/source/en.json
new file mode 100644
index 0000000..1dd7161
--- /dev/null
+++ b/tests/fixtures/vendor/laravel-lang/lang/source/en.json
@@ -0,0 +1,6 @@
+[
+ "Add Base",
+ "Changes Base",
+ "If you already have an account, you may accept this invitation by clicking the button below: base",
+ "Whoops! all"
+]
diff --git a/tests/fixtures/vendor/laravel-lang/lang/source/packages/breeze.json b/tests/fixtures/vendor/laravel-lang/lang/source/packages/breeze.json
new file mode 100644
index 0000000..92cb6c8
--- /dev/null
+++ b/tests/fixtures/vendor/laravel-lang/lang/source/packages/breeze.json
@@ -0,0 +1,6 @@
+[
+ "Cancel both",
+ "Confirm Password breeze",
+ "Log in breeze",
+ "Whoops! all"
+]
diff --git a/tests/fixtures/vendor/laravel-lang/lang/source/packages/cashier.json b/tests/fixtures/vendor/laravel-lang/lang/source/packages/cashier.json
new file mode 100644
index 0000000..71bc1e3
--- /dev/null
+++ b/tests/fixtures/vendor/laravel-lang/lang/source/packages/cashier.json
@@ -0,0 +1,6 @@
+[
+ "Cancel both",
+ "Card cashier",
+ "Confirm your :amount payment cashier",
+ "Whoops! all"
+]
diff --git a/tests/stubs/config/app.php b/tests/stubs/config/app.php
new file mode 100644
index 0000000..ac791e6
--- /dev/null
+++ b/tests/stubs/config/app.php
@@ -0,0 +1,28 @@
+ 'First Key',
+
+ /*
+ |--------------------------------------------------------------------------
+ | Application Locale Configuration
+ |--------------------------------------------------------------------------
+ |
+ | Comment
+ |
+ */
+
+ 'locale' => 'en',
+
+ /*
+ |--------------------------------------------------------------------------
+ | Comment key 3
+ |--------------------------------------------------------------------------
+ |
+ | Comment
+ |
+ */
+
+ 'other' => 'other key'
+
+];