Skip to content

Commit

Permalink
Allow subdirectories for for translation PHP files
Browse files Browse the repository at this point in the history
Accept the Laravel 5 structure: {{ trans('foo/bar/foo.key') }}
More info here:
https://laravel.io/forum/02-23-2015-localization-load-files-from-subdire
ctories-at-resourceslanglocale
  • Loading branch information
MichaelHoste committed Jan 11, 2018
1 parent c67f8a8 commit c14042e
Show file tree
Hide file tree
Showing 15 changed files with 561 additions and 41 deletions.
10 changes: 5 additions & 5 deletions src/Console/Commands/Sync.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
namespace Armandsar\LaravelTranslationio\Console\Commands;

use Illuminate\Console\Command;
use Armandsar\LaravelTranslationio\Service\Sync as SyncService;
use Armandsar\LaravelTranslationio\Service\SourceEditSync as SourceEditSyncService;
use Armandsar\LaravelTranslationio\Service\Sync as SyncService;

class Sync extends Command
{
Expand All @@ -23,20 +23,20 @@ class Sync extends Command
private $sourceEditSyncService;

public function __construct(
SyncService $syncService,
SourceEditSyncService $sourceEditSyncService
SourceEditSyncService $sourceEditSyncService,
SyncService $syncService
)
{
$this->syncService = $syncService;
$this->sourceEditSyncService = $sourceEditSyncService;
$this->syncService = $syncService;
parent::__construct();
}

public function handle()
{
$this->info('Sync started');
$this->syncService->call();
$this->sourceEditSyncService->call();
$this->syncService->call();
$this->info('Sync finished');
}
}
2 changes: 1 addition & 1 deletion src/POExtractor.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ public function call($string)

return $return;
}
}
}
2 changes: 1 addition & 1 deletion src/Service/SourceEditSync.php
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ private function throwErrorIfConflictInMetadata($metadataContent)
{
if (str_contains($metadataContent, ['>>>>', '<<<<'])) {
$metadataFilePath = $this->metadataFilePath();
throw new SourceEditException($metadataFilePath . " file is corrupted and seems to have unresolved versioning conflicts. Please resolve them and try again.");
throw new SourceEditSyncException($metadataFilePath . " file is corrupted and seems to have unresolved versioning conflicts. Please resolve them and try again.");
}
}

Expand Down
21 changes: 20 additions & 1 deletion src/SourceSaver.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,22 @@ public function __construct(

public function call($sourceEdit, $sourceLocale)
{
$key = $sourceEdit['key'];

$dir = $this->localePath($sourceLocale);

// Adapt $group and $dir if the key contains subfolders:
// https://laravel.io/forum/02-23-2015-localization-load-files-from-subdirectories-at-resourceslanglocale)
if (str_contains($key, '/')) {
$subFolders = explode('/', $key);
array_pop($subFolders);
$dir = join(DIRECTORY_SEPARATOR, array_merge([$dir], $subFolders));
}

$this->makeDirectoryIfNotExisting($dir);

$group = $this->group($sourceEdit['key']);

$groupFile = $dir . DIRECTORY_SEPARATOR . $group . '.php';

if ($this->filesystem->exists($groupFile)) {
Expand Down Expand Up @@ -79,7 +90,15 @@ private function makeDirectoryIfNotExisting($directory)

private function group($key)
{
return explode('.', $key)[0];
$foldersAndGroup = explode('.', $key)[0];

if (str_contains($foldersAndGroup, '/')) {
$parts = explode('/', $foldersAndGroup);
return array_pop($parts);
}
else {
return $foldersAndGroup;
}
}

private function keys($key)
Expand Down
31 changes: 26 additions & 5 deletions src/TranslationExtractor.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,22 +44,43 @@ public function call($locale)
}

$files = iterator_to_array(
Finder::create()->files()->ignoreDotFiles(true)->in($path)->depth(0),
Finder::create()->files()->ignoreDotFiles(true)->in($path),
false
);

return collect($files)->map(function (SplFileInfo $file) use ($locale) {
$translations = collect($files)->map(function (SplFileInfo $file) use ($locale) {
$group = $file->getBasename('.' . $file->getExtension());
$relativePath = $file->getRelativePath();

$data = array_dot([
$group => $this->translator->getLoader()->load($locale, $group)
$group => $this->translator->getLoader()->load($locale, $relativePath . DIRECTORY_SEPARATOR . $group)
]);

$data = collect($data);
$data = $this->addSubfolderToKeys($relativePath, $data);

return $data->filter();
return collect($data)->filter();
})->collapse()->toArray();

return $translations;
}

// if subfolder translation file, add $relativePath/ in front of each key
// (https://laravel.io/forum/02-23-2015-localization-load-files-from-subdirectories-at-resourceslanglocale)
private function addSubfolderToKeys($relativePath, $data)
{
if ($relativePath != '') {
$newData = [];

foreach ($data as $key => $value) {
$newData[$relativePath . '/' . $key] = $value;
}

return $newData;
}
else {
return $data;
}
}

private function localePath($locale)
{
Expand Down
10 changes: 9 additions & 1 deletion src/TranslationSaver.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,16 @@ private function save($locale, $group, $translations)
{
$dir = $this->localePath($locale);

// Adapt $group and $dir if key contains subfolders:
// https://laravel.io/forum/02-23-2015-localization-load-files-from-subdirectories-at-resourceslanglocale)
if (str_contains($group, '/')) {
$subFolders = explode('/', $group);
$group = array_pop($subFolders);
$dir = join(DIRECTORY_SEPARATOR, array_merge([$dir], $subFolders));
}

if ( ! $this->filesystem->exists($dir)) {
$this->filesystem->makeDirectory($dir);
$this->filesystem->makeDirectory($dir, 0777, true);
}

$fileContent = <<<'EOT'
Expand Down
12 changes: 8 additions & 4 deletions tests/Integration/InitTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,16 @@ public function testItWorks()
app()['config']->set('translationio.target_locales', ['lv', 'ru']);
app()['config']->set('translationio.key', '13f5dbf135334c20aa4fed952f5a81f9');

$this->addTranslationFixture('lv', 'auth', [
$this->addTranslationFixture('lv', [], 'auth', [
'password' => 'Parole'
]);

$this->addTranslationFixture('ru', 'auth', [
$this->addTranslationFixture('ru', [], 'auth', [
'password' => 'Пароль',
'error' => 'Ошибка'
]);

$this->addTranslationFixture('en', 'auth', [
$this->addTranslationFixture('en', [], 'auth', [
'password' => 'Password',
'email' => 'Email',
'fields' => [
Expand All @@ -30,10 +30,14 @@ public function testItWorks()
]
]);

$this->addTranslationFixture('en', ['subfolder'], 'forms', [
'title' => 'Title'
]);

$this->cassette('integration/init.yml');
$this->artisan('translations:init');

// if we got this far, all is good
$this->assertTrue(true);
}
}
}
178 changes: 177 additions & 1 deletion tests/Integration/SyncTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public function testItWorks()
app()['config']->set('translationio.target_locales', ['lv', 'ru']);
app()['config']->set('translationio.key', '13f5dbf135334c20aa4fed952f5a81f9');

$this->addTranslationFixture('en', 'auth', [
$this->addTranslationFixture('en', [], 'auth', [
'password' => 'Password changed',
'email' => 'Email changed',
'fields' => [
Expand All @@ -28,6 +28,48 @@ public function testItWorks()
$authLv = $this->filesystem->getRequire($this->localePath('lv') . DIRECTORY_SEPARATOR . 'auth.php');
$authRu = $this->filesystem->getRequire($this->localePath('ru') . DIRECTORY_SEPARATOR . 'auth.php');

$this->assertEquals(
[
'password' => 'Parole',
'email' => 'Epasts',
'fields' => [
'first_name' => 'Vārds',
'last_name' => 'Uzvārds'
]
], $authLv);

$this->assertEquals(
[
'password' => 'Пароль',
'email' => 'Почта',
'fields' => [
'first_name' => 'Имя',
'last_name' => 'Фамилия'
]
], $authRu);
}

public function testItWorksWithSourceEdits()
{
Carbon::setTestNow(Carbon::createFromTimestamp('1506615677'));
app()['config']->set('translationio.target_locales', ['lv', 'ru']);
app()['config']->set('translationio.key', '13f5dbf135334c20aa4fed952f5a81f9');

$this->addTranslationFixture('en', [], 'auth', [
'password' => 'Password changed',
'email' => 'Email changed',
'fields' => [
'first_name' => 'First name changed',
'last_name' => 'Last name changed',
]
]);

$this->cassette('integration/sync_with_source_edits.yml');
$this->artisan('translations:sync');

$authLv = $this->filesystem->getRequire($this->localePath('lv') . DIRECTORY_SEPARATOR . 'auth.php');
$authRu = $this->filesystem->getRequire($this->localePath('ru') . DIRECTORY_SEPARATOR . 'auth.php');

$this->assertEquals(
[
'password' => 'Parole',
Expand Down Expand Up @@ -61,4 +103,138 @@ public function testItWorks()
], $authEn);
}

public function testItWorksWithSubfolders()
{
Carbon::setTestNow(Carbon::createFromTimestamp('1506615677'));
app()['config']->set('translationio.target_locales', ['lv', 'ru']);
app()['config']->set('translationio.key', '13f5dbf135334c20aa4fed952f5a81f9');

$this->addTranslationFixture('en', ['subfolder'], 'auth', [
'password' => 'Password changed',
'email' => 'Email changed',
'fields' => [
'first_name' => 'First name changed',
'last_name' => 'Last name changed',
]
]);

$this->addTranslationFixture('en', ['subfolder', 'subsubfolder'], 'test', [
'keytest' => 'This is a test',
]);

$this->cassette('integration/sync_with_subfolders.yml');
$this->artisan('translations:sync');

$authLv = $this->filesystem->getRequire($this->localePath('lv') . DIRECTORY_SEPARATOR . 'subfolder' . DIRECTORY_SEPARATOR . 'auth.php');
$authRu = $this->filesystem->getRequire($this->localePath('ru') . DIRECTORY_SEPARATOR . 'subfolder' . DIRECTORY_SEPARATOR . 'auth.php');
$testLv = $this->filesystem->getRequire($this->localePath('lv') . DIRECTORY_SEPARATOR . 'subfolder' . DIRECTORY_SEPARATOR . 'subsubfolder' . DIRECTORY_SEPARATOR . 'test.php');
$testRu = $this->filesystem->getRequire($this->localePath('ru') . DIRECTORY_SEPARATOR . 'subfolder' . DIRECTORY_SEPARATOR . 'subsubfolder' . DIRECTORY_SEPARATOR . 'test.php');

$this->assertEquals(
[
'password' => 'Parole',
'email' => 'Epasts',
'fields' => [
'first_name' => 'Vārds',
'last_name' => 'Uzvārds'
]
], $authLv);

$this->assertEquals(
[
'password' => 'Пароль',
'email' => 'Почта',
'fields' => [
'first_name' => 'Имя',
'last_name' => 'Фамилия'
]
], $authRu);

$this->assertEquals(
[
'keytest' => 'Šis ir tests'
], $testLv);

$this->assertEquals(
[
'keytest' => 'Это тест'
], $testRu);
}

public function testItWorksWithSubfoldersAndSourceEdits()
{
Carbon::setTestNow(Carbon::createFromTimestamp('1506615677'));
app()['config']->set('translationio.target_locales', ['lv', 'ru']);
app()['config']->set('translationio.key', '13f5dbf135334c20aa4fed952f5a81f9');

$this->addTranslationFixture('en', ['subfolder'], 'auth', [
'password' => 'Password changed',
'email' => 'Email changed',
'fields' => [
'first_name' => 'First name changed',
'last_name' => 'Last name changed',
]
]);

$this->addTranslationFixture('en', ['subfolder', 'subsubfolder'], 'test', [
'keytest' => 'This is a test',
]);

$this->cassette('integration/sync_with_subfolders_and_source_edits.yml');
$this->artisan('translations:sync');

$authLv = $this->filesystem->getRequire($this->localePath('lv') . DIRECTORY_SEPARATOR . 'subfolder' . DIRECTORY_SEPARATOR . 'auth.php');
$authRu = $this->filesystem->getRequire($this->localePath('ru') . DIRECTORY_SEPARATOR . 'subfolder' . DIRECTORY_SEPARATOR . 'auth.php');
$testLv = $this->filesystem->getRequire($this->localePath('lv') . DIRECTORY_SEPARATOR . 'subfolder' . DIRECTORY_SEPARATOR . 'subsubfolder' . DIRECTORY_SEPARATOR . 'test.php');
$testRu = $this->filesystem->getRequire($this->localePath('ru') . DIRECTORY_SEPARATOR . 'subfolder' . DIRECTORY_SEPARATOR . 'subsubfolder' . DIRECTORY_SEPARATOR . 'test.php');

$this->assertEquals(
[
'password' => 'Parole',
'email' => 'Epasts',
'fields' => [
'first_name' => 'Vārds',
'last_name' => 'Uzvārds'
]
], $authLv);

$this->assertEquals(
[
'password' => 'Пароль',
'email' => 'Почта',
'fields' => [
'first_name' => 'Имя',
'last_name' => 'Фамилия'
]
], $authRu);

$this->assertEquals(
[
'keytest' => 'Šis ir tests'
], $testLv);

$this->assertEquals(
[
'keytest' => 'Это тест'
], $testRu);

$authEn = $this->filesystem->getRequire($this->localePath('en') . DIRECTORY_SEPARATOR . 'subfolder' . DIRECTORY_SEPARATOR . 'auth.php');
$testEn = $this->filesystem->getRequire($this->localePath('en') . DIRECTORY_SEPARATOR . 'subfolder' . DIRECTORY_SEPARATOR . 'subsubfolder' . DIRECTORY_SEPARATOR . 'test.php');

$this->assertEquals(
[
'password' => 'Password modified', // was modified by source_edits
'email' => 'Email changed', // was not modified by source_edits because old_text didn't match
'fields' => [
'first_name' => 'First name changed',
'last_name' => 'Surname changed', // was modified by source_edits
]
], $authEn);

$this->assertEquals(
[
'keytest' => 'This is a good test' // was modified by source_edits
], $testEn);
}

}
Loading

0 comments on commit c14042e

Please sign in to comment.