diff --git a/.travis.yml b/.travis.yml index abd4efe..2600028 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,15 +2,14 @@ language: php sudo: false php: - - 5.4 - - 5.5 - - 5.6 - - hhvm + - 7.2 + - 7.3 + - 7.4 before_script: - composer install --dev - - phpunit --coverage-clover=coverage.clover + - ./vendor/bin/phpunit --coverage-clover=coverage.clover - wget https://scrutinizer-ci.com/ocular.phar - php ocular.phar code-coverage:upload --format=php-clover coverage.clover -script: phpunit +script: ./vendor/bin/phpunit diff --git a/README.md b/README.md index 76d76d0..57e23e6 100644 --- a/README.md +++ b/README.md @@ -5,20 +5,19 @@ laravel-js-localization Simple, ease-to-use and flexible package for the [Laravel](http://laravel.com/) web framework. Allows you to use localized messages of the Laravel webapp (see `resources/lang` directory) in your Javascript code. You may easily configure which messages you need to export. +**⚠️ Looking for a new maintainer. Please contact me if you are interested.** -News ----- -A major bug when using the package with Laravel 5 has been fixed. - -Additionally, the `master` branch has been dropped. Use the branch that matches your framework version: +Branches +-------- - Laravel | Branch -:--------|:------- - 5.x | laravel-5 - 4.2 | laravel-4.2 - 4.1 | laravel-4.1 (near end of life) - 4.0 | laravel-4.0 (end of life) + Laravel | Branch +:----------|:------- + 8 | laravel-8 + 7 | laravel-7 + 6 | laravel-6 + 5.8 | laravel-5.8 + 5.0 - 5.7 | laravel-5 (end of life) Installation @@ -28,7 +27,7 @@ Add the following line to the `require` section of your Laravel webapp's `compos ```javascript "require": { - "andywer/js-localization": "dev-laravel-5" // "dev-laravel-4.1", "dev-laravel-4.2" for Laravel 4 + "andywer/js-localization": "dev-laravel-6" // see table above } ``` @@ -83,16 +82,20 @@ return [ * ] */ - // Set the keys of config properties you want to use in javascript. - // Caution: Do not expose any configuration values that should be kept privately! - 'config' => [ - 'app.debug' - ], + // Set the keys of config properties you want to use in javascript. + // Caution: Do not expose any configuration values that should be kept privately! + 'config' => [ + 'app.debug' + ], - // Disables the config cache if set to true, so you don't have to run `php artisan js-localization:refresh` - // each time you change configuration files. - // Attention: Should not be used in production mode due to decreased performance. - 'disable_config_cache' => false, + // Disables the config cache if set to true, so you don't have to run `php artisan js-localization:refresh` + // each time you change configuration files. + // Attention: Should not be used in production mode due to decreased performance. + 'disable_config_cache' => false, + + // Split up the exported messages.js file into separate files for each locale. + // This is to ensue faster loading times so one doesn't have to load translations for _all_ languages. + 'split_export_files' => true, ]; ``` @@ -104,6 +107,10 @@ The messages configuration will be cached when the JsLocalizationController is u Usage ----- +The translation resources for JavaScript can either be served by your Laravel app at run-time or they can be pre-generated as static JavaScript files, allowing you to serve them straight from your web server or CDN or to be included in your build process. + +### Run-time generation + You just need to add the necessary ` - + + @if(Config::get('js-localization.config')) - + @endif - @stop @section('js-localization.head.all_in_one') - - + @stop diff --git a/src/Caching/ConfigCachingService.php b/src/Caching/ConfigCachingService.php index 2977504..1002baf 100644 --- a/src/Caching/ConfigCachingService.php +++ b/src/Caching/ConfigCachingService.php @@ -1,17 +1,29 @@ createConfigJson(); $this->refreshCacheUsing($configJson); } /** - * @return string The JSON-encoded config exports. + * Returns the config (already JSON encoded). + * Refreshes the cache if necessary. + * + * @param bool $noCache (optional) Defines if cache should be ignored. + * @return mixed|string string The JSON-encoded config exports. */ - public function getConfigJson() + public function getConfigJson($noCache = false) { - if ($this->isDisabled()) { + if ($noCache || $this->isDisabled()) { return $this->createConfigJson(); } else { return $this->getData(); diff --git a/src/Caching/MessageCachingService.php b/src/Caching/MessageCachingService.php index 3add5bf..3f66e1e 100644 --- a/src/Caching/MessageCachingService.php +++ b/src/Caching/MessageCachingService.php @@ -1,12 +1,16 @@ getData(); + if ($noCache) { + return $this->createMessagesJson(); + } else { + return $this->getData(); + } } /** - * Refreshs the cache item containing the JSON encoded + * Refreshes the cache item containing the JSON encoded * messages object. - * Fires the 'JsLocalization.refresh' event. + * Fires the 'JsLocalization.registerMessages' event. * * @return void */ public function refreshCache() { - Event::fire('JsLocalization.registerMessages'); + Event::dispatch('JsLocalization.registerMessages'); + + $messagesJSON = $this->createMessagesJson(); + $this->refreshCacheUsing($messagesJSON); + } + /** + * @return string + */ + protected function createMessagesJson() + { $locales = $this->getLocales(); $messageKeys = $this->getMessageKeys(); $translatedMessages = $this->getTranslatedMessagesForLocales($messageKeys, $locales); - $this->refreshCacheUsing(json_encode($translatedMessages)); + return json_encode($translatedMessages); } /** @@ -104,7 +122,7 @@ protected function getTranslatedMessages(array $messageKeys, $locale) $translatedMessages = []; foreach ($messageKeys as $key) { - $translation = Lang::get($key, [], $locale); + $translation = __($key, [], $locale); if (is_array($translation)) { $flattened = $this->flattenTranslations($translation, $key.'.'); @@ -157,5 +175,4 @@ protected function getMessageKeys() return $messageKeys; } - } diff --git a/src/Console/ExportCommand.php b/src/Console/ExportCommand.php new file mode 100644 index 0000000..79c7ca2 --- /dev/null +++ b/src/Console/ExportCommand.php @@ -0,0 +1,170 @@ +option('no-cache'); + if ($noCache === true) $this->line('Exporting messages and config...'); + else $this->line('Refreshing and exporting the message and config cache...'); + + $locales = Config::get('js-localization.locales'); + + if(!is_array($locales)) { + throw new ConfigException('Please set the "locales" config! See https://github.com/andywer/laravel-js-localization#configuration'); + } + + if ($noCache === false) MessageCachingService::refreshCache(); + $messagesFilePath = $this->createPath('messages.js'); + $this->generateMessagesFile($messagesFilePath, $noCache); + + if ($noCache === false) ConfigCachingService::refreshCache(); + $configFilePath = $this->createPath('config.js'); + $this->generateConfigFile($configFilePath, $noCache); + } + + /** + * Execute the console command. + * Compatibility with previous Laravel 5.x versions. + * + * @return void + * @throws ConfigException + */ + public function fire() + { + $this->handle(); + } + + /** + * Create full file path. + * This method will also generate the directories if they don't exist already. + * + * @var string $filename + * + * @return string $path + */ + public function createPath($filename) + { + $dir = Config::get('js-localization.storage_path'); + if (!is_dir($dir)) { + mkdir($dir, 0777, true); + } + + return $dir . $filename; + } + + /** + * Generate the messages file. + * + * @param string $path + * @param bool $noCache + */ + public function generateMessagesFile($path, $noCache = false) + { + $splitFiles = Config::get('js-localization.split_export_files'); + $messages = MessageCachingService::getMessagesJson($noCache); + + if ($splitFiles) { + $this->generateMessageFiles(File::dirname($path), $messages); + } + + $contents = 'Lang.addMessages(' . $messages . ');'; + + File::put($path, $contents); + + $this->line("Generated $path"); + } + + /** + * Generate the lang-{locale}.js files + * + * @param string $path Directory to where we will store the files + * @param string $messages JSON string of messages + */ + protected function generateMessageFiles(string $path, string $messages) + { + $locales = Config::get('js-localization.locales'); + $messages = json_decode($messages, true); + + foreach ($locales as $locale) { + $fileName = $path . "/lang-{$locale}.js"; + + if (key_exists($locale, $messages)) { + $content = 'Lang.addMessages(' . json_encode([$locale => $messages[$locale]], JSON_PRETTY_PRINT) . ');'; + + File::put($fileName, $content); + $this->line("Generated $fileName"); + } + } + } + + /** + * Generate the config file. + * + * @param string $path + * @param bool $noCache + */ + public function generateConfigFile($path, $noCache = false) + { + $config = ConfigCachingService::getConfigJson($noCache); + if ($config === '{}') { + $this->line('No config specified. Config not written to file.'); + return; + } + + $contents = 'Config.addConfig(' . $config . ');'; + + File::put($path, $contents); + + $this->line("Generated $path"); + } +} diff --git a/src/Console/RefreshCommand.php b/src/Console/RefreshCommand.php index b978871..376345d 100644 --- a/src/Console/RefreshCommand.php +++ b/src/Console/RefreshCommand.php @@ -11,7 +11,6 @@ class RefreshCommand extends Command { - /** * The console command name. * @@ -32,7 +31,7 @@ class RefreshCommand extends Command * @return void * @throws ConfigException */ - public function fire() + public function handle() { $this->line('Refreshing the message cache...'); @@ -45,5 +44,16 @@ public function fire() MessageCachingService::refreshCache(); ConfigCachingService::refreshCache(); } - + + /** + * Execute the console command. + * Compatibility with previous Laravel 5.x versions. + * + * @return void + * @throws ConfigException + */ + public function fire() + { + $this->handle(); + } } diff --git a/src/Facades/ConfigCachingService.php b/src/Facades/ConfigCachingService.php index 7cb4f44..5fa8a31 100644 --- a/src/Facades/ConfigCachingService.php +++ b/src/Facades/ConfigCachingService.php @@ -17,7 +17,7 @@ * * @method static void refreshCache() * @method static \DateTime getLastRefreshTimestamp() - * @method static string getConfigJson() + * @method static string getConfigJson(bool $noCache = false) * @method static bool isDisabled() * @method static void public function refreshCache() */ diff --git a/src/Facades/MessageCachingService.php b/src/Facades/MessageCachingService.php index cfafde5..530434b 100644 --- a/src/Facades/MessageCachingService.php +++ b/src/Facades/MessageCachingService.php @@ -9,7 +9,7 @@ * * @method static void refreshCache() * @method static \DateTime getLastRefreshTimestamp() - * @method static string getMessagesJson() + * @method static string getMessagesJson(bool $noCache = false) * @method static void public function refreshCache() */ class MessageCachingService extends Facade diff --git a/src/JsLocalizationServiceProvider.php b/src/JsLocalizationServiceProvider.php index 3891fad..ef11f0f 100644 --- a/src/JsLocalizationServiceProvider.php +++ b/src/JsLocalizationServiceProvider.php @@ -7,6 +7,7 @@ use View; use Illuminate\Support\ServiceProvider; use Illuminate\Support\Facades\File; +use JsLocalization\Console\ExportCommand; use JsLocalization\Console\RefreshCommand; class JsLocalizationServiceProvider extends ServiceProvider { @@ -28,6 +29,10 @@ public function boot() $this->publishes([ __DIR__.'/../config/config.php' => config_path('js-localization.php') ]); + + $this->publishes([ + __DIR__.'/../public/js/localization.min.js' => public_path('vendor/js-localization/js-localization.min.js'), + ], 'public'); $this->mergeConfigFrom( __DIR__.'/../config/config.php', 'js-localization' @@ -36,6 +41,7 @@ public function boot() $this->loadViewsFrom(__DIR__.'/../resources/views', 'js-localization'); $this->registerRefreshCommand(); + $this->registerExportCommand(); } /** @@ -64,7 +70,7 @@ public function provides() */ private function registerRefreshCommand() { - $this->app['js-localization.refresh'] = $this->app->share(function() + $this->app->singleton('js-localization.refresh', function() { return new RefreshCommand; }); @@ -72,4 +78,17 @@ private function registerRefreshCommand() $this->commands('js-localization.refresh'); } + /** + * Register js-localization.export + */ + private function registerExportCommand() + { + $this->app->singleton('js-localization.export', function() + { + return new ExportCommand; + }); + + $this->commands('js-localization.export'); + } + } diff --git a/src/Utils/Helper.php b/src/Utils/Helper.php index 09de27a..f41e462 100644 --- a/src/Utils/Helper.php +++ b/src/Utils/Helper.php @@ -2,13 +2,13 @@ namespace JsLocalization\Utils; use App; -use Event; +use Illuminate\Support\Facades\Event; use Illuminate\Support\Facades\File; use JsLocalization\Exceptions\FileNotFoundException; class Helper { - + /** * Array of message keys. A set of messages that are * supposed to be exported to the JS code in addition @@ -192,4 +192,4 @@ private function prefix($prefix) return $prefix; } -} \ No newline at end of file +} diff --git a/tests/JsLocalization/Caching/ConfigCachingServiceTest.php b/tests/JsLocalization/Caching/ConfigCachingServiceTest.php index 81c2e47..bbc0351 100644 --- a/tests/JsLocalization/Caching/ConfigCachingServiceTest.php +++ b/tests/JsLocalization/Caching/ConfigCachingServiceTest.php @@ -5,7 +5,7 @@ class ConfigCachingServiceTest extends TestCase { - public function setUp() + public function setUp(): void { parent::setUp(); @@ -13,7 +13,7 @@ public function setUp() Cache::forget(JsLocalization\Caching\ConfigCachingService::CACHE_TIMESTAMP_KEY); } - public function tearDown() + public function tearDown(): void { m::close(); diff --git a/tests/JsLocalization/Caching/MessageCachingServiceTest.php b/tests/JsLocalization/Caching/MessageCachingServiceTest.php index 88b112e..e1d4895 100644 --- a/tests/JsLocalization/Caching/MessageCachingServiceTest.php +++ b/tests/JsLocalization/Caching/MessageCachingServiceTest.php @@ -6,7 +6,7 @@ class MessageCachingServiceTest extends TestCase { - public function setUp() + public function setUp(): void { parent::setUp(); @@ -14,7 +14,7 @@ public function setUp() Cache::forget(JsLocalization\Caching\MessageCachingService::CACHE_TIMESTAMP_KEY); } - public function tearDown() + public function tearDown(): void { m::close(); @@ -54,7 +54,11 @@ public function testGetLastRefreshTimestamp() public function testRefreshMessageCacheEvent() { - Event::shouldReceive('fire')->once()->with('JsLocalization.registerMessages'); + $this->addToAssertionCount( + \Mockery::getContainer()->mockery_getExpectationCount() + ); + + Event::shouldReceive('dispatch')->once()->with('JsLocalization.registerMessages'); MessageCachingService::refreshCache(); } diff --git a/tests/JsLocalization/Console/RefreshCommandTest.php b/tests/JsLocalization/Console/RefreshCommandTest.php index 1bf148d..5a6dcf7 100644 --- a/tests/JsLocalization/Console/RefreshCommandTest.php +++ b/tests/JsLocalization/Console/RefreshCommandTest.php @@ -5,13 +5,7 @@ class RefreshCommandTest extends TestCase { - - public function setUp() - { - parent::setUp(); - } - - public function tearDown() + public function tearDown(): void { m::close(); @@ -26,8 +20,7 @@ public function testNoLocalesConfigException() $config->shouldReceive('get')->with('js-localization.locales') ->andReturn(null); - - $this->setExpectedException('Exception'); + $this->expectException(Exception::class); $this->runCommand(); } @@ -36,8 +29,10 @@ protected function runCommand() { $cmd = new RefreshCommand(); + $cmd->setLaravel(app(\Illuminate\Contracts\Foundation\Application::class)); + $cmd->run( - new Symfony\Component\Console\Input\ArrayInput(['package' => 'foo']), + new Symfony\Component\Console\Input\ArrayInput([]), new Symfony\Component\Console\Output\NullOutput ); } diff --git a/tests/JsLocalization/Http/Responses/StaticFileResponseTest.php b/tests/JsLocalization/Http/Responses/StaticFileResponseTest.php index e5c8e54..bfcc067 100644 --- a/tests/JsLocalization/Http/Responses/StaticFileResponseTest.php +++ b/tests/JsLocalization/Http/Responses/StaticFileResponseTest.php @@ -5,9 +5,10 @@ class StaticFileResponseTest extends TestCase { - protected $testFilePath, $testFileContent; + protected $testFilePath; + protected $testFileContent; - public function setUp() + public function setUp(): void { parent::setUp(); @@ -32,9 +33,9 @@ public function testServingFile() public function testExceptionHandling() { $filePath = "/tmp/x/y/z/does-not-exist"; - $this->setExpectedException('Exception', "Cannot read file: $filePath"); - $response = new StaticFileResponse($filePath); + $this->expectException(Exception::class, "Cannot read file: $filePath"); + + new StaticFileResponse($filePath); } } -?> diff --git a/tests/JsLocalization/Utils/JsLocalizationHelperTest.php b/tests/JsLocalization/Utils/JsLocalizationHelperTest.php index 9544fa7..c03d901 100644 --- a/tests/JsLocalization/Utils/JsLocalizationHelperTest.php +++ b/tests/JsLocalization/Utils/JsLocalizationHelperTest.php @@ -59,7 +59,7 @@ protected function setUpTestMessagesFile($filePath) return $prefix; } - public function setUp() + public function setUp(): void { parent::setUp(); @@ -70,7 +70,7 @@ public function setUp() touch($this->tmpFilePath); } - public function tearDown() + public function tearDown(): void { unlink($this->tmpFilePath); @@ -120,7 +120,7 @@ public function testEventBasedAdding() $this->assertEquals([], JsLocalizationHelper::getAdditionalMessages()); - Event::fire('JsLocalization.registerMessages'); + Event::dispatch('JsLocalization.registerMessages'); $this->assertEquals( $this->additionalMessageKeysFlat, @@ -135,7 +135,7 @@ public function testEventBasedAdding() JsLocalizationHelper::addMessagesToExport(['another']); }); - Event::fire('JsLocalization.registerMessages'); + Event::dispatch('JsLocalization.registerMessages'); $this->assertEquals( array_merge($this->additionalMessageKeysFlat, ['another']), @@ -164,8 +164,8 @@ public function testAddMessageFileToExportExceptionHandling() { $filePath = "/tmp/x/y/z/does-not-exist"; - $this->setExpectedException( - 'JsLocalization\Exceptions\FileNotFoundException', + $this->expectException( + JsLocalization\Exceptions\FileNotFoundException::class, "File not found: $filePath" ); diff --git a/tests/TestCase.php b/tests/TestCase.php index 395e484..a551240 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -37,7 +37,7 @@ class TestCase extends Orchestra\Testbench\TestCase ]; - public function setUp() + public function setUp(): void { parent::setUp(); @@ -46,7 +46,7 @@ public function setUp() $this->mockLang(); } - public function tearDown() + public function tearDown(): void { m::close();