diff --git a/.env.example b/.env.example index 281445b..753a98e 100644 --- a/.env.example +++ b/.env.example @@ -71,3 +71,8 @@ AWS_BUCKET= AWS_USE_PATH_STYLE_ENDPOINT=false VITE_APP_NAME="${APP_NAME}" + + +XLANG_ACTIVE=false +XLANG_MAIN=en +XLANG_API_URL="http://5.255.98.77:3001" diff --git a/app/Http/Controllers/Admin/XLangController.php b/app/Http/Controllers/Admin/XLangController.php new file mode 100644 index 0000000..af04a9a --- /dev/null +++ b/app/Http/Controllers/Admin/XLangController.php @@ -0,0 +1,327 @@ + + ['title' => "Edit", 'class' => 'btn-outline-primary', 'icon' => 'ri-edit-2-line'], + 'show' => + ['title' => "Detail", 'class' => 'btn-outline-light', 'icon' => 'ri-eye-line'], + 'destroy' => + ['title' => "Remove", 'class' => 'btn-outline-danger delete-confirm', 'icon' => 'ri-close-line'], + ]; + + + public function __construct() + { + parent::__construct(XLang::class, XLangSaveRequest::class); + } + + /** + * @param $xlang XLang + * @param $request XLangSaveRequest + * @return XLang + */ + public function save($xlang, $request) + { + + + if ($xlang->id == null && $request->tag != 'en') { + + define("TRANSLATE_CONFIG_PATH", PREFIX_PATH . 'config/translator.php'); + define("TRANSLATE_NEW_FILE", PREFIX_PATH . 'resources/lang/' . $request->tag . '.json'); + $config = file_get_contents(TRANSLATE_CONFIG_PATH); + $re = '/\'languages\' \=\> (.*)\,/m'; + preg_match_all($re, $config, $matches, PREG_SET_ORDER, 0); + $oldLangs = $matches[0][1]; + + $newLans = json_encode(array_unique(array_merge(json_decode($oldLangs), [$request->tag]))); + $newConfig = (str_replace($oldLangs, $newLans, $config)); + file_put_contents(TRANSLATE_CONFIG_PATH, $newConfig); + + if (!file_exists(TRANSLATE_NEW_FILE)) { + file_put_contents(TRANSLATE_NEW_FILE, '{}'); + } + } + $xlang->name = $request->input('name'); + $xlang->tag = $request->input('tag'); + $xlang->rtl = $request->has('rtl'); + + $xlang->is_default = $request->has('is_default'); + if ($xlang->is_default) { + Xlang::where('is_default', '1')->update([ + 'is_default' => 0, + ]); + } + + if (!$request->has('emoji')) { + $xlang->emoji = $request->input('emoji'); + } else { + $xlang->emoji = getEmojiLanguagebyCode($xlang->tag); + } + + + if ($request->has('img')) { + $xlang->img = $this->storeFile('img', $xlang, 'langz'); + $key = 'img'; + $format = $request->file($key)->guessExtension(); + if (strtolower($format) == 'png') { + $format = 'webp'; + } + $i = SpatieImage::load($request->file($key)->getPathname()) + ->optimize() +// ->nonQueued() + ->format($format); + $i->save(storage_path() . '/app/public/langz/optimized-' . $xlang->$key); + } + $xlang->save(); + Artisan::call('translator:update'); + return $xlang; + + } + + + /** + * Show the form for creating a new resource. + */ + public function create() + { + // + return view($this->formView); + } + + /** + * Show the form for editing the specified resource. + */ + public function edit(XLang $item) + { + // + return view($this->formView, compact('item')); + } + + public function bulk(Request $request) + { + +// dd($request->all()); + $data = explode('.', $request->input('action')); + $action = $data[0]; + $ids = $request->input('id'); + switch ($action) { + case 'delete': + $msg = __(':COUNT items deleted successfully', ['COUNT' => count($ids)]); + $this->_MODEL_::destroy($ids); + break; + /**restore*/ + case 'restore': + $msg = __(':COUNT items restored successfully', ['COUNT' => count($ids)]); + foreach ($ids as $id) { + $this->_MODEL_::withTrashed()->find($id)->restore(); + } + break; + /*restore**/ + default: + $msg = __('Unknown bulk action : :ACTION', ["ACTION" => $action]); + } + + return $this->do_bulk($msg, $action, $ids); + } + + public function destroy(XLang $item) + { + return parent::delete($item); + } + + + public function update(Request $request, XLang $item) + { + return $this->bringUp($request, $item); + } + + /**restore*/ + public function restore($item) + { + return parent::restoreing(XLang::withTrashed()->where('id', $item)->first()); + } + + /*restore**/ + + public function translate() + { + $langs = Xlang::all(); +// return Product::where('name->en',null)->get(); + return view('admin.xlangs.xlang-translates', compact('langs')); + } + + public function download($tag) + { + define("TRANSLATE_FILE", PREFIX_PATH . 'resources/lang/' . $tag . '.json'); + return response()->download(TRANSLATE_FILE, $tag . '.json'); + } + + public function upload($tag, Request $request) + { + define("TRANSLATE_FILE", PREFIX_PATH . 'resources/lang/' . $tag . '.json'); + if (!$request->hasFile('json')) { + return redirect()->back(); + } + $data = (file_get_contents($request->file('json')->getRealPath())); + if (json_decode($data) == null) { + return redirect()->back()->withErrors(__("Invalid json file!")); + } + file_put_contents(TRANSLATE_FILE, $data); + return redirect()->back()->with(['message' => __("Translate updated")]); + } + + + public function ai($tag) + { + +// set_time_limit(300); + + define("TRANSLATE_FILE", PREFIX_PATH . 'resources/lang/' . $tag . '.json'); + $file = file_get_contents(TRANSLATE_FILE); + $url = config('app.xlang.api_url') . '/json?form=en&to=' . $tag; + + $client = new Client([ + 'headers' => ['Content-Type' => 'application/json'] + ]); + + $response = $client->post($url, + ['body' => $file] + ); + file_put_contents(TRANSLATE_FILE, $response->getBody()->getContents()); + return redirect()->back()->with(['message' => __("Translated by ai xstack service :TAG", ['TAG' => $tag])]); + } + + public function translateModel($id, $model) + { + + if (!in_array($model, $this->allowedModels)) { + return abort(404); + } + $langs = Xlang::where('is_default', 0)->get(); + $cls = $model; + $model = ($model)::where('id', $id)->firstOrFail(); +// return $model; + $translates = $model->translatable; + return view('admin.xlangs.xlang-translate-model', compact('model', 'translates', 'langs', 'cls')); + } + + public function translateModelSave($id, $model, Request $request) + { + + if (!in_array($model, $this->allowedModels)) { + return abort(404); + } + $langs = Xlang::where('is_default', 0)->get(); + $model = ($model)::where('id', $id)->firstOrFail(); +// $model = Product::whereId('id',$id)->first(); + foreach ($request->input('data') as $lang => $items) { + foreach ($items as $k => $item) { + if ($item != null) { + $model->setTranslation($k, $lang, $item); + } + } + } + + $model->save(); + return redirect()->back()->with(['message' => __('Translate updated')]); + + } + + public function translateModelAi($id, $model, $tag, $field) + { + + if (!in_array($model, $this->allowedModels)) { + return abort(404); + } + $langs = Xlang::where('is_default', 0)->get(); + $model = ($model)::where('id', $id)->firstOrFail(); +// $model = Product::whereId('id',$id)->first(); + $url = config('app.xlang.api_url').'/text?form=' . config('app.xlang_main') . '&to=' . $tag; + + $client = new Client([ + 'headers' => ['Content-Type' => 'application/x-www-form-urlencoded'] + ]); + + $response = $client->post($url, + ['form_params' => ['body' => $model->$field]], + ); +// file_put_contents(TRANSLATE_FILE, $response->getBody()); + if ($response->getStatusCode() != 200) { + return redirect()->back()->withErrors(__("API error!")); + } +// dd($response->getBody()->getContents()); + $model->setTranslation($field, $tag, $response->getBody()->getContents()); + $model->save(); + return redirect()->back()->with(['message' => __('Translate updated')]); + + } + +} diff --git a/app/Http/Requests/XLangSaveRequest.php b/app/Http/Requests/XLangSaveRequest.php new file mode 100644 index 0000000..3ab48f1 --- /dev/null +++ b/app/Http/Requests/XLangSaveRequest.php @@ -0,0 +1,31 @@ +check() && auth()->user()->hasRole('developer'); + } + + /** + * Get the validation rules that apply to the request. + * + * @return array|string> + */ + public function rules(): array + { + return [ + 'name' => ['required','string','min:3','max:128'], + 'tag' => ['required','alpha_dash:','min:2','max:7'], + 'img' => ['nullable','file','mimes:svg,png,jpg,gif'], + 'emoji' => ['nullable','string'] + ]; + } +} diff --git a/app/Models/XLang.php b/app/Models/XLang.php index 716e02a..7cee8a0 100644 --- a/app/Models/XLang.php +++ b/app/Models/XLang.php @@ -4,8 +4,32 @@ namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\SoftDeletes; class XLang extends Model { - use HasFactory; + use HasFactory,SoftDeletes; + + protected $table = 'xlangs'; + + public function imgUrl() + { + if ($this->img == null || $this->img == '') { + return asset('/assets/upload/logo.svg'); + } else { + return \Storage::url('langz/optimized-' . $this->img); + } + } + public function imgOriginalUrl() + { + if ($this->img == null || $this->img == '') { + return asset('/assets/upload/logo.svg'); + } else { + return \Storage::url('langz/' . $this->img); + } + } + + public function getRouteKeyName(){ + return 'tag'; + } } diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 1a6b261..96bbd59 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -11,6 +11,7 @@ use Carbon\Carbon; use Illuminate\Pagination\Paginator; use Illuminate\Support\Facades\Blade; use Illuminate\Support\ServiceProvider; +use Translator\Framework\TranslatorCommand; class AppServiceProvider extends ServiceProvider { @@ -20,6 +21,9 @@ class AppServiceProvider extends ServiceProvider public function register(): void { // + $this->commands([ + TranslatorCommand::class, + ]); } /** diff --git a/config/app.php b/config/app.php index 5bc4f2b..f125a56 100644 --- a/config/app.php +++ b/config/app.php @@ -152,6 +152,11 @@ return [ 'watermark_size' => env('MEDIA_WATERMARK_SIZE',15), 'watermark_opacity' => env('MEDIA_WATERMARK_OPACITY',50), ], + 'xlang' => [ + 'active' => (bool) env('XLANG_ACTIVE',false), + 'main' => env('XLANG_MAIN','en'), + 'api_url' => env('XLANG_API_URL',''), + ], diff --git a/config/translator.php b/config/translator.php index 8590ce6..4deb839 100644 --- a/config/translator.php +++ b/config/translator.php @@ -4,7 +4,7 @@ use Translator\Framework\LaravelConfigLoader; use Translator\Infra\LaravelJsonTranslationRepository; return [ - 'languages' => ['fa'], + 'languages' => ["fa","ar"], 'directories' => [ app_path(), resource_path('views'), diff --git a/database/migrations/0002_05_07_125311_create_x_langs_table.php b/database/migrations/0002_05_07_125311_create_x_langs_table.php index 3e214cb..75ce1ea 100644 --- a/database/migrations/0002_05_07_125311_create_x_langs_table.php +++ b/database/migrations/0002_05_07_125311_create_x_langs_table.php @@ -11,8 +11,16 @@ return new class extends Migration */ public function up(): void { - Schema::create('x_langs', function (Blueprint $table) { + Schema::create('xlangs', function (Blueprint $table) { $table->id(); + $table->string('name'); + $table->string('tag',7)->unique(); + $table->boolean('rtl')->default(false); + $table->boolean('is_default')->default(false); + $table->string('img')->nullable()->default(null); + $table->string('emoji')->nullable()->default(null); + $table->tinyInteger('sort')->default(0); + $table->softDeletes(); $table->timestamps(); }); } diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index 3b5970a..fe9eb63 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -23,6 +23,7 @@ class DatabaseSeeder extends Seeder '); $this->call([ + XLangSeeder::class, UserSeeder::class, GroupSeeder::class, PostSeeder::class, diff --git a/database/seeders/XLangSeeder.php b/database/seeders/XLangSeeder.php index 1829278..bf4341e 100644 --- a/database/seeders/XLangSeeder.php +++ b/database/seeders/XLangSeeder.php @@ -2,6 +2,7 @@ namespace Database\Seeders; +use App\Models\XLang; use Illuminate\Database\Console\Seeds\WithoutModelEvents; use Illuminate\Database\Seeder; @@ -13,5 +14,29 @@ class XLangSeeder extends Seeder public function run(): void { // + + + $langz = [ + 'en' => 'English', + 'ar' => 'عربي', + 'es' => 'Spanish', + 'fr' => 'French', + 'pt' => 'Portuguese', + 'fa' => 'پارسی', + 'ru' => 'Русский', + 'de' => 'Deutsch', + 'ro' => 'Romanian', + 'it' => 'Italian', + 'zh'=> '简化字', + ]; + if (config('app.xlang.active')) { + $lang = new XLang(); + $lang->tag = config('app.xlang.main'); + $lang->emoji = getEmojiLanguagebyCode(config('app.xlang.main')); + $lang->name = $langz[config('app.xlang.main')]??config('app.xlang.main'); + $lang->rtl = langIsRTL(config('app.xlang.main')); + $lang->is_default = true; + $lang->save(); + } } } diff --git a/resources/js/panel/editor-handle.js b/resources/js/panel/editor-handle.js index bcb281f..044f39c 100644 --- a/resources/js/panel/editor-handle.js +++ b/resources/js/panel/editor-handle.js @@ -1,11 +1,17 @@ window.addEventListener('load', function () { - let dirx = 'ltr'; + let dirx = document.querySelector('#panel-dir').value; let editors = {}; document.querySelectorAll('.ckeditorx')?.forEach(function (el) { + + const currentDir = el.getAttribute('dir'); + let finalDir = dirx; + if (currentDir != null){ + finalDir = currentDir; + } editors[el.getAttribute('name')] = CKEDITOR.replace(el.getAttribute('name'), { filebrowserUploadUrl: xupload, filebrowserUploadMethod: 'form', - contentsLangDirection: dirx, + contentsLangDirection: finalDir, skin: 'moono-dark', }); diff --git a/resources/lang/ar.json b/resources/lang/ar.json new file mode 100644 index 0000000..f9e23a8 --- /dev/null +++ b/resources/lang/ar.json @@ -0,0 +1,58 @@ +{ + " days ago": "منذ أيام", + " hours ago": "منذ ساعات", + " minutes ago": "منذ دقائق", + " seconds ago": "منذ ثواني", + "$role": "$ دور", + ":ADDRESS removed": ": تمت إزالة العنوان", + ":COUNT Images uploaded successfully": ":تم تحميل COUNT من الصور بنجاح", + ":COUNT items answered successfully": ":تم الرد على COUNT من العناصر بنجاح", + ":COUNT items changed status successfully": ": تم تغيير حالة COUNT من العناصر بنجاح", + ":COUNT items closed successfully": ":تم إغلاق COUNT من العناصر بنجاح", + ":COUNT items deleted successfully": ":تم حذف COUNT من العناصر بنجاح", + ":COUNT items drafted successfully": ": تمت صياغة COUNT من العناصر بنجاح", + ":COUNT items pending successfully": ":COUNT من العناصر المعلقة بنجاح", + ":COUNT items published successfully": ":تم نشر COUNT من العناصر بنجاح", + ":COUNT items restored successfully": ": تمت استعادة COUNT من العناصر بنجاح", + ":COUNT users role changed to :NEWROLE successfully": ":تم تغيير دور COUNT من المستخدمين إلى :COUNT بنجاح", + "A fresh verification link has been sent to your email address.": "تم إرسال رابط تحقق جديد إلى عنوان بريدك الإلكتروني.", + "Add": "أضف", + "Add another one": "أضف واحدًا آخر", + "Add cover to better results": "أضف غطاء لنتائج أفضل", + "Add new adv": "إضافة إعلان جديد", + "Add new attachment": "إضافة مرفق جديد", + "Add new category": "إضافة تصنيف جديد", + "Add new city": "إضافة مدينة جديدة", + "Add new clip": "إضافة مقطع جديد", + "Add new comment": "إضافة تعليق جديد", + "Add new contact": "إضافة جهة اتصال جديدة", + "Add new customer": "إضافة عميل جديد", + "Add new discount": "إضافة خصم جديد", + "Add new gallery": "إضافة معرض جديد", + "Add new group": "إضافة مجموعة جديدة", + "Add new language": "إضافة لغة جديدة", + "Add new post": "إضافة مشاركة جديدة", + "Add new product": "إضافة منتج جديد", + "Add new prop": "إضافة دعامة جديدة", + "Add new question": "إضافة سؤال جديد", + "Add new setting": "إضافة إعداد جديد", + "Add new slider": "إضافة شريط تمرير جديد", + "Add new state": "إضافة حالة جديدة", + "Add new ticket": "إضافة تذكرة جديدة", + "Add new transport": "إضافة وسيلة نقل جديدة", + "Add new user": "إضافة مستخدم جديد", + "Add to setting": "أضف إلى الإعداد", + "Added by:": "أضيفت بواسطة :", + "Additional data": "بيانات إضافية", + "Address added to :CUSTOMER": "تم إضافة العنوان إلى :CUSTOMER", + "Addresses": "العناوين", + "Advertise": "أعلن", + "Advs list": "قائمة الإعلانات", + "Amount": "المبلغ", + "Answer": "الإجابة", + "Answered": "تمت الإجابة", + "Approve": "موافقة", + "Approved": "تمت الموافقة", + "Area design": "تصميم المنطقة", + "yesterday": "أمس" +} \ No newline at end of file diff --git a/resources/lang/fa.json b/resources/lang/fa.json index 481c941..53f0fc7 100644 --- a/resources/lang/fa.json +++ b/resources/lang/fa.json @@ -30,6 +30,7 @@ "Add new discount": "افزودن یک تخفیف", "Add new gallery": "افزودن یک گالری", "Add new group": "افزودن یک سرفصل", + "Add new language": "افزودن یک زبان جدید", "Add new post": "افزودن یک نوشته", "Add new product": "افزودن یک محصول", "Add new prop": "افزودن یک ویژگی", @@ -103,6 +104,7 @@ "Dashboard": "پیشخوان", "Date": "تاریخ", "Deattach": "عدم پیوست", + "Default": "پیش‌فرض", "Description": "توضیحات", "Description Table": "جدول توضیحات", "Description Text": "نوشته توضیحات", @@ -115,6 +117,7 @@ "Do it": "انجام بده", "Double click on image to change index image": "برای تغییر تصویر شاخص روی آن جفت کلیک کنید", "Download": "بارگیری", + "Download json file": "", "Draft": "پیش‌نویس", "E-mail is unique each users": "رایانامه هر کاربر یکتا است", "Edit": "ویرایش", @@ -129,6 +132,7 @@ "Edit discount": "ویرایش تخفیف", "Edit gallery": "ویرایش گالری", "Edit group": "ویرایش سرفصل", + "Edit language": "ویرایش زبان", "Edit post": "ویرایش نوشته", "Edit product": "ویرایش محصول", "Edit prop": "ویرایش ویژگی", @@ -140,6 +144,7 @@ "Edit user": "ویرایش کاربر", "Email": "رایانامه", "Email Address": "نشانی ایمیل", + "Emoji": "ایموجی", "Excerpt": "خلاصه", "Expire": "انقضا", "Expire date": "تاریخ انقضا", @@ -150,6 +155,7 @@ "File ext": "پسوند پرونده", "File name": "نام پرونده", "File size": "حجم پرونده", + "Flag": "پرچم", "Forgot Your Password?": "آیا گذرواژه خود را فراموش کردید", "From - To": "از - تا", "GFX of website updated": "گرافیک سایت به روز شد", @@ -174,6 +180,7 @@ "Information": "اطلاعات", "Interaction": "تعامل", "Invalid area segment": "", + "Invalid json file!": "", "Invalid morph": "چند ریخیتی نا معتبر", "Invoices": "صورت‌حساب‌ها", "Is default": "آی پیش‌فرض است", @@ -182,6 +189,7 @@ "Key": "کلید", "Label": "برچسب", "Languages": "زبان‌ها", + "Languages list": "فهرست زبان‌ها", "Latitude": "عرض جغرافیایی", "Link": "پیوند", "Login": "ورود", @@ -230,6 +238,7 @@ "Question\/Message": "سوال|پیام", "Questions": "سوالات", "Questions list": "فهرست سوالات", + "RTL": "راست به چپ", "Recommends": "توصیه‌ها", "Register": "ثبت‌نام", "Reject": "رد کردن", @@ -276,6 +285,7 @@ "Stock quantity": "موجود انبار", "Subject": "عنوان", "Subtitle": "زیرعنوان", + "Tag": "برچسب", "Tags": "برچسب‌ها", "Tags, Press enter": "برچسب‌ها، Enter را بزنید", "The first and\/or second image will be index image": "اولی وی دومی به عنواان تصویر شاخص در نظر گرفته می‌شود", @@ -291,6 +301,8 @@ "Toggle navigation": "", "Toggle selection": "برعکس کردن انتخاب", "Totol": "همه", + "Translate updated": "", + "Translate with AI": "", "Transports": "حمل و نقل‌ها", "Transports list": "فهرست حمل و نقل‌ها", "Trashed": "حذف شده‌ها", @@ -299,6 +311,7 @@ "Type": "نوع", "Unit": "واحد", "Unknown bulk action : :ACTION": "کار دسته جمعی تعریف نشده :ACTION", + "Upload file": "", "Upload images": "بارگزاری تصاویر", "Upload new images": "بارگزاری تصاویر جدید", "User filter": "صافی کاربر", @@ -321,6 +334,7 @@ "approved": "تایید شد", "area :NAME of website updated": "محیط :NAME وبسایت به روز شد", "click here to request another": "برای ایجاد درخواست دیگر اینجا کلیک کنید", + "emoji": "ایموجی", "image": "تصویر", "jpg": "", "minute": "دقیق", @@ -332,4 +346,4 @@ "webp": "", "xShop": "", "yesterday": "دیروز" -} +} \ No newline at end of file diff --git a/resources/views/admin/templates/panel-list-template.blade.php b/resources/views/admin/templates/panel-list-template.blade.php index 9e7be2c..cfc8ede 100644 --- a/resources/views/admin/templates/panel-list-template.blade.php +++ b/resources/views/admin/templates/panel-list-template.blade.php @@ -110,11 +110,11 @@
+ data-bs-toggle="tooltip" + data-bs-placement="top" + data-bs-custom-class="custom-tooltip" + data-bs-title="{{__("Check all")}}" + class="form-check form-switch mt-1 mx-2">
@@ -158,7 +158,7 @@ @if(isset($item) && method_exists($item,'imgUrl')) - + @endif @@ -257,6 +257,15 @@ @endforeach + @if(config('app.xlang.active') && isset($item->translatable)) +
  • + + +   + {{__("Translate")}} + +
  • + @endif @endif @@ -298,6 +307,12 @@ @endif @endif @endforeach + @if(config('app.xlang.active') && isset($item->translatable)) + + + + @endif @@ -315,12 +330,12 @@
    + id="toggle-select" + class="btn btn-outline-light mx-2" + data-bs-toggle="tooltip" + data-bs-placement="top" + data-bs-custom-class="custom-tooltip" + data-bs-title="{{__("Toggle selection")}}">
    diff --git a/resources/views/admin/xlangs/xlang-form.blade.php b/resources/views/admin/xlangs/xlang-form.blade.php new file mode 100644 index 0000000..b9b147a --- /dev/null +++ b/resources/views/admin/xlangs/xlang-form.blade.php @@ -0,0 +1,105 @@ +@extends('admin.templates.panel-form-template') +@section('title') + @if(isset($item)) + {{__("Edit language")}} [{{$item->tag}}] + @else + {{__("Add new language")}} + @endif - +@endsection +@section('form') + +
    +
    + + @include('components.err') +
    +

    + + {{__("Tips")}} +

    +
      +
    • + {{__("Recommends")}} +
    • +
    +
    + +
    +
    +
    + +

    + @if(isset($item)) + {{__("Edit language")}} [{{$item->tag}}] + @else + {{__("Add new language")}} + @endif +

    + + + +
    +
    +
    + + +
    +
    +
    +
    + + +
    +
    +
    +
    + + +
    +
    +
    +
    + + +
    +
    +
    +
    +
    + rtl??null) == 1) checked="" @endif + value="1" > + +
    +
    +
    +
    +
    + is_default??null) == 1) checked="" @endif + value="1" > + +
    +
    +
    + + +
    +
    + +
    +
    +
    +@endsection diff --git a/resources/views/admin/xlangs/xlang-list.blade.php b/resources/views/admin/xlangs/xlang-list.blade.php new file mode 100644 index 0000000..a32f123 --- /dev/null +++ b/resources/views/admin/xlangs/xlang-list.blade.php @@ -0,0 +1,28 @@ +@extends('admin.templates.panel-list-template') + +@section('list-title') + + {{__("Languages list")}} +@endsection +@section('title') + {{__("Languages list")}} - +@endsection +@section('filter') + {{-- Other filters --}} +@endsection +@section('bulk') + {{-- --}} +@endsection +@section('list-foot') + + + +@endsection diff --git a/resources/views/admin/xlangs/xlang-translate-model.blade.php b/resources/views/admin/xlangs/xlang-translate-model.blade.php new file mode 100644 index 0000000..84bbb68 --- /dev/null +++ b/resources/views/admin/xlangs/xlang-translate-model.blade.php @@ -0,0 +1,91 @@ +@extends('layouts.app') +@section('title') + {{__("Translate model")}}: {{($model->{$translates[0]})}} + - +@endsection +@section('content') + + @include('components.err') + + +
    + +

    + {{__("Translate model")}}: {{($model->{$translates[0]})}} +

    + +

    + {{__("Main language content")}}:({{config('app.xlang.main')}}) +

    +
    + + + + + + @foreach($translates as $tr) + + + + + @endforeach +
    + {{__("Title")}} + + {{__("Value")}} +
    + {{$tr}} + + {{($model->{$tr})}} +
    +
    + +
    + +
    + + @csrf + @foreach($langs as $lang) +
    +

    + {{__("Translate model")}}: {{$lang->name}} ({{$lang->tag}}) +

    + @foreach($translates as $tr) +
    + +
    +
    + + @if( $tr == 'body' || $tr == 'desc' || $tr == 'description' || $tr == 'excerpt' || $tr == 'table') + + + @else + tag)) dir="rtl" @else dir="ltr" @endif type="text" + id="{{$lang->tag}}{{$tr}}" name="data[{{$lang->tag}}][{{$tr}}]" + value="{{gettype($model->getTranslation($tr,$lang->tag)) == 'string' ? $model->getTranslation($tr,$lang->tag):'' }}" + placeholder="" class="form-control"> + @endif +
    +
    + + + +
    +
    +
    + @endforeach +
    + @endforeach + +
    + +@endsection diff --git a/resources/views/admin/xlangs/xlang-translates.blade.php b/resources/views/admin/xlangs/xlang-translates.blade.php new file mode 100644 index 0000000..3679096 --- /dev/null +++ b/resources/views/admin/xlangs/xlang-translates.blade.php @@ -0,0 +1,45 @@ +@extends('layouts.app') +@section('content') + + @include('components.err') + +
    + @foreach($langs as $lang) + +
    +
    +
    + {{$lang->name}} [ {{$lang->emoji}} ] +
    + {{$lang->tag}} + @if($lang->tag != 'en') + + + + {{__("Download json file")}} + + @else + + + {{__("Download json file")}} + + @endif +
    + @csrf + + +
    + tag != 'en') href="{{route('admin.lang.ai',$lang->tag)}}" @endif class="btn btn-outline-success w-100 mt-3 btn-sm "> + + {{__("Translate with AI")}} + +
    +
    + @endforeach +
    +@endsection diff --git a/resources/views/components/panel-side-navbar.blade.php b/resources/views/components/panel-side-navbar.blade.php index 9573a55..96a8bf3 100644 --- a/resources/views/components/panel-side-navbar.blade.php +++ b/resources/views/components/panel-side-navbar.blade.php @@ -218,12 +218,14 @@ {{__('Logs of guests')}} -
  • - - - {{__("Languages")}} - -
  • + @if(auth()->user()->hasRole('developer') && config('app.xlang.active')) +
  • + + + {{__("Languages")}} + +
  • + @endif
  • + + @include('components.panel-top-navbar')
    diff --git a/routes/web.php b/routes/web.php index 404bd85..89f5825 100644 --- a/routes/web.php +++ b/routes/web.php @@ -1,5 +1,6 @@ name('admin.')->group( ); }); + + Route::prefix('langs')->name('lang.')->group( + function () { + Route::get('/', [\App\Http\Controllers\Admin\XLangController::class, 'index'])->name('index'); + Route::get('/translates', [\App\Http\Controllers\Admin\XLangController::class, 'translate'])->name('translate'); + Route::get('/delete/{item}', [\App\Http\Controllers\Admin\XLangController::class, 'destroy'])->name('delete'); + Route::get('/create', [\App\Http\Controllers\Admin\XLangController::class, 'create'])->name('create'); + Route::post('/store', [\App\Http\Controllers\Admin\XLangController::class, 'store'])->name('store'); + Route::get('/edit/{item}', [\App\Http\Controllers\Admin\XLangController::class, 'edit'])->name('edit'); + Route::post('/update/{item}', [\App\Http\Controllers\Admin\XLangController::class, 'update'])->name('update'); + Route::post('bulk', [\App\Http\Controllers\Admin\XLangController::class, "bulk"])->name('bulk'); + Route::get('/download/{tag}', [\App\Http\Controllers\Admin\XLangController::class, 'download'])->name('download'); + Route::get('/ai/{tag}', [\App\Http\Controllers\Admin\XLangController::class, 'ai'])->name('ai'); + Route::post('/upload/{tag}', [\App\Http\Controllers\Admin\XLangController::class, 'upload'])->name('upload'); + Route::get('/model/translate/{id}/{model}', [\App\Http\Controllers\Admin\XLangController::class, 'translateModel'])->name('model'); + Route::post('/model/translate/save/{id}/{model}', [\App\Http\Controllers\Admin\XLangController::class, 'translateModelSave'])->name('modelSave'); + Route::get('/model/ai/{id}/{model}/{field}/{lang}', [\App\Http\Controllers\Admin\XLangController::class, 'translateModelAi'])->name('aiText'); + Route::get('restore/{item}', [\App\Http\Controllers\Admin\XLangController::class, 'restore'])->name('restore'); + Route::get('trashed', [\App\Http\Controllers\Admin\XLangController::class, "trashed"])->name('trashed'); + + }); + }); Route::get('test',function (){ - // return \Resources\Views\Segments\PreloaderCircle::onAdd(); + Log::info('--test--'); + $i = \App\Models\Product::first(); + return get_class($i); - Log::info('--test--'); });