Language editor refactoring part 1 (nackend)

This commit is contained in:
Peter Papp
2021-03-27 18:53:41 +01:00
parent cdb395c77f
commit ec51440c3a
25 changed files with 1833 additions and 1677 deletions

View File

@@ -67,6 +67,7 @@ class SetupDevEnvironment extends Command
$this->store_default_settings();
$this->setup->seed_default_pages();
$this->setup->seed_default_settings('Extended');
$this->setup->seed_default_language();
$this->info('Creating default admin...');
$this->create_admin();

View File

@@ -2,58 +2,50 @@
namespace App\Http\Controllers\Admin;
use App\Setting;
use App\Language;
use App\LanguageString;
use App\Http\Tools\Demo;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use App\Http\Resources\LanguageCollection;
use App\Http\Resources\LanguageResource;
use App\Models\Language;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Cache;
use App\Services\DemoService;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\Routing\ResponseFactory;
use Illuminate\Http\Response;
use App\Http\Requests\Languages\UpdateStringRequest;
use App\Http\Requests\Languages\CreateLanguageRequest;
use App\Http\Requests\Languages\UpdateLanguageRequest;
class LanguageController extends Controller
{
protected $demo;
public function __construct()
{
$this->demo = resolve(DemoService::class);
}
/**
* Get all languages for admin translate
*
* @return Collection
*
* @return array|Application|ResponseFactory|Response
*/
public function get_languages()
{
return [
'languages' => Language::all(),
'set_language' => Setting::whereName('language')->first()->value
];
return response(
new LanguageCollection(Language::all()), 200
);
}
/**
* Get all language strings for admin translate
*
* @param Language $language
* @return Collection
*/
public function get_language_strings(Language $language)
{
$lang = Language::whereId($language->id);
$strings = $lang->with('languageStrings')->first();
// dd($language);
$license = get_setting('license') === 'Extended' ? 'extended' : 'regular';
$default_strings = collect(config('language_strings.' . $license));
return [
'translated_strings' => $strings,
'default_strings' => $default_strings
];
return response([
'current' => $language->languageStrings,
'default' => get_default_language_strings()
], 200);
}
/**
@@ -64,19 +56,18 @@ class LanguageController extends Controller
*/
public function create_language(CreateLanguageRequest $request)
{
// Check if is demo
if (env('APP_DEMO')) {
return Demo::response_204();
if (is_demo()) {
return $this->demo->response_with_no_content();
}
// Create languages & strings
$language = Language::create([
'name' => $request->name,
'locale' => $request->locale
'name' => $request->input('name'),
'locale' => $request->input('locale')
]);
// Return created language
return $language;
return response(
new LanguageResource($language), 201
);
}
/**
@@ -84,20 +75,18 @@ class LanguageController extends Controller
*
* @param UpdateLanguageRequest $request
* @param Language $language
* @return $language
*/
public function update_language(UpdateLanguageRequest $request, Language $language)
{
// Check if is demo
if (env('APP_DEMO')) {
return Demo::response_204();
if (is_demo()) {
return $this->demo->response_with_no_content();
}
// Update language
$language->update(make_single_input($request));
// Return updated language
return $language;
return response(
new LanguageResource($language), 201
);
}
/**
@@ -105,23 +94,22 @@ class LanguageController extends Controller
*
* @param UpdateStringRequest $request
* @param Language $language
* @return ResponseFactory|\Illuminate\Http\Response
* @return Application|ResponseFactory|Response
*/
public function update_string(UpdateStringRequest $request, Language $language)
{
// Check if is demo
if (env('APP_DEMO')) {
return Demo::response_204();
if (is_demo()) {
return $this->demo->response_with_no_content();
}
LanguageString::whereLangAndKey($language->locale, $request->name)
$language
->languageStrings()
->where('key', $request->name)
->update([
'key' => $request->name,
'lang' => $language->locale,
'value' => $request->value
'value' => $request->value
]);
Cache::forget('language_strings-' . $language->locale);
cache()->forget("language-strings-{$language->locale}");
return response('Done', 204);
}
@@ -130,13 +118,16 @@ class LanguageController extends Controller
* Delete the language with all children strings
*
* @param Language $language
* @return ResponseFactory|\Illuminate\Http\Response
* @return ResponseFactory|Response
*/
public function delete_language(Language $language)
{
// Check if is demo
if (env('APP_DEMO')) {
return Demo::response_204();
if (is_demo()) {
return $this->demo->response_with_no_content();
}
if ($language->locale === 'en') {
abort(401, "Sorry, you can't delete default language.");
}
$language->delete();

View File

@@ -447,6 +447,7 @@ class SetupWizardController extends Controller
// Set up application
$this->setup->seed_default_pages();
$this->setup->seed_default_settings($request->license);
$this->setup->seed_default_language();
// Login account
if (Auth::attempt($request->only(['email', 'password']))) {

View File

@@ -182,7 +182,7 @@ class BrowseController extends Controller
return [
[
'name' => __('vuefilemanager.home'),
'name' => __t('home'),
'location' => 'base',
'folders' => $folders,
]

View File

@@ -191,7 +191,7 @@ class BrowseShareController extends Controller
return [
[
'id' => $shared->item_id,
'name' => __('vuefilemanager.home'),
'name' => __t('home'),
'location' => 'public',
'folders' => $folders,
]

View File

@@ -24,7 +24,7 @@ class UpdateLanguageRequest extends FormRequest
public function rules()
{
return [
'name' => 'required|string',
'name' => 'required|string',
'value' => 'required|string'
];
}

View File

@@ -0,0 +1,26 @@
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\ResourceCollection;
class LanguageCollection extends ResourceCollection
{
public $collects = LanguageResource::class;
/**
* Transform the resource collection into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return [
'data' => $this->collection,
'meta' => [
'current_language' => get_setting('language') ?? 'en',
],
];
}
}

View File

@@ -0,0 +1,30 @@
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class LanguageResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return [
'data' => [
'id' => $this->id,
'type' => 'languages',
'attributes' => [
'name' => $this->name,
'locale' => $this->locale,
'updated_at' => $this->updated_at,
'created_at' => $this->created_at,
]
],
];
}
}

View File

@@ -10,6 +10,7 @@ use App\Models\LanguageString;
use ByteUnits\Metric;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Intervention\Image\ImageManagerStatic as Image;
@@ -279,7 +280,7 @@ function is_visitor($shared)
*/
function store_avatar($request, $name)
{
if (! $request->hasFile($name)) {
if (!$request->hasFile($name)) {
return null;
}
@@ -310,7 +311,7 @@ function store_avatar($request, $name)
*/
function store_system_image($request, $name)
{
if (! $request->hasFile($name)) {
if (!$request->hasFile($name)) {
return null;
}
@@ -573,16 +574,28 @@ function get_image_meta_data($file)
try {
// Try to get the exif data
return mb_convert_encoding(Image::make($file->getRealPath())->exif(),'UTF8', 'UTF8');
return mb_convert_encoding(Image::make($file->getRealPath())->exif(), 'UTF8', 'UTF8');
} catch ( \Exception $e) {
return null;
} catch (\Exception $e) {
return null;
}
}
}
/**
* @return Collection
*/
function get_default_language_strings()
{
$license = get_setting('license') ?? 'extended';
return collect(
config('language_strings.' . strtolower($license))
);
}
/**
* Check if app is in dev mode
*
@@ -600,16 +613,16 @@ function is_dev()
function seems_utf8($str)
{
$length = strlen($str);
for ($i=0; $i < $length; $i++) {
for ($i = 0; $i < $length; $i++) {
$c = ord($str[$i]);
if ($c < 0x80) $n = 0; # 0bbbbbbb
elseif (($c & 0xE0) == 0xC0) $n=1; # 110bbbbb
elseif (($c & 0xF0) == 0xE0) $n=2; # 1110bbbb
elseif (($c & 0xF8) == 0xF0) $n=3; # 11110bbb
elseif (($c & 0xFC) == 0xF8) $n=4; # 111110bb
elseif (($c & 0xFE) == 0xFC) $n=5; # 1111110b
elseif (($c & 0xE0) == 0xC0) $n = 1; # 110bbbbb
elseif (($c & 0xF0) == 0xE0) $n = 2; # 1110bbbb
elseif (($c & 0xF8) == 0xF0) $n = 3; # 11110bbb
elseif (($c & 0xFC) == 0xF8) $n = 4; # 111110bb
elseif (($c & 0xFE) == 0xFC) $n = 5; # 1111110b
else return false; # Does not match any model
for ($j=0; $j<$n; $j++) { # n bytes matching 10bbbbbb follow ?
for ($j = 0; $j < $n; $j++) { # n bytes matching 10bbbbbb follow ?
if ((++$i == $length) || ((ord($str[$i]) & 0xC0) != 0x80))
return false;
}
@@ -625,124 +638,125 @@ function seems_utf8($str)
* @param string $string Text that might have accent characters
* @return string Filtered string with replaced "nice" characters.
*/
function remove_accents($string) {
if ( !preg_match('/[\x80-\xff]/', $string) )
function remove_accents($string)
{
if (!preg_match('/[\x80-\xff]/', $string))
return $string;
if (seems_utf8($string)) {
$chars = array(
// Decompositions for Latin-1 Supplement
chr(195).chr(128) => 'A', chr(195).chr(129) => 'A',
chr(195).chr(130) => 'A', chr(195).chr(131) => 'A',
chr(195).chr(132) => 'A', chr(195).chr(133) => 'A',
chr(195).chr(135) => 'C', chr(195).chr(136) => 'E',
chr(195).chr(137) => 'E', chr(195).chr(138) => 'E',
chr(195).chr(139) => 'E', chr(195).chr(140) => 'I',
chr(195).chr(141) => 'I', chr(195).chr(142) => 'I',
chr(195).chr(143) => 'I', chr(195).chr(145) => 'N',
chr(195).chr(146) => 'O', chr(195).chr(147) => 'O',
chr(195).chr(148) => 'O', chr(195).chr(149) => 'O',
chr(195).chr(150) => 'O', chr(195).chr(153) => 'U',
chr(195).chr(154) => 'U', chr(195).chr(155) => 'U',
chr(195).chr(156) => 'U', chr(195).chr(157) => 'Y',
chr(195).chr(159) => 's', chr(195).chr(160) => 'a',
chr(195).chr(161) => 'a', chr(195).chr(162) => 'a',
chr(195).chr(163) => 'a', chr(195).chr(164) => 'a',
chr(195).chr(165) => 'a', chr(195).chr(167) => 'c',
chr(195).chr(168) => 'e', chr(195).chr(169) => 'e',
chr(195).chr(170) => 'e', chr(195).chr(171) => 'e',
chr(195).chr(172) => 'i', chr(195).chr(173) => 'i',
chr(195).chr(174) => 'i', chr(195).chr(175) => 'i',
chr(195).chr(177) => 'n', chr(195).chr(178) => 'o',
chr(195).chr(179) => 'o', chr(195).chr(180) => 'o',
chr(195).chr(181) => 'o', chr(195).chr(182) => 'o',
chr(195).chr(182) => 'o', chr(195).chr(185) => 'u',
chr(195).chr(186) => 'u', chr(195).chr(187) => 'u',
chr(195).chr(188) => 'u', chr(195).chr(189) => 'y',
chr(195).chr(191) => 'y',
chr(195) . chr(128) => 'A', chr(195) . chr(129) => 'A',
chr(195) . chr(130) => 'A', chr(195) . chr(131) => 'A',
chr(195) . chr(132) => 'A', chr(195) . chr(133) => 'A',
chr(195) . chr(135) => 'C', chr(195) . chr(136) => 'E',
chr(195) . chr(137) => 'E', chr(195) . chr(138) => 'E',
chr(195) . chr(139) => 'E', chr(195) . chr(140) => 'I',
chr(195) . chr(141) => 'I', chr(195) . chr(142) => 'I',
chr(195) . chr(143) => 'I', chr(195) . chr(145) => 'N',
chr(195) . chr(146) => 'O', chr(195) . chr(147) => 'O',
chr(195) . chr(148) => 'O', chr(195) . chr(149) => 'O',
chr(195) . chr(150) => 'O', chr(195) . chr(153) => 'U',
chr(195) . chr(154) => 'U', chr(195) . chr(155) => 'U',
chr(195) . chr(156) => 'U', chr(195) . chr(157) => 'Y',
chr(195) . chr(159) => 's', chr(195) . chr(160) => 'a',
chr(195) . chr(161) => 'a', chr(195) . chr(162) => 'a',
chr(195) . chr(163) => 'a', chr(195) . chr(164) => 'a',
chr(195) . chr(165) => 'a', chr(195) . chr(167) => 'c',
chr(195) . chr(168) => 'e', chr(195) . chr(169) => 'e',
chr(195) . chr(170) => 'e', chr(195) . chr(171) => 'e',
chr(195) . chr(172) => 'i', chr(195) . chr(173) => 'i',
chr(195) . chr(174) => 'i', chr(195) . chr(175) => 'i',
chr(195) . chr(177) => 'n', chr(195) . chr(178) => 'o',
chr(195) . chr(179) => 'o', chr(195) . chr(180) => 'o',
chr(195) . chr(181) => 'o', chr(195) . chr(182) => 'o',
chr(195) . chr(182) => 'o', chr(195) . chr(185) => 'u',
chr(195) . chr(186) => 'u', chr(195) . chr(187) => 'u',
chr(195) . chr(188) => 'u', chr(195) . chr(189) => 'y',
chr(195) . chr(191) => 'y',
// Decompositions for Latin Extended-A
chr(196).chr(128) => 'A', chr(196).chr(129) => 'a',
chr(196).chr(130) => 'A', chr(196).chr(131) => 'a',
chr(196).chr(132) => 'A', chr(196).chr(133) => 'a',
chr(196).chr(134) => 'C', chr(196).chr(135) => 'c',
chr(196).chr(136) => 'C', chr(196).chr(137) => 'c',
chr(196).chr(138) => 'C', chr(196).chr(139) => 'c',
chr(196).chr(140) => 'C', chr(196).chr(141) => 'c',
chr(196).chr(142) => 'D', chr(196).chr(143) => 'd',
chr(196).chr(144) => 'D', chr(196).chr(145) => 'd',
chr(196).chr(146) => 'E', chr(196).chr(147) => 'e',
chr(196).chr(148) => 'E', chr(196).chr(149) => 'e',
chr(196).chr(150) => 'E', chr(196).chr(151) => 'e',
chr(196).chr(152) => 'E', chr(196).chr(153) => 'e',
chr(196).chr(154) => 'E', chr(196).chr(155) => 'e',
chr(196).chr(156) => 'G', chr(196).chr(157) => 'g',
chr(196).chr(158) => 'G', chr(196).chr(159) => 'g',
chr(196).chr(160) => 'G', chr(196).chr(161) => 'g',
chr(196).chr(162) => 'G', chr(196).chr(163) => 'g',
chr(196).chr(164) => 'H', chr(196).chr(165) => 'h',
chr(196).chr(166) => 'H', chr(196).chr(167) => 'h',
chr(196).chr(168) => 'I', chr(196).chr(169) => 'i',
chr(196).chr(170) => 'I', chr(196).chr(171) => 'i',
chr(196).chr(172) => 'I', chr(196).chr(173) => 'i',
chr(196).chr(174) => 'I', chr(196).chr(175) => 'i',
chr(196).chr(176) => 'I', chr(196).chr(177) => 'i',
chr(196).chr(178) => 'IJ',chr(196).chr(179) => 'ij',
chr(196).chr(180) => 'J', chr(196).chr(181) => 'j',
chr(196).chr(182) => 'K', chr(196).chr(183) => 'k',
chr(196).chr(184) => 'k', chr(196).chr(185) => 'L',
chr(196).chr(186) => 'l', chr(196).chr(187) => 'L',
chr(196).chr(188) => 'l', chr(196).chr(189) => 'L',
chr(196).chr(190) => 'l', chr(196).chr(191) => 'L',
chr(197).chr(128) => 'l', chr(197).chr(129) => 'L',
chr(197).chr(130) => 'l', chr(197).chr(131) => 'N',
chr(197).chr(132) => 'n', chr(197).chr(133) => 'N',
chr(197).chr(134) => 'n', chr(197).chr(135) => 'N',
chr(197).chr(136) => 'n', chr(197).chr(137) => 'N',
chr(197).chr(138) => 'n', chr(197).chr(139) => 'N',
chr(197).chr(140) => 'O', chr(197).chr(141) => 'o',
chr(197).chr(142) => 'O', chr(197).chr(143) => 'o',
chr(197).chr(144) => 'O', chr(197).chr(145) => 'o',
chr(197).chr(146) => 'OE',chr(197).chr(147) => 'oe',
chr(197).chr(148) => 'R',chr(197).chr(149) => 'r',
chr(197).chr(150) => 'R',chr(197).chr(151) => 'r',
chr(197).chr(152) => 'R',chr(197).chr(153) => 'r',
chr(197).chr(154) => 'S',chr(197).chr(155) => 's',
chr(197).chr(156) => 'S',chr(197).chr(157) => 's',
chr(197).chr(158) => 'S',chr(197).chr(159) => 's',
chr(197).chr(160) => 'S', chr(197).chr(161) => 's',
chr(197).chr(162) => 'T', chr(197).chr(163) => 't',
chr(197).chr(164) => 'T', chr(197).chr(165) => 't',
chr(197).chr(166) => 'T', chr(197).chr(167) => 't',
chr(197).chr(168) => 'U', chr(197).chr(169) => 'u',
chr(197).chr(170) => 'U', chr(197).chr(171) => 'u',
chr(197).chr(172) => 'U', chr(197).chr(173) => 'u',
chr(197).chr(174) => 'U', chr(197).chr(175) => 'u',
chr(197).chr(176) => 'U', chr(197).chr(177) => 'u',
chr(197).chr(178) => 'U', chr(197).chr(179) => 'u',
chr(197).chr(180) => 'W', chr(197).chr(181) => 'w',
chr(197).chr(182) => 'Y', chr(197).chr(183) => 'y',
chr(197).chr(184) => 'Y', chr(197).chr(185) => 'Z',
chr(197).chr(186) => 'z', chr(197).chr(187) => 'Z',
chr(197).chr(188) => 'z', chr(197).chr(189) => 'Z',
chr(197).chr(190) => 'z', chr(197).chr(191) => 's',
chr(196) . chr(128) => 'A', chr(196) . chr(129) => 'a',
chr(196) . chr(130) => 'A', chr(196) . chr(131) => 'a',
chr(196) . chr(132) => 'A', chr(196) . chr(133) => 'a',
chr(196) . chr(134) => 'C', chr(196) . chr(135) => 'c',
chr(196) . chr(136) => 'C', chr(196) . chr(137) => 'c',
chr(196) . chr(138) => 'C', chr(196) . chr(139) => 'c',
chr(196) . chr(140) => 'C', chr(196) . chr(141) => 'c',
chr(196) . chr(142) => 'D', chr(196) . chr(143) => 'd',
chr(196) . chr(144) => 'D', chr(196) . chr(145) => 'd',
chr(196) . chr(146) => 'E', chr(196) . chr(147) => 'e',
chr(196) . chr(148) => 'E', chr(196) . chr(149) => 'e',
chr(196) . chr(150) => 'E', chr(196) . chr(151) => 'e',
chr(196) . chr(152) => 'E', chr(196) . chr(153) => 'e',
chr(196) . chr(154) => 'E', chr(196) . chr(155) => 'e',
chr(196) . chr(156) => 'G', chr(196) . chr(157) => 'g',
chr(196) . chr(158) => 'G', chr(196) . chr(159) => 'g',
chr(196) . chr(160) => 'G', chr(196) . chr(161) => 'g',
chr(196) . chr(162) => 'G', chr(196) . chr(163) => 'g',
chr(196) . chr(164) => 'H', chr(196) . chr(165) => 'h',
chr(196) . chr(166) => 'H', chr(196) . chr(167) => 'h',
chr(196) . chr(168) => 'I', chr(196) . chr(169) => 'i',
chr(196) . chr(170) => 'I', chr(196) . chr(171) => 'i',
chr(196) . chr(172) => 'I', chr(196) . chr(173) => 'i',
chr(196) . chr(174) => 'I', chr(196) . chr(175) => 'i',
chr(196) . chr(176) => 'I', chr(196) . chr(177) => 'i',
chr(196) . chr(178) => 'IJ', chr(196) . chr(179) => 'ij',
chr(196) . chr(180) => 'J', chr(196) . chr(181) => 'j',
chr(196) . chr(182) => 'K', chr(196) . chr(183) => 'k',
chr(196) . chr(184) => 'k', chr(196) . chr(185) => 'L',
chr(196) . chr(186) => 'l', chr(196) . chr(187) => 'L',
chr(196) . chr(188) => 'l', chr(196) . chr(189) => 'L',
chr(196) . chr(190) => 'l', chr(196) . chr(191) => 'L',
chr(197) . chr(128) => 'l', chr(197) . chr(129) => 'L',
chr(197) . chr(130) => 'l', chr(197) . chr(131) => 'N',
chr(197) . chr(132) => 'n', chr(197) . chr(133) => 'N',
chr(197) . chr(134) => 'n', chr(197) . chr(135) => 'N',
chr(197) . chr(136) => 'n', chr(197) . chr(137) => 'N',
chr(197) . chr(138) => 'n', chr(197) . chr(139) => 'N',
chr(197) . chr(140) => 'O', chr(197) . chr(141) => 'o',
chr(197) . chr(142) => 'O', chr(197) . chr(143) => 'o',
chr(197) . chr(144) => 'O', chr(197) . chr(145) => 'o',
chr(197) . chr(146) => 'OE', chr(197) . chr(147) => 'oe',
chr(197) . chr(148) => 'R', chr(197) . chr(149) => 'r',
chr(197) . chr(150) => 'R', chr(197) . chr(151) => 'r',
chr(197) . chr(152) => 'R', chr(197) . chr(153) => 'r',
chr(197) . chr(154) => 'S', chr(197) . chr(155) => 's',
chr(197) . chr(156) => 'S', chr(197) . chr(157) => 's',
chr(197) . chr(158) => 'S', chr(197) . chr(159) => 's',
chr(197) . chr(160) => 'S', chr(197) . chr(161) => 's',
chr(197) . chr(162) => 'T', chr(197) . chr(163) => 't',
chr(197) . chr(164) => 'T', chr(197) . chr(165) => 't',
chr(197) . chr(166) => 'T', chr(197) . chr(167) => 't',
chr(197) . chr(168) => 'U', chr(197) . chr(169) => 'u',
chr(197) . chr(170) => 'U', chr(197) . chr(171) => 'u',
chr(197) . chr(172) => 'U', chr(197) . chr(173) => 'u',
chr(197) . chr(174) => 'U', chr(197) . chr(175) => 'u',
chr(197) . chr(176) => 'U', chr(197) . chr(177) => 'u',
chr(197) . chr(178) => 'U', chr(197) . chr(179) => 'u',
chr(197) . chr(180) => 'W', chr(197) . chr(181) => 'w',
chr(197) . chr(182) => 'Y', chr(197) . chr(183) => 'y',
chr(197) . chr(184) => 'Y', chr(197) . chr(185) => 'Z',
chr(197) . chr(186) => 'z', chr(197) . chr(187) => 'Z',
chr(197) . chr(188) => 'z', chr(197) . chr(189) => 'Z',
chr(197) . chr(190) => 'z', chr(197) . chr(191) => 's',
// Euro Sign
chr(226).chr(130).chr(172) => 'E',
chr(226) . chr(130) . chr(172) => 'E',
// GBP (Pound) Sign
chr(194).chr(163) => '');
chr(194) . chr(163) => '');
$string = strtr($string, $chars);
} else {
// Assume ISO-8859-1 if not UTF-8
$chars['in'] = chr(128).chr(131).chr(138).chr(142).chr(154).chr(158)
.chr(159).chr(162).chr(165).chr(181).chr(192).chr(193).chr(194)
.chr(195).chr(196).chr(197).chr(199).chr(200).chr(201).chr(202)
.chr(203).chr(204).chr(205).chr(206).chr(207).chr(209).chr(210)
.chr(211).chr(212).chr(213).chr(214).chr(216).chr(217).chr(218)
.chr(219).chr(220).chr(221).chr(224).chr(225).chr(226).chr(227)
.chr(228).chr(229).chr(231).chr(232).chr(233).chr(234).chr(235)
.chr(236).chr(237).chr(238).chr(239).chr(241).chr(242).chr(243)
.chr(244).chr(245).chr(246).chr(248).chr(249).chr(250).chr(251)
.chr(252).chr(253).chr(255);
$chars['in'] = chr(128) . chr(131) . chr(138) . chr(142) . chr(154) . chr(158)
. chr(159) . chr(162) . chr(165) . chr(181) . chr(192) . chr(193) . chr(194)
. chr(195) . chr(196) . chr(197) . chr(199) . chr(200) . chr(201) . chr(202)
. chr(203) . chr(204) . chr(205) . chr(206) . chr(207) . chr(209) . chr(210)
. chr(211) . chr(212) . chr(213) . chr(214) . chr(216) . chr(217) . chr(218)
. chr(219) . chr(220) . chr(221) . chr(224) . chr(225) . chr(226) . chr(227)
. chr(228) . chr(229) . chr(231) . chr(232) . chr(233) . chr(234) . chr(235)
. chr(236) . chr(237) . chr(238) . chr(239) . chr(241) . chr(242) . chr(243)
. chr(244) . chr(245) . chr(246) . chr(248) . chr(249) . chr(250) . chr(251)
. chr(252) . chr(253) . chr(255);
$chars['out'] = "EfSZszYcYuAAAAAACEEEEIIIINOOOOOOUUUUYaaaaaaceeeeiiiinoooooouuuuyy";
@@ -754,6 +768,7 @@ function remove_accents($string) {
return $string;
}
/**
* Get all files from folder and get their folder location in VueFileManager directories
*
@@ -793,16 +808,16 @@ function get_files_for_zip($folders, $files, $path = [])
}
/**
* Set time by user timezone GMT
* Set time by user timezone GMT
*
* @param $time
* @return int
* @return Carbon
*/
function set_time_by_user_timezone($time)
{
$user = Auth::user();
if($user) {
if ($user) {
// Get the value of timezone if user have some
$time_zone = intval($user->settings->timezone * 60 ?? null);
@@ -811,56 +826,55 @@ function set_time_by_user_timezone($time)
}
return Carbon::parse($time);
}
/**
* Translate the given message.
*
* @param $key
* @param null $values
* @return string|string[]
*/
function __t($key, $values = null)
{
// Check if is in cache save default_language
if (Cache::has('default_language')) {
// Get current locale
$locale = cache()->rememberForever('language', function () {
return get_setting('language') ?? 'en';
});
$locale = Cache::get('default_language');
} else {
$strings = cache()->rememberForever("language-strings-$locale", function () use ($locale) {
return Language::whereLocale($locale)->first()->languageStrings ?? get_default_language_strings();
});
$locale = Cache::rememberForever('default_language', function () {
return get_setting('language');
});
}
// Find the string by key
$string = $strings->get($key)
? $strings->get($key)
: $strings->firstWhere('key', $key)->value;
// Check if cash has string
if (Cache::has('language_strings-' . $locale)) {
$strings = Cache::get('language_strings-' . $locale)
->languageStrings;
// Find the string by key
$string = $strings->firstWhere('key', $key)->value;
}
// If cash dont have string return string from database
$string = LanguageString::whereLangAndKey($locale, $key)
->first()
->value;
if($values) {
return adjust_value($string, $values);
if ($values) {
return replace_occurrence($string, collect($values));
}
return $string;
}
function adjust_value($string, $values)
/**
* Replace string occurrence in __t() by their values
*
* @param $string
* @param $values
* @return string|string[]
*/
function replace_occurrence($string, $values)
{
$search = [];
$replace = [];
if($values) {
foreach($values as $key => $variable) {
array_push($search, ':' . $key);
array_push($replace, $variable);
}
}
return str_ireplace($search, $replace, $string);
$occurrences = $values->map(function ($message, $key) {
return [
'key' => ":$key",
'message' => $message,
];
});
return str_ireplace(
$occurrences->pluck('key')->toArray(), $occurrences->pluck('message')->toArray(), $string
);
}

View File

@@ -2,24 +2,27 @@
namespace App\Models;
use App\Models\LanguageString;
use App\Services\HelperService;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Cache;
use Illuminate\Database\Eloquent\Model;
class Language extends Model
{
protected $guarded = ['id'];
protected $guarded = [
'id'
];
protected $keyType = 'string';
protected $primaryKey = 'id';
public $incrementing = false ;
public $incrementing = false;
public $timestamps = false;
public function languageStrings()
{
return $this->hasMany(LanguageString::class, 'lang', 'locale');
}
protected static function boot()
{
@@ -27,45 +30,23 @@ class Language extends Model
static::creating(function ($language) {
$language->id = Str::uuid();
resolve(HelperService::class)
->create_default_language_strings(
get_setting('license') ?? 'extended', $language->locale
);
});
static::updating(function ($language) {
cache()->forget("language-strings-$language->locale");
});
static::deleting(function ($language) {
DB::table('language_strings')
->where('lang', $language->locale)
->whereLang($language->locale)
->delete();
Cache::forget('language_strings-' . $language->locale );
cache()->forget("language-strings-$language->locale");
});
static::updated(function($language) {
Cache::forget('language_strings-' . $language->locale );
});
static::created(function ($language) {
$license = get_setting('license') === 'Extended' ? 'extended' : 'regular';
$language_strings = collect(config('language_strings.' . $license));
$strings = $language_strings->map(function ($value , $key) use($language) {
return [
'key' => $key,
'lang' => $language->locale,
'value' => $value
];
})->toArray();
DB::table('language_strings')
->insert($strings);
});
}
public function languageStrings()
{
return $this->hasMany('App\LanguageString', 'lang', 'locale');
}
}

View File

@@ -2,7 +2,6 @@
namespace App\Models;
use Illuminate\Support\Facades\Cache;
use Illuminate\Database\Eloquent\Model;
class LanguageString extends Model
@@ -13,16 +12,7 @@ class LanguageString extends Model
public $incrementing = false;
protected $fillable = ['value' ,'key', 'lang'];
protected static function boot()
{
parent::boot();
static::updated(function() {
dd('test');
// Cache::forget('language_strings');
});
}
protected $fillable = [
'value'
];
}

View File

@@ -43,7 +43,7 @@ class SharedSendViaEmail extends Notification
public function toMail($notifiable)
{
return (new MailMessage)
->subject(__t('shared_link_email_subject' , ['user' => $this->user->name]))
->subject(__t('shared_link_email_subject', ['user' => $this->user->name]))
->greeting(__t('shared_link_email_greeting'))
->line(__t('shared_link_email_user', ['user' => $this->user->name, 'email' => $this->user->email]))
->action(__t('shared_link_email_link'), url('/shared', ['token' => $this->token]))

View File

@@ -59,15 +59,15 @@ class HelperService
$accessible_folder_ids = Arr::flatten([filter_folders_ids($foldersIds), $shared->item_id]);
// Check user access
if ( is_array($requested_id) ) {
if (is_array($requested_id)) {
foreach ($requested_id as $id) {
if (!in_array($id, $accessible_folder_ids))
abort(403);
}
}
if (! is_array($requested_id)) {
if (! in_array($requested_id, $accessible_folder_ids))
if (!is_array($requested_id)) {
if (!in_array($requested_id, $accessible_folder_ids))
abort(403);
}
}
@@ -323,4 +323,23 @@ class HelperService
}
}
}
/**
* @param $license
* @param $locale
*/
function create_default_language_strings($license, $locale)
{
$strings = collect(config('language_strings.' . strtolower($license)))
->map(function ($value, $key) use ($locale) {
return [
'lang' => $locale,
'value' => $value,
'key' => $key,
];
})->toArray();
DB::table('language_strings')->insert($strings);
}
}

View File

@@ -2,9 +2,12 @@
namespace App\Services;
use App\Models\Language;
use App\Models\Page;
use App\Models\Setting;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Symfony\Component\Console\Helper\Helper;
class SetupService
{
@@ -48,4 +51,22 @@ class SetupService
Setting::forceCreate($content);
});
}
/**
* Store default VueFileManager settings into database
*
* @param $license
*/
public function seed_default_language()
{
Language::create([
'name' => 'English',
'locale' => 'en'
]);
Setting::create([
'name' => 'language',
'value' => 'en',
]);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -14,9 +14,10 @@ class CreateLanguagesTable extends Migration
public function up()
{
Schema::create('languages', function (Blueprint $table) {
$table->uuid('id')->primary();
$table->uuid('id')->primary()->index();
$table->string('name');
$table->string('locale')->unique();
$table->timestamps();
});
}

View File

@@ -1,66 +0,0 @@
<?php
return [
'app_description' => '利用 VueFileManager 创建您自己的私有云,由 Laravel and Vue 驱动',
'user_not_fount' => '我们没有找到此邮箱对应的用户信息。',
'incorrect_password' => '不好意思,您的密码好像不正确。',
'time' => '%d. %B. %Y 于 %H:%M',
'home' => '首页',
//Shared link email message
'shared_link_email_subject' => '🙋 :user share some files with you. Look at it!',
'shared_link_email_greeting' => 'Hello!',
'shared_link_email_user' => ':user (:email) send you a link to shared files.',
'shared_link_email_link' => 'Open your files',
'shared_link_email_salutation' => 'Regards, :app_name',
// Reset password email
'reset_password_greeting' => 'Hello!',
'reset_password_subject' => 'Reset password for your account on ',
'reset_password_line_1' => 'You are receiving this email because we received a password reset request for your account.',
'reset_password_line_2' => 'If you did not request a password reset, no further action is required.',
'reset_password_action' => 'Reset Password',
'salutation' => 'Regards',
// Invoice
'print_button' => 'Print Document',
'vat' => 'VAT',
'vat_included' => 'incl.',
'subtotal' => 'Subtotal',
'tax_exempted' => 'Tax is exempted',
'tax_be_paid_reverse' => 'Tax to be paid on reverse charge basis',
'invoice_title' => 'Invoice',
'date' => 'Date',
'product' => 'Product',
'subscription' => 'Subscription',
'invoice_number' => 'Invoice Number',
'seller' => 'Seller',
'client' => 'Client',
'seller_vat' => 'VAT number',
'seller_name' => 'Name',
'seller_phone' => 'Phone',
'name' => 'Name',
'phone' => 'Phone',
'address' => 'Address',
'city' => 'City',
'state' => 'State',
'postal_code' => 'Postal code',
'country' => 'Country',
'col_description' => 'Description',
'col_date' => 'Date',
'col_amount' => 'Amount',
'total' => 'Total',
// OG Page
'user_sending' => ':name is sending you this file',
'protected_file' => 'This link is protected by password',
];

View File

@@ -1,66 +0,0 @@
<?php
// return [
// 'app_description' => __t('app_description'),
// 'user_not_fount' => __t('user_not_fount'),
// 'incorrect_password' => __t('incorrect_password'),
// 'time' => __t('time'),
// 'home' => __t('home'),
// //Shared link email message
// 'shared_link_email_subject' => __t('shared_link_email_subject'),
// 'shared_link_email_greeting' => __t('shared_link_email_greeting'),
// 'shared_link_email_user' => __t('shared_link_email_user'),
// 'shared_link_email_link' => __t('shared_link_email_link'),
// 'shared_link_email_salutation' => __t('shared_link_email_salutation'),
// // Reset password email
// 'reset_password_greeting' => __t('reset_password_greeting'),
// 'reset_password_subject' => __t('reset_password_subject'),
// 'reset_password_line_1' => __t('reset_password_line_1'),
// 'reset_password_line_2' => __t('reset_password_line_2'),
// 'reset_password_action' => __t('reset_password_action'),
// 'salutation' => __t('salutation'),
// Invoice
// 'print_button' => __t('print_button'),
// 'vat' => __t('vat'),
// 'vat_included' => __t('vat_included'),
// 'subtotal' => __t('subtotal'),
// 'tax_exempted' => __t('tax_exempted'),
// 'tax_be_paid_reverse' => __t('tax_be_paid_reverse'),
// 'invoice_title' => __t('invoice_title'),
// 'date' => __t('date'),
// 'product' => __t('product'),
// 'subscription' => __t('subscription'),
// 'invoice_number' => __t('invoice_number'),
// 'seller' => __t('seller'),
// 'client' => __t('client'),
// 'seller_vat' => __t('seller_vat'),
// 'seller_name' => __t('seller_name'),
// 'seller_phone' => __t('seller_phone'),
// 'name' => __t('name'),
// 'phone' => __t('phone'),
// 'address' => __t('address'),
// 'city' => __t('city'),
// 'state' => __t('state'),
// 'postal_code' => __t('postal_code'),
// 'country' => __t('country'),
// 'col_description' => __t('col_description'),
// 'col_date' => __t('col_date'),
// 'col_amount' => __t('col_amount'),
// 'total' => __t('total'),
// OG Page
// 'user_sending' => __t('user_sending'),
// 'protected_file' => __t('protected_file'),
// ];

View File

@@ -1,66 +0,0 @@
<?php
return [
'app_description' => 'Vytvor si svoj vlastný privátny cloud s VueFileManager klientom poháňaným Laravelom a Vue',
'user_not_fount' => 'Uživateľ s touto emailovou adresou sa nenašiel.',
'incorrect_password' => 'Prepáč, zadané heslo je nesprávne',
'time' => '%d. %B. %Y o %H:%M',
'home' => 'Domov',
//Shared link email message
'shared_link_email_subject' => '🙋 :user vám posiela zdieľané súbory.',
'shared_link_email_greeting' => 'Ahoj!',
'shared_link_email_user' => ':user (:email) vám posiela odkaz pre zdieľané súbory.',
'shared_link_email_link' => 'Vaše súbory',
'shared_link_email_salutation' => 'S pozdravom, :app_name',
// Reset password email
'reset_password_greeting' => 'Ahoj!',
'reset_password_subject' => 'Resetujte svoje heslo v aplikácií ',
'reset_password_line_1' => 'Tento email ste dostali pretože ste nás požiadali o zmenu hesla pre Váš účet.',
'reset_password_line_2' => 'Pokiaľ ste si nechceli zmeniť heslo, žiadna akcia nie je vyžadovaná.',
'reset_password_action' => 'Resetovať heslo',
'salutation' => 'S pozdravom ',
// Invoice
'print_button' => 'Vytlačiť dokument',
'vat' => 'Daň',
'vat_included' => 'zah.',
'subtotal' => 'Medzisúčet',
'tax_exempted' => 'Daň je oslobodená',
'tax_be_paid_reverse' => 'Daň, ktorá sa má zaplatiť na základe prenesenia daňovej povinnosti',
'invoice_title' => 'Faktúra',
'date' => 'Dátum',
'product' => 'Produkt',
'subscription' => 'Predplatné',
'invoice_number' => 'Číslo faktúry',
'seller' => 'Predajca',
'client' => 'Klient',
'seller_vat' => 'IČ DPH',
'seller_name' => 'Meno',
'seller_phone' => 'Telefónne číslo',
'name' => 'Meno',
'phone' => 'Telefónne číslo',
'address' => 'Adresa',
'city' => 'Mesto',
'state' => 'Štát',
'postal_code' => 'PSČ',
'country' => 'Krajina',
'col_description' => 'Popis',
'col_date' => 'Dátum',
'col_amount' => 'Čiastka',
'total' => 'Spolu',
// OG Page
'user_sending' => ':name ti posiela súbor.',
'protected_file' => 'Tento link je chránený heslom',
];

View File

@@ -41,7 +41,7 @@
host: '{{ url('/') }}',
api: '{{ url('/api') }}',
locale: '{{ \Illuminate\Support\Facades\App::getLocale() }}',
language: '{{ isset($settings->language) ? $settings->language : en }}',
language: {{ $settings->language ?? 'en' }},
app_color: '{{ $settings->app_color ?? '#00BC7E' }}',
app_logo: '{{ $settings->app_logo ?? null }}',

View File

@@ -2,6 +2,7 @@
use App\Http\Controllers\Admin\DashboardController;
use App\Http\Controllers\Admin\InvoiceController;
use App\Http\Controllers\Admin\LanguageController;
use App\Http\Controllers\Admin\PagesController;
use App\Http\Controllers\Admin\PlanController;
use App\Http\Controllers\Admin\UserController;
@@ -59,10 +60,10 @@ Route::group(['prefix' => 'settings'], function () {
// Language
Route::group(['prefix' => 'languages'], function () {
Route::get('/{language}/strings', 'Admin\LanguageController@get_language_strings');
Route::patch('/{language}/string', 'Admin\LanguageController@update_string');
Route::delete('/{language}', 'Admin\LanguageController@delete_language');
Route::patch('/{language}', 'Admin\LanguageController@update_language');
Route::post('/', 'Admin\LanguageController@create_language');
Route::get('/', 'Admin\LanguageController@get_languages');
Route::get('/{language}/strings', [LanguageController::class, 'get_language_strings']);
Route::patch('/{language}/strings', [LanguageController::class, 'update_string']);
Route::delete('/{language}', [LanguageController::class, 'delete_language']);
Route::patch('/{language}', [LanguageController::class, 'update_language']);
Route::post('/', [LanguageController::class, 'create_language']);
Route::get('/', [LanguageController::class, 'get_languages']);
});

View File

@@ -1,6 +1,6 @@
<?php
namespace Tests\Feature\Accounts;
namespace Tests\Feature\Admin;
use App\Models\File;
use App\Models\Folder;

View File

@@ -0,0 +1,238 @@
<?php
namespace Tests\Feature\Admin;
use App\Models\Language;
use App\Models\Setting;
use App\Models\User;
use App\Services\SetupService;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Laravel\Sanctum\Sanctum;
use Tests\TestCase;
class LanguageEditorTest extends TestCase
{
use DatabaseMigrations;
protected $setup;
public function __construct()
{
parent::__construct();
$this->setup = app()->make(SetupService::class);
}
/**
* @test
*/
public function it_create_language()
{
Setting::create([
'name' => 'license',
'value' => 'Extended',
]);
$admin = User::factory(User::class)
->create(['role' => 'admin']);
Sanctum::actingAs($admin);
$this->postJson('/api/admin/languages', [
'name' => 'Slovenčina',
'locale' => 'sk',
])
->assertStatus(201)
->assertJsonFragment([
'name' => 'Slovenčina',
'locale' => 'sk',
]);
$this->assertDatabaseHas('languages', [
'name' => 'Slovenčina',
'locale' => 'sk',
]);
$this->assertDatabaseHas('language_strings', [
'key' => 'actions.close',
'value' => 'Close',
'lang' => 'sk',
]);
}
/**
* @test
*/
public function it_update_language()
{
$this->setup->seed_default_language();
$admin = User::factory(User::class)
->create(['role' => 'admin']);
Sanctum::actingAs($admin);
$language = Language::first();
$this->patchJson("/api/admin/languages/$language->id", [
'name' => 'name',
'value' => 'Slovenčina',
])
->assertStatus(201)
->assertJsonFragment([
'name' => 'Slovenčina',
]);
$this->assertDatabaseHas('languages', [
'name' => 'Slovenčina',
'locale' => 'en',
]);
}
/**
* @test
*/
public function it_delete_language()
{
$language = Language::create([
'name' => 'Slovenčina',
'locale' => 'sk'
]);
$admin = User::factory(User::class)
->create(['role' => 'admin']);
Sanctum::actingAs($admin);
$this->deleteJson("/api/admin/languages/$language->id")
->assertStatus(204);
$this->assertDatabaseMissing('languages', [
'name' => 'Slovenčina',
'locale' => 'sk',
]);
$this->assertDatabaseMissing('language_strings', [
'key' => 'actions.close',
'value' => 'Close',
'lang' => 'sk',
]);
}
/**
* @test
*/
public function it_try_to_delete_default_language()
{
$this->setup->seed_default_language();
$admin = User::factory(User::class)
->create(['role' => 'admin']);
Sanctum::actingAs($admin);
$language = Language::first();
$this->deleteJson("/api/admin/languages/$language->id")
->assertStatus(401);
}
/**
* @test
*/
public function it_get_all_languages()
{
$this->setup->seed_default_language();
$admin = User::factory(User::class)
->create(['role' => 'admin']);
Sanctum::actingAs($admin);
$this->getJson('/api/admin/languages')
->assertStatus(200)
->assertJsonFragment([
"name" => "English",
"current_language" => "en",
]);
}
/**
* @test
*/
public function it_update_language_string()
{
$this->setup->seed_default_language();
$admin = User::factory(User::class)
->create(['role' => 'admin']);
Sanctum::actingAs($admin);
$language = Language::first();
$this->patchJson("/api/admin/languages/$language->id/strings", [
'name' => 'actions.close',
'value' => 'Close It, now!',
]);
$this->assertDatabaseHas('language_strings', [
'key' => 'actions.close',
'value' => 'Close It, now!',
'lang' => 'en',
]);
}
/**
* @test
*/
public function it_get_language_strings_by_selected_language_id()
{
$this->setup->seed_default_language();
$admin = User::factory(User::class)
->create(['role' => 'admin']);
Sanctum::actingAs($admin);
$language = Language::first();
$this->getJson("/api/admin/languages/$language->id/strings")
->assertStatus(200)
->assertJsonFragment([
"key" => "actions.close",
"value" => "Close",
"lang" => "en",
]);
}
/**
* @test
*/
public function it_get_translated_string_from_t_helper_function()
{
$this->setup->seed_default_language();
Language::first()
->languageStrings()
->forceCreate([
"key" => "test",
"value" => "Hi, my name is :name :surname",
"lang" => "en",
]);
$this->assertEquals(
__t('actions.close'),
'Close'
);
$this->assertEquals(
__t('shared_link_email_subject', ['user' => 'John']),
'🙋 John share some files with you. Look at it!'
);
$this->assertEquals(
__t('test', ['name' => 'John', 'surname' => 'Doe']),
'Hi, my name is John Doe'
);
}
}

View File

@@ -2,14 +2,17 @@
namespace Tests\Feature\Setup;
use App\Models\Language;
use App\Models\LanguageString;
use App\Models\Setting;
use App\Services\SetupService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Storage;
use Tests\TestCase;
class SetupServiceTest extends TestCase
{
use DatabaseMigrations;
public function __construct()
{
@@ -31,4 +34,31 @@ class SetupServiceTest extends TestCase
Storage::disk('local')->assertExists($directory);
});
}
/**
* @test
*/
public function it_seed_default_language()
{
Setting::create([
'name' => 'license',
'value' => 'Extended',
]);
Language::create([
'name' => 'English',
'locale' => 'en'
]);
$this->assertDatabaseHas('languages', [
'name' => 'English',
'locale' => 'en',
]);
$this->assertDatabaseHas('language_strings', [
'key' => 'actions.close',
'value' => 'Close',
'lang' => 'en',
]);
}
}

View File

@@ -265,6 +265,17 @@ class SetupWizardTest extends TestCase
'value' => '8624194e-3156-4cd0-944e-3440fcecdacb',
]);
$this->assertDatabaseHas('languages', [
'name' => 'English',
'locale' => 'en',
]);
$this->assertDatabaseHas('language_strings', [
'key' => 'actions.close',
'value' => 'Close',
'lang' => 'en',
]);
$avatar = User::first()
->settings
->getRawOriginal('avatar');