first upload all files

This commit is contained in:
NW
2023-06-11 13:14:03 +01:00
parent f14dbc52b5
commit c08b36d1b6
1705 changed files with 106852 additions and 0 deletions

View File

@@ -0,0 +1,22 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Define which assets will be available through the asset manager
|--------------------------------------------------------------------------
| These assets are registered on the asset manager
*/
'all_assets' => [
'admin.translation.css' => ['module' => 'translation:admin/css/translation.css'],
'admin.translation.js' => ['module' => 'translation:admin/js/translation.js'],
],
/*
|--------------------------------------------------------------------------
| Define which default assets will always be included in your pages
| through the asset pipeline
|--------------------------------------------------------------------------
*/
'required_assets' => [],
];

View File

@@ -0,0 +1,8 @@
<?php
return [
'admin.translations' => [
'index' => 'translation::permissions.index',
'edit' => 'translation::permissions.edit',
],
];

View File

@@ -0,0 +1,30 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateTranslationsTable extends Migration
{
/**
* Run the migrations.
* @return void
*/
public function up()
{
Schema::create('translations', function (Blueprint $table) {
$table->increments('id');
$table->string('key')->index();
$table->timestamps();
});
}
/**
* Reverse the migrations.
* @return void
*/
public function down()
{
Schema::dropIfExists('translations');
}
}

View File

@@ -0,0 +1,36 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateTranslationTranslationsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('translation_translations', function (Blueprint $table) {
$table->increments('id');
$table->integer('translation_id')->unsigned();
$table->string('locale');
$table->text('value');
$table->unique(['translation_id', 'locale']);
$table->foreign('translation_id')->references('id')->on('translations')->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('translation_translations');
}
}

View File

@@ -0,0 +1,96 @@
<?php
namespace Modules\Translation\Entities;
use Modules\Support\Eloquent\Model;
use Illuminate\Support\Facades\Cache;
use Modules\Support\Eloquent\Translatable;
class Translation extends Model
{
use Translatable;
/**
* The relations to eager load on every query.
*
* @var array
*/
protected $with = ['translations'];
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = ['key'];
/**
* The attributes that are translatable.
*
* @var array
*/
protected $translatedAttributes = ['value'];
/**
* Retrieve all translations.
*
* @return void
*/
public static function retrieve()
{
if (! config('app.cache')) {
return self::getTranslations();
}
return Cache::tags('translations')->rememberForever(md5('translations.all'), function () {
return self::getTranslations();
});
}
protected static function getTranslations()
{
return array_replace_recursive(static::getFileTranslations(), static::getDatabaseTranslations());
}
/**
* Get file translations.
*
* @return array
*/
public static function getFileTranslations()
{
$translations = [];
foreach (resolve('translation.loader')->paths() as $hint => $path) {
foreach (supported_locales() as $locale => $language) {
foreach (glob("{$path}/{$locale}/*.php") as $file) {
foreach (array_dot(require $file) as $key => $value) {
$group = str_replace('.php', '', basename($file));
$translations["{$hint}::{$group}.{$key}"][$locale] = $value;
}
}
}
}
return $translations;
}
/**
* Get database translations.
*
* @return array
*/
public static function getDatabaseTranslations()
{
$translations = [];
foreach (static::all() as $translation) {
foreach ($translation->translations as $translationTranslation) {
$translations[$translation->key][$translationTranslation->locale] = $translationTranslation->value;
}
}
return $translations;
}
}

View File

@@ -0,0 +1,45 @@
<?php
namespace Modules\Translation\Entities;
use Illuminate\Support\Facades\Cache;
use Illuminate\Database\Eloquent\Model;
class TranslationTranslation extends Model
{
/**
* Indicates if the model should be timestamped.
*
* @var bool
*/
public $timestamps = false;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = ['locale', 'value'];
/**
* Perform any actions required after the model boots.
*
* @return void
*/
protected static function booted()
{
static::saved(function ($translationTranslation) {
$translationTranslation->clearCache();
});
}
/**
* Clear translations cache.
*
* @return bool
*/
public static function clearCache()
{
Cache::tags('translations')->flush();
}
}

View File

@@ -0,0 +1,38 @@
<?php
namespace Modules\Translation\Http\Controllers\Admin;
use Modules\Translation\Entities\Translation;
class TranslationController
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
$translations = Translation::retrieve();
return view('translation::admin.translations.index', compact('translations'));
}
/**
* Update the specified resource in storage.
*
* @param string $key
* @return \Illuminate\Http\Response
*/
public function update($key)
{
Translation::firstOrCreate(['key' => $key])
->translations()
->updateOrCreate(
['locale' => request('locale')],
['value' => request('value', '')]
);
return trans('admin::messages.resource_saved', ['resource' => trans('translation::translations.translation')]);
}
}

View File

@@ -0,0 +1,77 @@
<?php
namespace Modules\Translation\Providers;
use Illuminate\Support\Carbon;
use Astrotomic\Translatable\Locales;
use Modules\Support\Traits\AddsAsset;
use Illuminate\Translation\Translator;
use Illuminate\Support\ServiceProvider;
use Modules\Translation\TranslationLoader;
class TranslationServiceProvider extends ServiceProvider
{
use AddsAsset;
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
if (! config('app.installed')) {
return;
}
Carbon::setLocale(locale());
$this->setupTranslatable();
$this->addAdminAssets('admin.translations.index', ['admin.translation.css', 'admin.translation.js']);
}
private function setupTranslatable()
{
$this->app['config']->set('translatable.use_fallback', true);
$this->app['config']->set('translatable.fallback_locale', setting('default_locale'));
$this->app['config']->set('translatable.locales', supported_locale_keys());
// Re-register translatable locales helper after overriding config.
$this->app->singleton('translatable.locales', Locales::class);
$this->app->singleton(Locales::class);
}
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
// The translation loader must be registered first.
$this->registerLoader();
$this->registerTranslator();
}
private function registerLoader()
{
$this->app->singleton('translation.loader', function ($app) {
return new TranslationLoader($app['files'], $app['path.lang']);
});
}
private function registerTranslator()
{
$this->app->singleton('translator', function ($app) {
$loader = $app['translation.loader'];
$locale = $app['config']['app.locale'];
$trans = new Translator($loader, $locale);
$trans->setFallback($app['config']['app.fallback_locale']);
return $trans;
});
}
}

View File

@@ -0,0 +1,29 @@
import '../../../../node_modules/x-editable/dist/bootstrap3-editable/js/bootstrap-editable';
export default class {
constructor() {
$('.translation').editable({
url: this.update,
type: 'text',
mode: 'inline',
send: 'always',
});
}
update(data) {
$.ajax({
url: route('admin.translations.update', this.dataset.key),
type: 'PUT',
data: {
locale: this.dataset.locale,
value: data.value,
},
success(message) {
success(message);
},
error(xhr) {
error(xhr.responseJSON.message);
},
});
}
}

View File

@@ -0,0 +1,10 @@
import TranslationEditor from './TranslationEditor';
$('.translations-table').dataTable({
pageLength: 20,
lengthMenu: [10, 20, 50, 100, 200],
drawCallback: () => {
new TranslationEditor();
},
});

View File

@@ -0,0 +1,6 @@
<?php
return [
'index' => 'Index Translations',
'edit' => 'Edit Translations',
];

View File

@@ -0,0 +1,5 @@
<?php
return [
'translations' => 'Translations',
];

View File

@@ -0,0 +1,9 @@
<?php
return [
'translation' => 'Translation',
'translations' => 'Translations',
'table' => [
'key' => 'Key',
],
];

View File

@@ -0,0 +1,44 @@
@extends('admin::layout')
@section('title', trans('translation::translations.translations'))
@component('admin::components.page.header')
@slot('title', trans('translation::translations.translations'))
<li class="active">{{ trans('translation::translations.translations') }}</li>
@endcomponent
@section('content')
<div class="box box-primary">
<div class="box-body index-table">
<table class="table table-hover translations-table">
<thead>
<tr>
<th>{{ trans('translation::translations.table.key') }}</th>
@foreach (supported_locales() as $locale => $language)
<th>{{ $language['name'] }}</th>
@endforeach
</tr>
</thead>
<tbody>
@foreach ($translations as $key => $translation)
<tr>
<td>{{ $key }}</td>
@foreach (supported_locales() as $locale => $language)
<td class="translation-td">
<a href="#" class="translation editable-click {{ array_has($translation, $locale) ? '' : 'editable-empty' }}"
data-locale="{{ $locale }}"
data-key="{{ $key }}"
>{{ array_get($translation, $locale) }}</a>
</td>
@endforeach
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
@endsection

View File

@@ -0,0 +1,15 @@
<?php
use Illuminate\Support\Facades\Route;
Route::get('translations', [
'uses' => 'TranslationController@index',
'as' => 'admin.translations.index',
'middleware' => 'can:admin.translations.index',
]);
Route::put('translations/{key}', [
'uses' => 'TranslationController@update',
'as' => 'admin.translations.update',
'middleware' => 'can:admin.translations.edit',
]);

View File

@@ -0,0 +1,33 @@
<?php
namespace Modules\Translation\Sidebar;
use Maatwebsite\Sidebar\Item;
use Maatwebsite\Sidebar\Menu;
use Maatwebsite\Sidebar\Group;
use Modules\Admin\Sidebar\BaseSidebarExtender;
class SidebarExtender extends BaseSidebarExtender
{
public function extend(Menu $menu)
{
$menu->group(trans('admin::sidebar.system'), function (Group $group) {
$group->item(trans('admin::sidebar.localization'), function (Item $item) {
$item->weight(10);
$item->icon('fa fa-globe');
$item->route('admin.translations.index');
$item->authorize(
$this->auth->hasAccess('admin.translations.index')
);
$item->item(trans('translation::sidebar.translations'), function (Item $item) {
$item->route('admin.translations.index');
$item->weight(5);
$item->authorize(
$this->auth->hasAccess('admin.translations.index')
);
});
});
});
}
}

View File

@@ -0,0 +1,116 @@
<?php
namespace Modules\Translation;
use Illuminate\Support\Facades\Cache;
use Illuminate\Translation\FileLoader;
use Modules\Translation\Entities\Translation;
class TranslationLoader extends FileLoader
{
/**
* Get translation file paths.
*
* @return array
*/
public function paths()
{
return array_merge([$this->path], $this->hints);
}
/**
* Load the messages for the given locale.
*
* @param string $locale
* @param string $group
* @param string $namespace
* @return array
*/
public function load($locale, $group, $namespace = null)
{
if (! config('app.cache')) {
return $this->getTranslations($locale, $group, $namespace);
}
return Cache::tags('translations')
->rememberForever(md5("translation_loader.{$locale}.{$group}.{$namespace}"), function () use ($locale, $group, $namespace) {
return $this->getTranslations($locale, $group, $namespace);
});
}
/**
* Get file and database translations.
*
* @param string $locale
* @param string $group
* @param string $namespace
* @return array
*/
private function getTranslations($locale, $group, $namespace)
{
$databaseTranslations = [];
if (config('app.installed')) {
$databaseTranslations = $this->databaseTranslations($locale, $group, $namespace);
}
return array_replace_recursive(
$this->fileTranslations($locale, $group, $namespace),
$this->breakDot($databaseTranslations)
);
}
/**
* Break flattened dot translations to an array.
*
* @param array $translations
* @return array
*/
private function breakDot($translations)
{
$array = [];
foreach ($translations as $key => $value) {
if (strpos($key, '*') === false) {
array_set($array, $key, $value);
} else {
$array[$key] = $value;
}
}
return $array;
}
/**
* Get file translations.
*
* @param string $locale
* @param string $group
* @param string $namespace
* @return array
*/
private function fileTranslations($locale, $group, $namespace)
{
return parent::load($locale, $group, $namespace);
}
/**
* Get database translations.
*
* @param string $locale
* @param string $group
* @param string $namespace
* @return array
*/
private function databaseTranslations($locale, $group, $namespace)
{
return Translation::where('key', 'LIKE', "{$namespace}::{$group}.%")
->whereHas('translations', function ($query) use ($locale) {
$query->where('locale', $locale);
})->get()->mapWithKeys(function ($translation) use ($namespace, $group) {
$key = str_replace("{$namespace}::{$group}.", '', $translation->key);
return [$key => $translation->value];
})->all();
}
}

View File

@@ -0,0 +1,28 @@
{
"name": "fleetcart/translation",
"description": "The FleetCart Translation Module.",
"authors": [
{
"name": "Envay Soft",
"email": "envaysoft@gmail.com"
}
],
"require": {
"php": "^8.0.2",
"astrotomic/laravel-translatable": "^11.0"
},
"autoload": {
"psr-4": {
"Modules\\Translation\\": ""
}
},
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"config": {
"sort-packages": true
},
"minimum-stability": "dev"
}

View File

@@ -0,0 +1,9 @@
{
"name": "Translation",
"alias": "translation",
"description": "Module containing all FleetCart translations",
"priority": 1,
"providers": [
"Modules\\Translation\\Providers\\TranslationServiceProvider"
]
}

View File

@@ -0,0 +1,7 @@
{
"name": "translation-module",
"private": true,
"devDependencies": {
"x-editable": "^1.5.1"
}
}

View File

@@ -0,0 +1,11 @@
let mix = require('laravel-mix');
let execSync = require('child_process').execSync;
mix.js(`${__dirname}/Resources/assets/admin/js/main.js`, `${__dirname}/Assets/admin/js/translation.js`)
.styles([
`${__dirname}/node_modules/x-editable/dist/bootstrap3-editable/css/bootstrap-editable.css`,
], `${__dirname}/Assets/admin/css/translation.css`)
.copy(`${__dirname}/node_modules/x-editable/dist/bootstrap3-editable/img`, `${__dirname}/Assets/admin/img`)
.then(() => {
execSync(`npm run rtlcss ${__dirname}/Assets/admin/css/translation.css ${__dirname}/Assets/admin/css/translation.rtl.css`);
});

View File

@@ -0,0 +1,7 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
x-editable@^1.5.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/x-editable/-/x-editable-1.5.1.tgz#2edbb8911ef2c5d61f63f06b0cf020be0fcc5849"