Skip to content

Commit

Permalink
Merge pull request #49 from benaja/main
Browse files Browse the repository at this point in the history
Translation Strings as Keys support and adding file name in key option
  • Loading branch information
MohmmedAshraf authored Jan 19, 2024
2 parents b1b1fe2 + 905ebae commit 77bb15f
Show file tree
Hide file tree
Showing 27 changed files with 781 additions and 530 deletions.
2 changes: 2 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
"nunomaduro/collision": "^7.0",
"orchestra/testbench": "^8.0",
"pestphp/pest": "^2.18",
"pestphp/pest-plugin-faker": "^2.0",
"pestphp/pest-plugin-laravel": "^2.2",
"phpstan/extension-installer": "^1.1",
"phpstan/phpstan-deprecation-rules": "^1.0",
"phpstan/phpstan-phpunit": "^1.0",
Expand Down
2 changes: 2 additions & 0 deletions config/translations.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@
*/
'database_connection' => env('TRANSLATIONS_DB_CONNECTION', null),

'include_file_in_key' => env('TRANSLATIONS_INCLUDE_FILE_IN_KEY', false),

/*
|--------------------------------------------------------------------------
| Source Language
Expand Down
2 changes: 1 addition & 1 deletion database/factories/LanguageFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ class LanguageFactory extends Factory
public function definition(): array
{
return [
'rtl' => $this->faker->boolean(),
'code' => $this->faker->randomElement(['en', 'nl', 'fr', 'de', 'es', 'it', 'pt', 'ru', 'ja', 'zh']),
'name' => $this->faker->randomElement(['English', 'Dutch', 'French', 'German', 'Spanish', 'Italian', 'Portuguese', 'Russian', 'Japanese', 'Chinese']),
'rtl' => $this->faker->boolean(),
];
}
}
10 changes: 9 additions & 1 deletion database/factories/TranslationFileFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,15 @@ public function definition(): array
{
return [
'name' => $this->faker->randomElement(['app', 'auth', 'pagination', 'passwords', 'validation']),
'extension' => $this->faker->randomElement(['json', 'php']),
'extension' => 'php',
'is_root' => false,
];
}

public function json(): self
{
return $this->state([
'extension' => 'json',
]);
}
}
22 changes: 22 additions & 0 deletions database/migrations/add_is_root_to_translation_files_table.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class() extends Migration
{
public function up(): void
{
Schema::table('ltu_translation_files', function (Blueprint $table) {
$table->boolean('is_root')->default(false)->after('extension');
});
}

public function down(): void
{
Schema::table('ltu_translation_files', function (Blueprint $table) {
$table->dropColumn('is_root');
});
}
};
15 changes: 13 additions & 2 deletions src/Actions/CopyPhrasesFromSourceAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Outhebox\TranslationsUI\Actions;

use Outhebox\TranslationsUI\Models\Translation;
use Outhebox\TranslationsUI\Models\TranslationFile;

class CopyPhrasesFromSourceAction
{
Expand All @@ -11,14 +12,24 @@ public static function execute(Translation $translation): void
$sourceTranslation = Translation::where('source', true)->first();

$sourceTranslation->phrases()->with('file')->get()->each(function ($sourcePhrase) use ($translation) {
$file = $sourcePhrase->file;

if ($file->is_root) {
$file = TranslationFile::firstOrCreate([
'is_root' => true,
'extension' => $file->extension,
'name' => $translation->language->code,
]);
}

$translation->phrases()->create([
'value' => null,
'uuid' => str()->uuid(),
'key' => $sourcePhrase->key,
'group' => $sourcePhrase->group,
'group' => $file->name,
'phrase_id' => $sourcePhrase->id,
'parameters' => $sourcePhrase->parameters,
'translation_file_id' => $sourcePhrase->file->id,
'translation_file_id' => $file->id,
]);
});
}
Expand Down
5 changes: 5 additions & 0 deletions src/Actions/SyncPhrasesAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,16 @@ public static function execute(Translation $source, $key, $value, $locale, $file
'source' => config('translations.source_language') === $locale,
]);

$isRoot = $file === $locale.'.json' || $file === $locale.'.php';

$translationFile = TranslationFile::firstOrCreate([
'name' => pathinfo($file, PATHINFO_FILENAME),
'extension' => pathinfo($file, PATHINFO_EXTENSION),
'is_root' => $isRoot,
]);

$key = config('translations.include_file_in_key') && ! $isRoot ? "{$translationFile->name}.{$key}" : $key;

$translation->phrases()->updateOrCreate([
'key' => $key,
'group' => $translationFile->name,
Expand Down
33 changes: 33 additions & 0 deletions src/Console/Commands/ImportTranslationsCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Illuminate\Console\Command;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Str;
use Outhebox\TranslationsUI\Actions\SyncPhrasesAction;
use Outhebox\TranslationsUI\Database\Seeders\LanguagesTableSeeder;
use Outhebox\TranslationsUI\Models\Language;
Expand Down Expand Up @@ -106,5 +107,37 @@ public function syncTranslations(Translation $translation, string $locale): void
SyncPhrasesAction::execute($translation, $key, $value, $locale, $file);
}
}

if ($locale === config('translations.source_language')) {
return;
}

$this->syncMissingTranslations($translation, $locale);
}

public function syncMissingTranslations(Translation $source, string $locale): void
{
$language = Language::where('code', $locale)->first();

$translation = Translation::firstOrCreate([
'language_id' => $language->id,
'source' => false,
]);

$source->load('phrases.translation', 'phrases.file');

$source->phrases->each(function ($phrase) use ($translation, $locale) {
if (! $translation->phrases()->where('key', $phrase->key)->first()) {
$fileName = $phrase->file->name.'.'.$phrase->file->extension;

if ($phrase->file->name === config('translations.source_language')) {
$fileName = Str::replaceStart(config('translations.source_language').'.', "{$locale}.", $fileName);
} else {
$fileName = Str::replaceStart(config('translations.source_language').'/', "{$locale}/", $fileName);
}

SyncPhrasesAction::execute($phrase->translation, $phrase->key, '', $locale, $fileName);
}
});
}
}
3 changes: 0 additions & 3 deletions src/Http/Controllers/PhraseController.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,6 @@ public function edit(Translation $translation, Phrase $phrase): RedirectResponse
->setTarget($translation->language->code)
->translate($phrase->source->value),
],
// 'deepl' => 'DeepL',
// 'microsoft' => 'Microsoft Translator',
// 'amazon' => 'Amazon Translate',
],
]);
}
Expand Down
3 changes: 1 addition & 2 deletions src/Http/Controllers/TranslationController.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,7 @@ public function store(Request $request): RedirectResponse
'languages' => 'required|array',
]);

$selectedLanguageIds = $request->input('languages');
$languages = Language::whereIn('id', $selectedLanguageIds)->get();
$languages = Language::whereIn('id', $request->input('languages'))->get();

foreach ($languages as $language) {
CreateTranslationForLanguageAction::execute($language);
Expand Down
4 changes: 4 additions & 0 deletions src/Models/TranslationFile.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ class TranslationFile extends Model

public $timestamps = false;

protected $casts = [
'is_root' => 'boolean',
];

public function phrases(): HasMany
{
return $this->hasMany(Phrase::class);
Expand Down
63 changes: 48 additions & 15 deletions src/TranslationsManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,11 @@
use Illuminate\Filesystem\Filesystem;
use Illuminate\Support\Str;
use Outhebox\TranslationsUI\Models\Translation;
use SplFileInfo;

class TranslationsManager
{
public function __construct(
protected Filesystem $filesystem,
private array $translations = []
protected Filesystem $filesystem
) {
}

Expand All @@ -30,38 +28,73 @@ public function getLocales(): array
$locales->push(basename($dir));
}

collect($this->filesystem->files(lang_path()))->each(function ($file) use ($locales) {
if ($this->filesystem->extension($file) != 'json') {
return;
}

if (! $locales->contains($file->getFilenameWithoutExtension())) {
$locales->push($file->getFilenameWithoutExtension());
}
});

return $locales->toArray();
}

public function getTranslations(string $local): array
public function getTranslations(string $locale): array
{
if (blank($local)) {
$local = config('translations.source_language');
if (blank($locale)) {
$locale = config('translations.source_language');
}

$translations = [];
$rootFileName = "$locale.json";

$files = [];

if ($this->filesystem->exists(lang_path($locale))) {
$files = $this->filesystem->allFiles(lang_path($locale));
}

collect($this->filesystem->allFiles(lang_path($local)))
->merge(collect($this->filesystem->glob(lang_path()."/$local.*"))->map(fn ($file) => new SplFileInfo($file)))
collect($files)
->map(function ($file) use ($locale) {
return $locale.DIRECTORY_SEPARATOR.$file->getFilename();
})
->when($this->filesystem->exists(lang_path($rootFileName)), function ($collection) use ($rootFileName) {
return $collection->prepend($rootFileName);
})
->filter(function ($file) {
return ! in_array($file->getFilename(), config('translations.exclude_files'));
foreach (config('translations.exclude_files') as $excludeFile) {
if (fnmatch($excludeFile, $file)) {
return false;
}
if (fnmatch($excludeFile, basename($file))) {
return false;
}

return true;
}

return ! in_array($file, config('translations.exclude_files'));
})
->filter(function ($file) {
return $this->filesystem->extension($file) == 'php' || $this->filesystem->extension($file) == 'json';
})
->each(function ($file) {
->each(function ($file) use (&$translations) {
try {
if ($this->filesystem->extension($file) == 'php') {
$this->translations[$file->getFilename()] = $this->filesystem->getRequire($file->getPathname());
$translations[$file] = $this->filesystem->getRequire(lang_path($file));
}

if ($this->filesystem->extension($file) == 'json') {
$this->translations[$file->getFilename()] = json_decode($this->filesystem->get($file), true);
$translations[$file] = json_decode($this->filesystem->get(lang_path($file)), true);
}
} catch (FileNotFoundException $e) {
$this->translations[$file->getFilename()] = [];
$translations[$file] = [];
}
});

return $this->translations;
return $translations;
}

public function export(): void
Expand Down Expand Up @@ -92,7 +125,7 @@ public function export(): void
}

if ($this->filesystem->extension($path) == 'json') {
$this->filesystem->put($path, json_encode($phrases, JSON_PRETTY_PRINT));
$this->filesystem->put($path, json_encode($phrases, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT));
}
}
}
Expand Down
1 change: 1 addition & 0 deletions src/TranslationsUIServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public function configurePackage(Package $package): void
'create_contributors_table',
'create_contributor_languages_table',
'create_invites_table',
'add_is_root_to_translation_files_table',
])
->hasCommands([
PublishCommand::class,
Expand Down
19 changes: 0 additions & 19 deletions tests/FilesystemMock.php

This file was deleted.

35 changes: 35 additions & 0 deletions tests/Helpers.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

use Brick\VarExporter\VarExporter;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Str;

function createDirectoryIfNotExits($path): void
{
// check if $path is a filename or a directory
if (Str::contains($path, '.')) {
$path = dirname($path);
}

if (! File::exists($path)) {
File::makeDirectory($path, 0755, true);
}
}

function createPhpLanguageFile($path, array $content): void
{
$path = lang_path($path);

createDirectoryIfNotExits($path);

File::put($path, "<?php\n\nreturn ".VarExporter::export($content, VarExporter::TRAILING_COMMA_IN_ARRAY).';'.PHP_EOL);
}

function createJsonLanguageFile($path, array $content): void
{
$path = lang_path($path);

createDirectoryIfNotExits($path);

File::put($path, json_encode($content, JSON_PRETTY_PRINT));
}
Loading

0 comments on commit 77bb15f

Please sign in to comment.