Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added support for packages loadTranslationsFrom method #149

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 60 additions & 31 deletions src/Mariuzzo/LaravelJsLocalization/Generators/LangJsGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Illuminate\Filesystem\Filesystem as File;
use Illuminate\Support\Str;
use JShrink\Minifier;
use Illuminate\Support\Arr;

/**
* The LangJsGenerator class.
Expand Down Expand Up @@ -35,6 +36,12 @@ class LangJsGenerator
*/
protected $messagesIncluded = [];

/**
* List of namespace index of packages language folder
* @var array
*/
protected $packagesMessages = [];

/**
* Name of the domain in which all string-translation should be stored under.
* More about string-translation: https://laravel.com/docs/master/localization#retrieving-translation-strings
Expand All @@ -46,14 +53,17 @@ class LangJsGenerator
/**
* Construct a new LangJsGenerator instance.
*
* @param File $file The file service instance.
* @param File $file The file service instance.
* @param string $sourcePath The source path of the language files.
* @param array $messagesIncluded
* @param array $packagesMessages
*/
public function __construct(File $file, $sourcePath, $messagesIncluded = [])
public function __construct(File $file, $sourcePath, $messagesIncluded = [], $packagesMessages = [])
{
$this->file = $file;
$this->sourcePath = $sourcePath;
$this->messagesIncluded = $messagesIncluded;
$this->packagesMessages = $packagesMessages;
}

/**
Expand Down Expand Up @@ -125,37 +135,17 @@ protected function getMessages($noSort)
throw new \Exception("${path} doesn't exists!");
}

foreach ($this->file->allFiles($path) as $file) {
$pathName = $file->getRelativePathName();
$extension = $this->file->extension($pathName);
if ($extension != 'php' && $extension != 'json') {
continue;
}

if ($this->isMessagesExcluded($pathName)) {
continue;
}

$key = substr($pathName, 0, -4);
$key = str_replace('\\', '.', $key);
$key = str_replace('/', '.', $key);

if (Str::startsWith($key, 'vendor')) {
$key = $this->getVendorKey($key);
foreach($this->packagesMessages as $namespace => $langPath)
{
foreach ($this->file->allFiles($langPath) as $file)
{
$this->processFile($messages, $file, $namespace);
}
}

$fullPath = $path.DIRECTORY_SEPARATOR.$pathName;
if ($extension == 'php') {
$messages[$key] = include $fullPath;
} else {
$key = $key.$this->stringsDomain;
$fileContent = file_get_contents($fullPath);
$messages[$key] = json_decode($fileContent, true);

if (json_last_error() !== JSON_ERROR_NONE) {
throw new InvalidArgumentException('Error while decode ' . basename($fullPath) . ': ' . json_last_error_msg());
}
}
foreach ($this->file->allFiles($path) as $file)
{
$this->processFile($messages, $file);
}

if (!$noSort)
Expand Down Expand Up @@ -214,4 +204,43 @@ private function getVendorKey($key)

return $keyParts[2] .'.'. $keyParts[1] . '::' . $keyParts[3];
}

private function processFile(&$messages, $file, $namespace = null)
{
$pathName = $file->getRelativePathName();
$extension = $file->getExtension();
if ($extension != 'php' && $extension != 'json') {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd change it to for readability
$supportedExtensions = ['json', 'php'];
!in_array($extension, $supportedExtensions)

I'm thinking laravel actually does this already somehow, maybe we should look into
The Illuminate\Translation\Translator uses Illuminate\Translation\FileLoaderto load/process files. Maybe we can use some of that logic

return;
}

if ($this->isMessagesExcluded($pathName)) {
return;
}

$key = substr($pathName, 0, -4);
$key = str_replace('\\', '.', $key);
$key = str_replace('/', '.', $key);

if ($namespace !== null)
{
$key = 'vendor.' . $namespace . '.'. $key;
}

if (Str::startsWith($key, 'vendor')) {
$key = $this->getVendorKey($key);
}

$fullPath = $file->getRealPath();
if ($extension == 'php') {
$messages[$key] = array_replace(Arr::get($messages,$key,[]), include $fullPath);
Copy link

@StefanPrintezis StefanPrintezis Sep 8, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you need to check the include $fullPath actually returns a filled array before adding it.

You can add a test for it for trying to include a translation file, that isn't a valid translation file.

} else {
$key = $key.$this->stringsDomain;
$fileContent = file_get_contents($fullPath);
$messages[$key] = json_decode($fileContent, true);

if (json_last_error() !== JSON_ERROR_NONE) {
throw new InvalidArgumentException('Error while decode ' . basename($fullPath) . ': ' . json_last_error_msg());
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,15 +68,17 @@ public function register()
$app = $this->app;
$laravelMajorVersion = (int) $app::VERSION;

$translator = $app->make('Illuminate\Translation\Translator');
$files = $app['files'];

if ($laravelMajorVersion === 4) {
$langs = $app['path.base'].'/app/lang';
} elseif ($laravelMajorVersion >= 5) {
$langs = $app['path.base'].'/resources/lang';
}
$messages = $app['config']->get('localization-js.messages');
$generator = new Generators\LangJsGenerator($files, $langs, $messages);
$messages = $app['config']->get('localization-js.messages', []);
$packagesLanguages = $translator->getLoader()->namespaces();
$generator = new Generators\LangJsGenerator($files, $langs, $messages, $packagesLanguages);

return new Commands\LangJsCommand($generator);
});
Expand Down
8 changes: 8 additions & 0 deletions tests/fixtures/packages/nonameinc/lang/en/messages.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

return array(

'important_data' => 'package important data should be overridden with lang/vendor/nonameinc/en/ declarations',
'another_important_data' => 'this is from the package lang',

);
16 changes: 16 additions & 0 deletions tests/fixtures/resources/lang/en/messages.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

return array(

'home' => 'Home',
'family' => array(
'father' => 'Dad',
'mother' => 'Mom',
'children' => array(
'son' => 'Son',
),
),
'plural' => 'one apple|a million apples',
'random' => 'gm8ft2hrrlq1u6m54we9udi',
0x045F => 'should still be error code 1119'
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?php

return array(
'important_data' => 'should have replaced packages value for this key',
'new_key' => 'this is a new key added ontop of the packages',
);
36 changes: 35 additions & 1 deletion tests/specs/LangJsCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,40 @@ public function testAllFilesShouldBeConverted()
$this->cleanupOutputDirectory();
}

/**
*/
public function testPackageFilesShouldBeConverted()
{
$langPath = "{$this->testPath}/fixtures/resources/lang";
$packageFiles = ["nonameinc" => "{$this->testPath}/fixtures/packages/nonameinc/lang"];

$generator = new LangJsGenerator(new File(), $langPath, [], $packageFiles);

$command = new LangJsCommand($generator);
$command->setLaravel($this->app);

$code = $this->runCommand($command, ['target' => $this->outputFilePath]);
$this->assertRunsWithSuccess($code);
$this->assertFileExists($this->outputFilePath);

$contents = file_get_contents($this->outputFilePath);

$this->_assertStringContainsString('gm8ft2hrrlq1u6m54we9udi', $contents);

# do not reindex error codes.
$this->_assertStringContainsString('"1119":"should still be error code 1119"', $contents);

$this->_assertStringNotContainsString('vendor.nonameinc.en.messages', $contents);

$this->_assertStringContainsString('en.nonameinc::messages', $contents);

$this->_assertStringContainsString('should have replaced packages value for this key', $contents);
$this->_assertStringContainsString('this is a new key added ontop of the packages', $contents);
$this->_assertStringContainsString('another_important_data', $contents);

$this->cleanupOutputDirectory();
}

/**
*/
public function testFilesSelectedInConfigShouldBeConverted()
Expand Down Expand Up @@ -240,7 +274,7 @@ public function testShouldIgnoreDefaultOutputPathFromConfigIfTargetArgumentExist
$code = $this->runCommand($command, ['target' => $this->outputFilePath]);
$this->assertRunsWithSuccess($code);
$this->assertFileExists($this->outputFilePath);
$this->assertFileNotExists($customOutputFilePath);
$this->assertFileDoesNotExist($customOutputFilePath);

$template = "$this->rootPath/src/Mariuzzo/LaravelJsLocalization/Generators/Templates/langjs_with_messages.js";
$this->assertFileExists($template);
Expand Down
86 changes: 81 additions & 5 deletions tests/specs/LangJsServiceProviderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Mariuzzo\LaravelJsLocalization;

use Illuminate\Support\Facades\File as FileFacade;
use Orchestra\Testbench\TestCase;

/**
Expand All @@ -11,18 +12,93 @@
*/
class LangJsServiceProviderTest extends TestCase
{
/**
* The base path of tests.
*
* @var string
*/
private $testPath;

/**
* The root path of the project.
*
* @var string
*/
private $rootPath;

/**
* The file path of the expected output.
*
* @var string
*/
private $outputFilePath;

/**
* The base path of language files.
*
* @var string
*/
private $langPath;

/**
* LangJsCommandTest constructor.
*/
public function __construct()
{
parent::__construct();

$this->testPath = __DIR__ . '/..';
$this->rootPath = __DIR__ . '/../..';
$this->outputFilePath = "$this->testPath/output/lang.js";
$this->langPath = "$this->testPath/fixtures/lang";
}

protected function getPackageProviders($app = null)
{
return ['Mariuzzo\LaravelJsLocalization\LaravelJsLocalizationServiceProvider'];
return [
'Mariuzzo\LaravelJsLocalization\LaravelJsLocalizationServiceProvider',
'Mariuzzo\LaravelJsLocalization\NonameIncProvider',
];
}

/**
* Test the command.
*/
public function testShouldRegisterProvider()
public function testShouldIncludePackageLangRegisteredInProvider()
{

$this->app->setBasePath(__DIR__ . '/../fixtures/');

// this checks the LaravelJsLocalizationServiceProvider was loaded
$this->artisan("lang:js {$this->outputFilePath}")
->assertExitCode(0);
$this->assertFileExists($this->outputFilePath);

$expected = '"en.nonameinc::messages":{"another_important_data":"this is from the package lang","important_data":"should have replaced packages value for this key","new_key":"this is a new key added ontop of the packages"}';
$result = file_get_contents($this->outputFilePath);
$this->_assertStringContainsString($expected, $result);

$this->cleanupOutputDirectory();

}

/**
* Cleanup output directory after tests.
*/
protected function cleanupOutputDirectory()
{
// TODO: Add some assertions. (however, this already test if this
// package can be provided with the method: getPackageProviders).
$this->assertTrue(true); // Add empty assert to remove warning
$files = FileFacade::files("{$this->testPath}/output");
foreach ($files as $file) {
FileFacade::delete($file);
}
}

public function _assertStringContainsString($needle, $haystack)
{
if (method_exists(get_parent_class($this), 'assertStringContainsString')) {
return $this->assertStringContainsString($needle, $haystack);
}

return $this->assertContains($needle, $haystack);
}
}
15 changes: 15 additions & 0 deletions tests/specs/NonameIncProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php
namespace Mariuzzo\LaravelJsLocalization;


use Illuminate\Support\ServiceProvider;

class NonameIncProvider extends ServiceProvider
{
public function boot()
{
$this->loadTranslationsFrom(__DIR__ . '/../fixtures/packages/nonameinc/lang', 'nonameinc');
}

}