![]() Server : Apache System : Linux server2.corals.io 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 15 09:17:08 EST 2021 x86_64 User : corals ( 1002) PHP Version : 7.4.33 Disable Function : exec,passthru,shell_exec,system Directory : /home/corals/medad.corals.io/vendor/barryvdh/laravel-translation-manager/src/ |
<?php namespace Barryvdh\TranslationManager; use Barryvdh\TranslationManager\Events\TranslationsExportedEvent; use Barryvdh\TranslationManager\Models\Translation; use Illuminate\Contracts\Events\Dispatcher; use Illuminate\Contracts\Foundation\Application; use Illuminate\Filesystem\Filesystem; use Illuminate\Support\Arr; use Illuminate\Support\Str; use Symfony\Component\Finder\Finder; class Manager { const JSON_GROUP = '_json'; /** @var \Illuminate\Contracts\Foundation\Application */ protected $app; /** @var \Illuminate\Filesystem\Filesystem */ protected $files; /** @var \Illuminate\Contracts\Events\Dispatcher */ protected $events; protected $config; protected $locales; protected $ignoreLocales; protected $ignoreFilePath; public function __construct(Application $app, Filesystem $files, Dispatcher $events) { $this->app = $app; $this->files = $files; $this->events = $events; $this->config = $app['config']['translation-manager']; $this->ignoreFilePath = storage_path('.ignore_locales'); $this->locales = []; $this->ignoreLocales = $this->getIgnoredLocales(); } protected function getIgnoredLocales() { if (!$this->files->exists($this->ignoreFilePath)) { return []; } $result = json_decode($this->files->get($this->ignoreFilePath)); return ($result && is_array($result)) ? $result : []; } public function importTranslations($replace = false, $base = null, $nameSpace = null, $import_group = false) { $counter = 0; //allows for vendor lang files to be properly recorded through recursion. $vendor = false; if ($base == null) { $base = $this->app['path.lang']; $vendor = false; } foreach ($this->files->directories($base) as $langPath) { $locale = basename($langPath); //import langfiles for each vendor if ($locale == 'vendor') { foreach ($this->files->directories($langPath) as $vendor) { $counter += $this->importTranslations($replace, $vendor, $nameSpace); } continue; } $vendorName = $this->files->name($this->files->dirname($langPath)); foreach ($this->files->allfiles($langPath) as $file) { $info = pathinfo($file); $group = $info['filename']; if ($import_group) { if ($import_group !== $group) { continue; } } if (in_array($group, $this->config['exclude_groups'])) { continue; } $subLangPath = str_replace($langPath . DIRECTORY_SEPARATOR, '', $info['dirname']); $subLangPath = str_replace(DIRECTORY_SEPARATOR, '/', $subLangPath); $langPath = str_replace(DIRECTORY_SEPARATOR, '/', $langPath); if ($subLangPath != $langPath) { $group = $subLangPath . '/' . $group; } if (!$vendor) { if ($nameSpace == 'Default') { $translations = \Lang::getLoader()->load($locale, $group); } else { $translations = \Lang::getLoader()->load($locale, $group, $nameSpace); } } else { $translations = include $file; $group = 'vendor/' . $vendorName; } if ($translations && is_array($translations)) { foreach (Arr::dot($translations) as $key => $value) { $importedTranslation = $this->importTranslation($key, $value, $locale, $group, $replace, $nameSpace); $counter += $importedTranslation ? 1 : 0; } } } } foreach ($this->files->files($this->app['path.lang']) as $jsonTranslationFile) { ; if (strpos($jsonTranslationFile, '.json') === false) { continue; } $locale = basename($jsonTranslationFile, '.json'); $group = self::JSON_GROUP; $translations = \Lang::getLoader()->load($locale, '*', '*'); // Retrieves JSON entries of the given locale only if ($translations && is_array($translations)) { foreach ($translations as $key => $value) { $importedTranslation = $this->importTranslation($key, $value, $locale, $group, $replace, $nameSpace); $counter += $importedTranslation ? 1 : 0; } } } return $counter; } public function importTranslation($key, $value, $locale, $group, $replace = false, $nameSpace = null) { // process only string values if (is_array($value)) { return false; } $value = (string)$value; $translation = Translation::firstOrNew([ 'locale' => $locale, 'group' => $group, 'key' => $key, 'namespace' => $nameSpace, ]); // Check if the database is different then the files $newStatus = $translation->value === $value ? Translation::STATUS_SAVED : Translation::STATUS_CHANGED; if ($newStatus !== (int)$translation->status) { $translation->status = $newStatus; } // Only replace when empty, or explicitly told so if ($replace || !$translation->value) { $translation->value = $value; } $translation->save(); return true; } public function findTranslations($path = null) { $path = $path ?: base_path(); $groupKeys = []; $stringKeys = []; $functions = $this->config['trans_functions']; $groupPattern = // See https://regex101.com/r/WEJqdL/6 "[^\w|>]" . // Must not have an alphanum or _ or > before real method '(' . implode('|', $functions) . ')' . // Must start with one of the functions "\(" . // Match opening parenthesis "[\'\"]" . // Match " or ' '(' . // Start a new group to match: '[\/a-zA-Z0-9_-]+' . // Must start with group "([.](?! )[^\1)]+)+" . // Be followed by one or more items/keys ')' . // Close group "[\'\"]" . // Closing quote "[\),]"; // Close parentheses or new parameter $stringPattern = "[^\w]" . // Must not have an alphanum before real method '(' . implode('|', $functions) . ')' . // Must start with one of the functions "\(\s*" . // Match opening parenthesis "(?P<quote>['\"])" . // Match " or ' and store in {quote} "(?P<string>(?:\\\k{quote}|(?!\k{quote}).)*)" . // Match any string that can be {quote} escaped "\k{quote}" . // Match " or ' previously matched "\s*[\),]"; // Close parentheses or new parameter // Find all PHP + Twig files in the app folder, except for storage $finder = new Finder(); $finder->in($path)->exclude('storage')->exclude('vendor')->name('*.php')->name('*.twig')->name('*.vue')->files(); /** @var \Symfony\Component\Finder\SplFileInfo $file */ foreach ($finder as $file) { // Search the current file for the pattern if (preg_match_all("/$groupPattern/siU", $file->getContents(), $matches)) { // Get all matches foreach ($matches[2] as $key) { $groupKeys[] = $key; } } if (preg_match_all("/$stringPattern/siU", $file->getContents(), $matches)) { foreach ($matches['string'] as $key) { if (preg_match("/(^[\/a-zA-Z0-9_-]+([.][^\1)\ ]+)+$)/siU", $key, $groupMatches)) { // group{.group}.key format, already in $groupKeys but also matched here // do nothing, it has to be treated as a group continue; } //TODO: This can probably be done in the regex, but I couldn't do it. //skip keys which contain namespacing characters, unless they also contain a //space, which makes it JSON. if (!(Str::contains($key, '::') && Str::contains($key, '.')) || Str::contains($key, ' ')) { $stringKeys[] = $key; } } } } // Remove duplicates $groupKeys = array_unique($groupKeys); $stringKeys = array_unique($stringKeys); // Add the translations to the database, if not existing. foreach ($groupKeys as $key) { // Split the group and item list($group, $item) = explode('.', $key, 2); $this->missingKey('', $group, $item); } foreach ($stringKeys as $key) { $group = self::JSON_GROUP; $item = $key; $this->missingKey('', $group, $item); } // Return the number of found translations return count($groupKeys + $stringKeys); } public function missingKey($namespace, $group, $key) { if (!in_array($group, $this->config['exclude_groups'])) { Translation::firstOrCreate([ 'locale' => $this->app['config']['app.locale'], 'group' => $group, 'key' => $key, ]); } } public function exportTranslations($group = null, $json = false, $nameSpace = null, $base = null) { $group = basename($group); if ($nameSpace == 'Default') { $basePath = $this->app['path.lang']; } else { $basePath = $base; } if (!is_null($group) && !$json) { if (!in_array($group, $this->config['exclude_groups'])) { $vendor = false; if ($group == '*') { return $this->exportAllTranslations(); } else { if (Str::startsWith($group, 'vendor')) { $vendor = true; } } $translation = Translation::where('namespace', '=', $nameSpace); $tree = $this->makeTree($translation->ofTranslatedGroup($group) ->orderByGroupKeys(Arr::get($this->config, 'sort_keys', false)) ->get()); foreach ($tree as $locale => $groups) { $locale = basename($locale); if (isset($groups[$group])) { $translations = $groups[$group]; $path = $basePath; $locale_path = $locale . DIRECTORY_SEPARATOR . $group; if ($vendor) { $path = $basePath . '/' . $group . '/' . $locale; $locale_path = Str::after($group, '/'); } $subfolders = explode(DIRECTORY_SEPARATOR, $locale_path); array_pop($subfolders); $subfolder_level = ''; foreach ($subfolders as $subfolder) { $subfolder_level = $subfolder_level . $subfolder . DIRECTORY_SEPARATOR; $temp_path = rtrim($path . DIRECTORY_SEPARATOR . $subfolder_level, DIRECTORY_SEPARATOR); if (!is_dir($temp_path)) { mkdir($temp_path, 0777, true); } } $path = $path . DIRECTORY_SEPARATOR . $locale . DIRECTORY_SEPARATOR . $group . '.php'; $output = "<?php\n\nreturn " . var_export($translations, true) . ';' . \PHP_EOL; $this->files->put($path, $output); } } Translation::ofTranslatedGroup($group)->update(['status' => Translation::STATUS_SAVED]); } } if ($json) { $tree = $this->makeTree(Translation::ofTranslatedGroup(self::JSON_GROUP) ->orderByGroupKeys(Arr::get($this->config, 'sort_keys', false)) ->get(), true); foreach ($tree as $locale => $groups) { if (isset($groups[self::JSON_GROUP])) { $translations = $groups[self::JSON_GROUP]; $path = $basePath . '/' . $locale . '.json'; $output = json_encode($translations, \JSON_PRETTY_PRINT | \JSON_UNESCAPED_UNICODE); $this->files->put($path, $output); } } Translation::ofTranslatedGroup(self::JSON_GROUP)->update(['status' => Translation::STATUS_SAVED]); } $this->events->dispatch(new TranslationsExportedEvent()); } public function exportAllTranslations() { $groups = Translation::whereNotNull('value')->selectDistinctGroup()->get('group'); foreach ($groups as $group) { if ($group->group == self::JSON_GROUP) { $this->exportTranslations(null, true); } else { $this->exportTranslations($group->group); } } $this->events->dispatch(new TranslationsExportedEvent()); } protected function makeTree($translations, $json = false) { $array = []; foreach ($translations as $translation) { if ($json) { $this->jsonSet($array[$translation->locale][$translation->group], $translation->key, $translation->value); } else { Arr::set($array[$translation->locale][$translation->group], $translation->key, $translation->value); } } return $array; } public function jsonSet(&$array, $key, $value) { if (is_null($key)) { return $array = $value; } $array[$key] = $value; return $array; } public function cleanTranslations() { Translation::whereNull('value')->delete(); } public function truncateTranslations() { Translation::truncate(); } public function getLocales() { if (empty($this->locales)) { $locales = array_merge([config('app.locale')], Translation::groupBy('locale')->pluck('locale')->toArray()); foreach ($this->files->directories($this->app->langPath()) as $localeDir) { if (($name = $this->files->name($localeDir)) != 'vendor') { $locales[] = $name; } } $this->locales = array_unique($locales); sort($this->locales); } return array_diff($this->locales, $this->ignoreLocales); } public function addLocale($locale) { $localeDir = $this->app->langPath() . '/' . basename($locale); $this->ignoreLocales = array_diff($this->ignoreLocales, [$locale]); $this->saveIgnoredLocales(); $this->ignoreLocales = $this->getIgnoredLocales(); if (!$this->files->exists($localeDir) || !$this->files->isDirectory($localeDir)) { return $this->files->makeDirectory($localeDir); } return true; } protected function saveIgnoredLocales() { return $this->files->put($this->ignoreFilePath, json_encode($this->ignoreLocales)); } public function removeLocale($locale) { if (!$locale) { return false; } $this->ignoreLocales = array_merge($this->ignoreLocales, [$locale]); $this->saveIgnoredLocales(); $this->ignoreLocales = $this->getIgnoredLocales(); Translation::where('locale', $locale)->delete(); } public function getConfig($key = null) { if ($key == null) { return $this->config; } else { return $this->config[$key]; } } }