245 lines
6.5 KiB
PHP
245 lines
6.5 KiB
PHP
<?php
|
|
|
|
namespace Modules\Language\Services;
|
|
|
|
use App\Services\MediaService;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Arr;
|
|
use Illuminate\Support\Facades\Cache;
|
|
use Illuminate\Support\Facades\File;
|
|
use Illuminate\Support\Facades\Lang;
|
|
use Modules\Language\Models\Language;
|
|
use Modules\Language\Models\LanguageProperty;
|
|
use Exception;
|
|
|
|
class LanguageService extends MediaService
|
|
{
|
|
public string $cacheKey;
|
|
protected array $groupNames = ['auth', 'button', 'common', 'dashboard', 'frontend', 'input', 'settings', 'table'];
|
|
|
|
public function __construct(Request $request)
|
|
{
|
|
$this->cacheKey = 'language_properties';
|
|
}
|
|
|
|
function storeLanguage($data)
|
|
{
|
|
$langPath = base_path('lang');
|
|
$langDir = $langPath . "/" . $data['code'];
|
|
$appLangPath = storage_path('app/lang/default');
|
|
|
|
|
|
$language = Language::create($data);
|
|
$this->syncLanguagePropertiesFromFiles($language);
|
|
|
|
$alreadyExists = is_dir($langDir);
|
|
|
|
if (! $alreadyExists) {
|
|
File::makeDirectory($langDir, 0777, true, true);
|
|
File::copyDirectory($appLangPath, $langDir);
|
|
}
|
|
}
|
|
|
|
function updateLanguage($id, $data)
|
|
{
|
|
Language::find($id)->update($data);
|
|
}
|
|
|
|
public function syncLanguageFromFiles(string $locale): void
|
|
{
|
|
$language = Language::where('code', $locale)->first();
|
|
|
|
if (! $language) {
|
|
return;
|
|
}
|
|
|
|
$this->syncLanguagePropertiesFromFiles($language);
|
|
$this->forgetLanguageCache($locale);
|
|
}
|
|
|
|
protected function loadLanguageGroup(string $locale, string $groupName): array
|
|
{
|
|
$defaultGroupPath = storage_path("app/lang/groups/{$groupName}.php");
|
|
$defaultGroups = file_exists($defaultGroupPath) ? require $defaultGroupPath : [];
|
|
|
|
$repoGroupPath = base_path("lang/{$locale}/groups/{$groupName}.php");
|
|
if (file_exists($repoGroupPath)) {
|
|
return require $repoGroupPath;
|
|
}
|
|
|
|
$flatFilePath = base_path("lang/{$locale}/{$groupName}.php");
|
|
if (file_exists($flatFilePath)) {
|
|
$flatTranslations = require $flatFilePath;
|
|
return $this->mergeFlatTranslations($defaultGroups, $flatTranslations, $groupName);
|
|
}
|
|
|
|
return $defaultGroups;
|
|
}
|
|
|
|
protected function mergeFlatTranslations(array $defaultGroups, array $flatTranslations, string $groupName): array
|
|
{
|
|
if (empty($defaultGroups)) {
|
|
return [[
|
|
'name' => ucfirst(str_replace('_', ' ', $groupName)),
|
|
'slug' => $groupName,
|
|
'properties' => $flatTranslations,
|
|
]];
|
|
}
|
|
|
|
$groups = [];
|
|
|
|
foreach ($defaultGroups as $group) {
|
|
$properties = [];
|
|
foreach ($group['properties'] as $key => $value) {
|
|
if (array_key_exists($key, $flatTranslations)) {
|
|
$properties[$key] = $flatTranslations[$key];
|
|
unset($flatTranslations[$key]);
|
|
} else {
|
|
$properties[$key] = $value;
|
|
}
|
|
}
|
|
|
|
$groups[] = [
|
|
...$group,
|
|
'properties' => $properties,
|
|
];
|
|
}
|
|
|
|
if (! empty($flatTranslations)) {
|
|
$groups[] = [
|
|
'name' => ucfirst(str_replace('_', ' ', $groupName)) . ' Extra',
|
|
'slug' => "{$groupName}_extra",
|
|
'properties' => $flatTranslations,
|
|
];
|
|
}
|
|
|
|
return $groups;
|
|
}
|
|
|
|
protected function syncLanguagePropertiesFromFiles(Language $language): void
|
|
{
|
|
foreach ($this->groupNames as $groupName) {
|
|
$groups = $this->loadLanguageGroup($language->code, $groupName);
|
|
|
|
foreach ($groups as $group) {
|
|
LanguageProperty::updateOrCreate(
|
|
[
|
|
'language_id' => $language->id,
|
|
'group' => $groupName,
|
|
'slug' => $group['slug'],
|
|
],
|
|
[
|
|
'name' => $group['name'],
|
|
'properties' => $group['properties'],
|
|
]
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
function defaultLanguage($id)
|
|
{
|
|
Language::where('is_default', true)->update(['is_default' => false]);
|
|
Language::where('id', $id)->update(['is_default' => true]);
|
|
}
|
|
|
|
protected function getCacheKey(string $locale): string
|
|
{
|
|
return "{$this->cacheKey}_{$locale}";
|
|
}
|
|
|
|
public function forgetLanguageCache(string $locale): void
|
|
{
|
|
Cache::forget($this->getCacheKey($locale));
|
|
}
|
|
|
|
protected function getDefaultLocale(): string
|
|
{
|
|
$default = Language::where('is_default', true)->value('code');
|
|
|
|
if ($default) {
|
|
return $default;
|
|
}
|
|
|
|
return config('app.locale', 'en');
|
|
}
|
|
|
|
protected function buildTranslationsFromFiles(string $locale): array
|
|
{
|
|
$langPath = lang_path($locale);
|
|
|
|
if (! is_dir($langPath)) {
|
|
return [];
|
|
}
|
|
|
|
$translations = [];
|
|
|
|
foreach (File::allFiles($langPath) as $file) {
|
|
if ($file->getExtension() !== 'php') {
|
|
continue;
|
|
}
|
|
|
|
$group = $file->getFilenameWithoutExtension();
|
|
$values = require $file->getPathname();
|
|
|
|
foreach (Arr::dot($values) as $key => $value) {
|
|
$translations[$group . '.' . $key] = $value;
|
|
}
|
|
}
|
|
|
|
return $translations;
|
|
}
|
|
|
|
function setLanguageProperties(string $locale): void
|
|
{
|
|
$cacheKey = $this->getCacheKey($locale);
|
|
|
|
$cached = Cache::rememberForever($cacheKey, function () use ($locale) {
|
|
$language = Language::where('code', $locale)
|
|
->with('properties')
|
|
->first();
|
|
|
|
if (! $language) {
|
|
return [];
|
|
}
|
|
|
|
$groups = [];
|
|
foreach ($language->properties as $property) {
|
|
$groups[$property->group] = array_merge($groups[$property->group] ?? [], $property->properties);
|
|
}
|
|
|
|
$translations = [];
|
|
foreach ($groups as $group => $properties) {
|
|
foreach ($properties as $key => $value) {
|
|
$translations[$group . '.' . $key] = $value;
|
|
}
|
|
}
|
|
|
|
return $translations;
|
|
});
|
|
|
|
if (empty($cached)) {
|
|
$cached = $this->buildTranslationsFromFiles($locale);
|
|
}
|
|
|
|
Lang::addLines($cached, $locale);
|
|
}
|
|
|
|
function deleteLanguage($id)
|
|
{
|
|
$lang = Language::find($id);
|
|
$langPath = base_path('lang');
|
|
$langDir = $langPath . "/" . $lang->code;
|
|
|
|
if ($lang->is_default) {
|
|
throw new Exception("Default language can't be deleted");
|
|
}
|
|
|
|
if (is_dir($langDir)) {
|
|
File::deleteDirectory($langDir);
|
|
}
|
|
|
|
$lang->delete();
|
|
}
|
|
}
|