mirror of https://github.com/4xmen/xshop.git
added multi language support
parent
d885ce07be
commit
b45f3cbce7
@ -0,0 +1,327 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Admin;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Http\Controllers\XController;
|
||||||
|
use App\Http\Requests\XLangSaveRequest;
|
||||||
|
use App\Models\Access;
|
||||||
|
use App\Models\Attachment;
|
||||||
|
use App\Models\Category;
|
||||||
|
use App\Models\City;
|
||||||
|
use App\Models\Clip;
|
||||||
|
use App\Models\Discount;
|
||||||
|
use App\Models\Gallery;
|
||||||
|
use App\Models\Group;
|
||||||
|
use App\Models\Image;
|
||||||
|
use App\Models\Item;
|
||||||
|
use App\Models\Post;
|
||||||
|
use App\Models\Product;
|
||||||
|
use App\Models\Prop;
|
||||||
|
use App\Models\Setting;
|
||||||
|
use App\Models\Slider;
|
||||||
|
use App\Models\State;
|
||||||
|
use App\Models\Transport;
|
||||||
|
use App\Models\XLang;
|
||||||
|
use GuzzleHttp\Client;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use App\Helper;
|
||||||
|
use Illuminate\Support\Facades\Artisan;
|
||||||
|
use Spatie\Image\Image as SpatieImage;
|
||||||
|
use function App\Helpers\hasCreateRoute;
|
||||||
|
|
||||||
|
|
||||||
|
const PREFIX_PATH = __DIR__ . '/../../../../';
|
||||||
|
|
||||||
|
class XLangController extends XController
|
||||||
|
{
|
||||||
|
|
||||||
|
public $allowedModels = [
|
||||||
|
Attachment::class,
|
||||||
|
Discount::class,
|
||||||
|
Product::class,
|
||||||
|
Category::class,
|
||||||
|
Post::class,
|
||||||
|
Group::class,
|
||||||
|
Slider::class,
|
||||||
|
Item::class,
|
||||||
|
Gallery::class,
|
||||||
|
Clip::class,
|
||||||
|
Prop::class,
|
||||||
|
Setting::class,
|
||||||
|
Image::class,
|
||||||
|
State::class,
|
||||||
|
City::class,
|
||||||
|
Transport::class,
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
// protected $_MODEL_ = XLang::class;
|
||||||
|
// protected $SAVE_REQUEST = XLangSaveRequest::class;
|
||||||
|
|
||||||
|
protected $cols = ['name', 'tag', 'emoji', 'is_default'];
|
||||||
|
protected $extra_cols = ['id', 'img'];
|
||||||
|
|
||||||
|
protected $searchable = [];
|
||||||
|
|
||||||
|
protected $listView = 'admin.xlangs.xlang-list';
|
||||||
|
protected $formView = 'admin.xlangs.xlang-form';
|
||||||
|
|
||||||
|
|
||||||
|
protected $buttons = [
|
||||||
|
'edit' =>
|
||||||
|
['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')]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class XLangSaveRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*/
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return auth()->check() && auth()->user()->hasRole('developer');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|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']
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -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": "أمس"
|
||||||
|
}
|
@ -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')
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-3">
|
||||||
|
|
||||||
|
@include('components.err')
|
||||||
|
<div class="item-list mb-3">
|
||||||
|
<h3 class="p-3">
|
||||||
|
<i class="ri-message-3-line"></i>
|
||||||
|
{{__("Tips")}}
|
||||||
|
</h3>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
{{__("Recommends")}}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-9 ps-xl-1 ps-xxl-1">
|
||||||
|
<div class="general-form ">
|
||||||
|
|
||||||
|
<h1>
|
||||||
|
@if(isset($item))
|
||||||
|
{{__("Edit language")}} [{{$item->tag}}]
|
||||||
|
@else
|
||||||
|
{{__("Add new language")}}
|
||||||
|
@endif
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-8 mt-3">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="name" >
|
||||||
|
{{__('Name')}}
|
||||||
|
</label>
|
||||||
|
<input name="name" type="text" class="form-control @error('name') is-invalid @enderror" id="name" placeholder="{{__('Name')}}" value="{{old('name',$item->name??null)}}" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4 mt-3">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="tag" >
|
||||||
|
{{__('Tag')}}
|
||||||
|
</label>
|
||||||
|
<input name="tag" type="text" class="form-control @error('tag') is-invalid @enderror" id="tag" placeholder="{{__('Tag')}}" value="{{old('tag',$item->tag??null)}}" maxlength="7" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4 mt-3">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="emoji" >
|
||||||
|
{{__('Emoji')}}
|
||||||
|
</label>
|
||||||
|
<input name="emoji" type="text" class="form-control @error('emoji') is-invalid @enderror" id="emoji" placeholder="{{__('emoji')}}" value="{{old('emoji',$item->emoji??null)}}" maxlength="4" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4 mt-3">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="flag" >
|
||||||
|
{{__('Image')}}
|
||||||
|
</label>
|
||||||
|
<input name="img" type="file" class="form-control @error('img') is-invalid @enderror" id="flag" placeholder="{{__('Flag')}}" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-2 mt-3">
|
||||||
|
<div class="form-check form-switch mt-1">
|
||||||
|
<br>
|
||||||
|
<input class="form-check-input @error('rtl') is-invalid @enderror"
|
||||||
|
name="rtl" type="checkbox" id="rtl" @if(old('rtl',$item->rtl??null) == 1) checked="" @endif
|
||||||
|
value="1" >
|
||||||
|
<label for="rtl">
|
||||||
|
{{__('RTL')}}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-2 mt-3">
|
||||||
|
<div class="form-check form-switch mt-1">
|
||||||
|
<br>
|
||||||
|
<input class="form-check-input @error('is_default') is-invalid @enderror"
|
||||||
|
name="is_default" type="checkbox" id="is_default" @if(old('is_default',$item->is_default??null) == 1) checked="" @endif
|
||||||
|
value="1" >
|
||||||
|
<label for="is_default">
|
||||||
|
{{__('Default')}}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 mt-4">
|
||||||
|
<label> </label>
|
||||||
|
<input name="" id="" type="submit" class="btn btn-primary mt-2" value="{{__('Save')}}" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endsection
|
@ -0,0 +1,28 @@
|
|||||||
|
@extends('admin.templates.panel-list-template')
|
||||||
|
|
||||||
|
@section('list-title')
|
||||||
|
<i class="ri-user-3-line"></i>
|
||||||
|
{{__("Languages list")}}
|
||||||
|
@endsection
|
||||||
|
@section('title')
|
||||||
|
{{__("Languages list")}} -
|
||||||
|
@endsection
|
||||||
|
@section('filter')
|
||||||
|
{{-- Other filters --}}
|
||||||
|
@endsection
|
||||||
|
@section('bulk')
|
||||||
|
{{-- <option value="-"> - </option> --}}
|
||||||
|
@endsection
|
||||||
|
@section('list-foot')
|
||||||
|
<a
|
||||||
|
href="{{getRoute('translate')}}"
|
||||||
|
class="action-btn circle-btn"
|
||||||
|
data-bs-toggle="tooltip"
|
||||||
|
data-bs-placement="top"
|
||||||
|
data-bs-custom-class="custom-tooltip"
|
||||||
|
data-bs-title="{{__("Sort")}}"
|
||||||
|
style="inset-inline-end: 1.2rem;inset-inline-start: auto;"
|
||||||
|
>
|
||||||
|
<i class="ri-translate-2"></i>
|
||||||
|
</a>
|
||||||
|
@endsection
|
@ -0,0 +1,91 @@
|
|||||||
|
@extends('layouts.app')
|
||||||
|
@section('title')
|
||||||
|
{{__("Translate model")}}: {{($model->{$translates[0]})}}
|
||||||
|
-
|
||||||
|
@endsection
|
||||||
|
@section('content')
|
||||||
|
|
||||||
|
@include('components.err')
|
||||||
|
|
||||||
|
|
||||||
|
<div class="general-form mb-3">
|
||||||
|
|
||||||
|
<h1>
|
||||||
|
{{__("Translate model")}}: {{($model->{$translates[0]})}}
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
<h4 class="lang-support p-3">
|
||||||
|
{{__("Main language content")}}:({{config('app.xlang.main')}})
|
||||||
|
</h4>
|
||||||
|
<div class="p-3">
|
||||||
|
<table class="table">
|
||||||
|
<tr>
|
||||||
|
<th class="w-25">
|
||||||
|
{{__("Title")}}
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
{{__("Value")}}
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
@foreach($translates as $tr)
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
{{$tr}}
|
||||||
|
</th>
|
||||||
|
<td>
|
||||||
|
{{($model->{$tr})}}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form action="{{route( 'admin.lang.modelSave',[$model->id,$cls])}}" method="post">
|
||||||
|
|
||||||
|
@csrf
|
||||||
|
@foreach($langs as $lang)
|
||||||
|
<div class="general-form mb-3">
|
||||||
|
<h1 class="lang-support">
|
||||||
|
{{__("Translate model")}}: {{$lang->name}} ({{$lang->tag}})
|
||||||
|
</h1>
|
||||||
|
@foreach($translates as $tr)
|
||||||
|
<div class="form-group px-3 pt-2">
|
||||||
|
<label for="{{$lang->tag}}{{$tr}}">
|
||||||
|
{{$tr}}:
|
||||||
|
</label>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-10">
|
||||||
|
|
||||||
|
@if( $tr == 'body' || $tr == 'desc' || $tr == 'description' || $tr == 'excerpt' || $tr == 'table')
|
||||||
|
|
||||||
|
<textarea
|
||||||
|
@if(langIsRTL($lang->tag)) dir="rtl" @else dir="ltr" @endif
|
||||||
|
class="form-control @if($tr == 'body' || $tr == 'desc' || $tr == 'description' || $tr == 'table' ) ckeditorx @endif"
|
||||||
|
rows="4" id="{{$lang->tag}}{{$tr}}"
|
||||||
|
name="data[{{$lang->tag}}][{{$tr}}]">{{gettype($model->getTranslation($tr,$lang->tag)) == 'string' ? $model->getTranslation($tr,$lang->tag):'' }}</textarea>
|
||||||
|
@else
|
||||||
|
<input @if(langIsRTL($lang->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
|
||||||
|
</div>
|
||||||
|
<div class="col-md-2 d-flex align-items-center">
|
||||||
|
<a href="{{route('admin.lang.aiText',[$model->id,$cls,$lang->tag,$tr])}}" class="btn-ai"
|
||||||
|
title="{{__("AI translate form original source")}}">
|
||||||
|
<i class="ri-translate"></i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
@endforeach
|
||||||
|
<button class="btn btn-outline-dark w-100 my-3">
|
||||||
|
{{__("Save")}}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
@endsection
|
@ -0,0 +1,45 @@
|
|||||||
|
@extends('layouts.app')
|
||||||
|
@section('content')
|
||||||
|
|
||||||
|
@include('components.err')
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
@foreach($langs as $lang)
|
||||||
|
|
||||||
|
<div class="col-md-4 mb-4">
|
||||||
|
<div class="item-list p-3">
|
||||||
|
<h5 class="text-center">
|
||||||
|
{{$lang->name}} [ {{$lang->emoji}} ]
|
||||||
|
</h5>
|
||||||
|
<img src="{{$lang->imgUrl()}}" class="img-fluid my-3" alt="{{$lang->tag}}">
|
||||||
|
@if($lang->tag != 'en')
|
||||||
|
|
||||||
|
<a href="{{route('admin.lang.download',$lang->tag)}}"
|
||||||
|
class="btn btn-outline-light w-100 mb-3 btn-sm">
|
||||||
|
<i class="ri-download-2-line"></i>
|
||||||
|
{{__("Download json file")}}
|
||||||
|
</a>
|
||||||
|
@else
|
||||||
|
<a class="btn btn-outline-light w-100 mb-3 btn-sm disabled">
|
||||||
|
<i class="ri-download-2-line"></i>
|
||||||
|
{{__("Download json file")}}
|
||||||
|
</a>
|
||||||
|
@endif
|
||||||
|
<form action="{{route('admin.lang.upload',$lang->tag)}}" method="post"
|
||||||
|
enctype="multipart/form-data">
|
||||||
|
@csrf
|
||||||
|
<input type="file" name="json" id="file" class="form-control mb-2">
|
||||||
|
<button class="btn btn-outline-primary btn-sm w-100 mt-2 " @if($lang->tag == 'en') disabled @endif>
|
||||||
|
<i class="ri-upload-2-line"></i>
|
||||||
|
{{__("Upload file")}}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
<a @if($lang->tag != 'en') href="{{route('admin.lang.ai',$lang->tag)}}" @endif class="btn btn-outline-success w-100 mt-3 btn-sm ">
|
||||||
|
<i class="ri-ai-generate"></i>
|
||||||
|
{{__("Translate with AI")}}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
@endsection
|
Loading…
Reference in New Issue