translation/laravel

View on GitHub
src/SourceSaver.php

Summary

Maintainability
A
0 mins
Test Coverage
A
100%
<?php

namespace Tio\Laravel;

use Tio\Laravel\PrettyVarExport;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Filesystem\Filesystem;
use Illuminate\Support\Str;

class SourceSaver
{
    /**
     * @var Application
     */
    private $application;
    /**
     * @var Filesystem
     */
    private $filesystem;
    /**
     * @var PrettyVarExport
     */
    private $prettyVarExport;

    public function __construct(
        Application $application,
        FileSystem $fileSystem,
        PrettyVarExport $prettyVarExport
    ) {
        $this->application = $application;
        $this->filesystem = $fileSystem;
        $this->prettyVarExport = $prettyVarExport;
    }

    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->filesystem->makeDirectory($dir, 0777, true, true);

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

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

        if ($this->filesystem->exists($groupFile)) {
            $translations = $this->filesystem->getRequire($groupFile);

            $translations = $this->applySourceEditInTranslations($translations, $sourceEdit);

            // Leave the extra newline at the end
            $fileContent = <<<'EOT'
<?php

return {{translations}};

EOT;

            $prettyTranslationsExport = $this->prettyVarExport->call($translations, ['array-align' => true]);
            $fileContent  = str_replace('{{translations}}', $prettyTranslationsExport, $fileContent);

            $this->filesystem->put($groupFile, $fileContent);
        }
    }


    private function localePath($locale)
    {
        return $this->path() . DIRECTORY_SEPARATOR . $locale;
    }

    private function path()
    {
        return $this->application['path.lang'];
    }

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

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

    private function keys($key)
    {
        $keyParts = explode('.', $key);
        array_shift($keyParts); // remove group part
        return $keyParts;
    }

    private function applySourceEditInTranslations($translations, $sourceEdit)
    {
        $keys = $this->keys($sourceEdit['key']);
        $oldText = $sourceEdit['old_text'];
        $newText = $sourceEdit['new_text'];

        $current = &$translations;

        for ($i = 0; $i < count($keys) - 1; $i++) {
            $key = $keys[$i];
            $current = &$current[$key];
        }

        if (isset($current[$keys[count($keys) - 1]]) && $current[$keys[count($keys) - 1]] == $oldText) {
            $current[$keys[count($keys) - 1]] = $newText;
        }

        return $translations;
    }
}