Skip to content

Commit

Permalink
Nested folders support testing (#102)
Browse files Browse the repository at this point in the history
  • Loading branch information
kha333n authored Apr 20, 2024
1 parent d4942b9 commit c97ee7a
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 45 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@ name: run-tests



on: [pull_request]
on: [ pull_request ]

jobs:
build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
php: [8.3, 8.2]
laravel: [11.*]
php: [ 8.3, 8.2 ]
laravel: [ 11.* ]
dependency-version: [ prefer-lowest, prefer-stable ]
include:
- laravel: 11.*
Expand Down
77 changes: 39 additions & 38 deletions src/TranslationsManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,19 +78,20 @@ public function getTranslations(string $locale): array
->when($this->filesystem->exists(lang_path($rootFileName)), function ($collection) use ($rootFileName) {
return $collection->prepend($rootFileName);
})
->filter(function ($file) {
->filter(function ($file) use ($locale) {
foreach (config('translations.exclude_files') as $excludeFile) {
if (fnmatch($excludeFile, $file)) {
return false;
}
if (fnmatch($excludeFile, basename($file))) {

/**
* <h1>File exclusion by wildcard</h1>
* <h3>$file is with language like <code>en/book/create.php</code> while $excludedFile contains only wildcards or path like <code>book/create.php</code></h3>
* <h3>So, we need to remove the language part from $file before comparing with $excludeFile</h3>
*/
if (fnmatch($excludeFile, str_replace($locale.'/', '', $file))) {
return false;
}

return true;
}

return ! in_array($file, config('translations.exclude_files'));
return true;
})
->filter(function ($file) {
return $this->filesystem->extension($file) == 'php' || $this->filesystem->extension($file) == 'json';
Expand All @@ -112,6 +113,36 @@ public function getTranslations(string $locale): array
return $translations;
}

public function download(): ?string
{
try {
$this->export(download: true);

$zip = new ZipArchive();

$zipPath = storage_path('app/lang.zip');
$zip->open($zipPath, ZipArchive::CREATE | ZipArchive::OVERWRITE);

$baseDir = storage_path('app/translations');
$zip->addEmptyDir('lang');

$files = $this->filesystem->allFiles($baseDir);

foreach ($files as $file) {
$relativePath = str_replace($baseDir.DIRECTORY_SEPARATOR, '', $file->getPathname());
$zip->addFile($file->getPathname(), 'lang/'.$relativePath);
}

$zip->close();

return $zipPath;
} catch (Exception $e) {
logger()->error($e->getMessage());

return null;
}
}

public function export($download = false): void
{
$translations = Translation::with('phrases')->get();
Expand Down Expand Up @@ -150,34 +181,4 @@ public function export($download = false): void
}
}
}

public function download(): ?string
{
try {
$this->export(download: true);

$zip = new ZipArchive();

$zipPath = storage_path('app/lang.zip');
$zip->open($zipPath, ZipArchive::CREATE | ZipArchive::OVERWRITE);

$baseDir = storage_path('app/translations');
$zip->addEmptyDir('lang');

$files = $this->filesystem->allFiles($baseDir);

foreach ($files as $file) {
$relativePath = str_replace($baseDir.DIRECTORY_SEPARATOR, '', $file->getPathname());
$zip->addFile($file->getPathname(), 'lang/'.$relativePath);
}

$zip->close();

return $zipPath;
} catch (Exception $e) {
logger()->error($e->getMessage());

return null;
}
}
}
82 changes: 78 additions & 4 deletions tests/TranslationsManagerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@

createPhpLanguageFile('de/validation.php', []);

// Create nested folder structure
createPhpLanguageFile('en/book/create.php', []);

$translationsManager = new TranslationsManager(new Filesystem());
$locales = $translationsManager->getLocales();

Expand All @@ -41,7 +44,16 @@
'title' => 'My title',
]);

Config::set('translations.exclude_files', ['validation.php']);
// Update to include nested folder
createPhpLanguageFile('en/book/create.php', [
'nested' => 'Nested test',
]);

createPhpLanguageFile('en/book/excluded.php', [
'nested' => 'Nested test',
]);

Config::set('translations.exclude_files', ['validation.php', 'book/excluded.php']);
Config::set('translations.source_language', 'en');
$filesystem = new Filesystem();

Expand All @@ -50,12 +62,14 @@
expect($translations)->toBe([
'en.json' => ['title' => 'My title'],
'en/auth.php' => ['test' => 'Test'],
'en/book/create.php' => ['nested' => 'Nested test'],
]);

$translations = $translationsManager->getTranslations('');
expect($translations)->toBe([
'en.json' => ['title' => 'My title'],
'en/auth.php' => ['test' => 'Test'],
'en/book/create.php' => ['nested' => 'Nested test'],
]);
});

Expand All @@ -70,6 +84,11 @@
'title' => 'My title',
]);

// Update to include nested folder
createPhpLanguageFile('en/book/create.php', [
'nested' => 'Nested test',
]);

Config::set('translations.exclude_files', ['*.php']);
Config::set('translations.source_language', 'en');
$filesystem = new Filesystem();
Expand All @@ -89,6 +108,8 @@
test('export creates a new translation file with the correct content', function () {
$filesystem = new Filesystem();
createDirectoryIfNotExits(lang_path('en/auth.php'));
// Update to include nested folder
createDirectoryIfNotExits(lang_path('en/book/create.php'));

$translation = Translation::factory([
'source' => true,
Expand All @@ -104,23 +125,45 @@
]),
]))->create();

$nestedTranslation = Translation::factory([
'source' => true,
'language_id' => Language::factory([
'code' => 'en',
'name' => 'English',
]),
])->has(Phrase::factory()->state([
'phrase_id' => null,
'translation_file_id' => TranslationFile::factory([
'name' => 'book/create',
'extension' => 'php',
]),
]))->create();

$translationsManager = new TranslationsManager($filesystem);
$translationsManager->export();

$fileName = lang_path('en/'.$translation->phrases[0]->file->name.'.'.$translation->phrases[0]->file->extension);
$nestedFileName = lang_path('en/'.$nestedTranslation->phrases[0]->file->name.'.'.$nestedTranslation->phrases[0]->file->extension);

$fileNameInDisk = File::allFiles(lang_path($translation->language->code))[0]->getPathname();
$nestedFileNameInDisk = File::allFiles(lang_path($nestedTranslation->language->code))[1]->getPathname();

expect($fileName)->toBe($fileNameInDisk)
->and(File::get($fileName))
->toBe("<?php\n\nreturn ".VarExporter::export($translation->phrases->pluck('value', 'key')->toArray(), VarExporter::TRAILING_COMMA_IN_ARRAY).';'.PHP_EOL);
->toBe("<?php\n\nreturn ".VarExporter::export($translation->phrases->pluck('value', 'key')->toArray(), VarExporter::TRAILING_COMMA_IN_ARRAY).';'.PHP_EOL)
->and($nestedFileName)->toBe($nestedFileNameInDisk)
->and(File::get($nestedFileName))
->toBe("<?php\n\nreturn ".VarExporter::export($nestedTranslation->phrases->pluck('value', 'key')->toArray(), VarExporter::TRAILING_COMMA_IN_ARRAY).';'.PHP_EOL);

File::deleteDirectory(lang_path());
});

test('export can handle PHP translation files', function () {
createPhpLanguageFile('en/test.php', ['accepted' => 'The :attribute must be accepted.']);

// Update to include nested folder
createPhpLanguageFile('en/book/create.php', ['nested' => 'Nested :attribute must be accepted.']);

$filesystem = new Filesystem();

$translation = Translation::factory()
Expand All @@ -134,19 +177,36 @@
->for(Language::factory()->state(['code' => 'en']))
->create();

$nestedTranslation = Translation::factory()
->has(Phrase::factory()
->for(TranslationFile::factory()->state(['name' => 'book/create', 'extension' => 'php']), 'file')
->state([
'key' => 'nested',
'value' => 'Nested :attribute must be accepted.',
'phrase_id' => null,
]))
->for(Language::factory()->state(['code' => 'en']))
->create();

$translationsManager = new TranslationsManager($filesystem);
$translationsManager->export();

$path = lang_path('en'.DIRECTORY_SEPARATOR.'test.php');
$nestedPath = lang_path('en'.DIRECTORY_SEPARATOR.'book'.DIRECTORY_SEPARATOR.'create.php');
$pathInDisk = lang_path($translation->language->code.DIRECTORY_SEPARATOR.'test.php');
$nestedPathInDisk = lang_path($nestedTranslation->language->code.DIRECTORY_SEPARATOR.'book'.DIRECTORY_SEPARATOR.'create.php');

expect(File::get($path))->toBe(File::get($pathInDisk));
expect(File::get($path))->toBe(File::get($pathInDisk))
->and(File::get($nestedPath))->toBe(File::get($nestedPathInDisk));

File::deleteDirectory(lang_path());
});

test('export can handle JSON translation files', function () {
createJsonLanguageFile('en/test.json', ['accepted' => 'The :attribute must be accepted.']);

// Update to include nested folder
createJsonLanguageFile('en/book/create.json', ['nested' => 'Nested test']);
$filesystem = new Filesystem();

$translation = Translation::factory()
Expand All @@ -160,13 +220,27 @@
->for(Language::factory()->state(['code' => 'en']))
->create();

$nestedTranslation = Translation::factory()
->has(Phrase::factory()
->for(TranslationFile::factory()->state(['name' => 'book/create', 'extension' => 'json']), 'file')
->state([
'key' => 'nested',
'value' => 'Nested test',
'phrase_id' => null,
]))
->for(Language::factory()->state(['code' => 'en']))
->create();

$translationsManager = new TranslationsManager($filesystem);
$translationsManager->export();

$path = lang_path('en'.DIRECTORY_SEPARATOR.'test.json');
$nestedPath = lang_path('en'.DIRECTORY_SEPARATOR.'book'.DIRECTORY_SEPARATOR.'create.json');
$pathInDisk = lang_path($translation->language->code.DIRECTORY_SEPARATOR.'test.json');
$nestedPathInDisk = lang_path($nestedTranslation->language->code.DIRECTORY_SEPARATOR.'book'.DIRECTORY_SEPARATOR.'create.json');

expect(File::get($path))->toBe(File::get($pathInDisk));
expect(File::get($path))->toBe(File::get($pathInDisk))
->and(File::get($nestedPath))->toBe(File::get($nestedPathInDisk));

File::deleteDirectory(lang_path());
});
Expand Down

0 comments on commit c97ee7a

Please sign in to comment.