Parcourir la source

Merge remote-tracking branch 'origin/dev' into dev

lsm12139 il y a 2 mois
Parent
commit
cea61a00c2

+ 26 - 0
app/Http/Controllers/API/ProjectController.php

@@ -49,10 +49,12 @@ use App\Models\RequirementGroup;
 use App\Repositories\ActionRepository;
 use App\Services\File\FileAssociationService;
 use App\Services\History\ModelChangeDetector;
+use App\Services\Project\ProjectBACnetService;
 use App\Services\Project\ProjectKanbanService;
 use App\Services\Project\ProjectGanttService;
 use App\Services\Project\ProjectTaskGroupViewService;
 use Carbon\Carbon;
+use Illuminate\Http\JsonResponse;
 use Illuminate\Http\Request;
 use Illuminate\Support\Facades\Auth;
 use Illuminate\Support\Facades\Cache;
@@ -727,5 +729,29 @@ class ProjectController extends Controller
         ]);
     }
 
+    /**
+     * 获取指定$siteId的$deviceId的数据
+     * @param Request $request
+     * @param string $siteId
+     * @param string $deviceId
+     * @return JsonResponse
+     */
+    public function fetchDeviceObjects(Request $request, string $siteId, string $deviceId): JsonResponse
+    {
+        $data = (new ProjectBACnetService())->fetchDeviceObjects($siteId, $deviceId);
+        return $this->success(['data' => $data], [],JSON_UNESCAPED_UNICODE | JSON_NUMERIC_CHECK);
+    }
 
+    /**
+     * 获取指定$siteId的$dataKey的数据
+     * @param Request $request
+     * @param string $siteId
+     * @param string $dataKey
+     * @return JsonResponse
+     */
+    public function fetchObjectsValueMulti(Request $request, string $siteId, string $dataKey): JsonResponse
+    {
+        $data = (new ProjectBACnetService())->fetchObjectsValueMulti($siteId, $dataKey);
+        return $this->success(['data' => $data], [],JSON_UNESCAPED_UNICODE | JSON_NUMERIC_CHECK);
+    }
 }

+ 11 - 2
app/Models/Enums/ActionObjectType.php

@@ -4,6 +4,7 @@ namespace App\Models\Enums;
 
 use App\Models\Asset;
 use App\Models\Container;
+use App\Models\File;
 use App\Models\Plan;
 use App\Models\Project;
 use App\Models\Requirement;
@@ -11,6 +12,7 @@ use App\Models\Task;
 use App\Services\History\Detector\AssetDetector;
 use App\Services\History\Detector\ContainerContentDetector;
 use App\Services\History\Detector\ContainerDetector;
+use App\Services\History\Detector\FileDetector;
 use App\Services\History\Detector\ProjectDetector;
 use App\Services\History\Detector\RequirementDetector;
 use App\Services\History\Detector\TaskDetector;
@@ -42,6 +44,7 @@ enum ActionObjectType: string
             self::PLAN => Plan::query(),
             self::REQUIREMENT => Requirement::query(),
             self::CONTAINER => Container::query(),
+            self::CONTAINER_FILE => File::query(),
         };
     }
 
@@ -54,14 +57,19 @@ enum ActionObjectType: string
             self::PLAN => Plan::query(),
             self::REQUIREMENT => Requirement::query(),
             self::CONTAINER => Container::query()->allowed($id),
+            self::CONTAINER_FILE => File::query(),
         };
     }
 
     public function nameField(): string
     {
         return match ($this) {
-            self::ASSET, self::PROJECT, self::TASK  => "name",
-            self::PLAN => "title", self::REQUIREMENT => "title",
+            self::ASSET,
+            self::PROJECT,
+            self::TASK  => "name",
+            self::PLAN => "title",
+            self::REQUIREMENT => "title",
+            self::CONTAINER_FILE => 'title',
             default => "name",
         };
     }
@@ -75,6 +83,7 @@ enum ActionObjectType: string
             ActionObjectType::TASK => TaskDetector::class,
             ActionObjectType::CONTAINER => ContainerDetector::class,
             ActionObjectType::CONTAINER_CONTENT => ContainerContentDetector::class,
+            ActionObjectType::CONTAINER_FILE => FileDetector::class,
             default => null
         };
     }

+ 4 - 1
app/Providers/AppServiceProvider.php

@@ -13,7 +13,10 @@ class AppServiceProvider extends ServiceProvider
      */
     public function register(): void
     {
-        //
+        if ($this->app->environment('local')) {
+            $this->app->register(\Laravel\Telescope\TelescopeServiceProvider::class);
+            $this->app->register(TelescopeServiceProvider::class);
+        }
     }
 
     /**

+ 64 - 0
app/Providers/TelescopeServiceProvider.php

@@ -0,0 +1,64 @@
+<?php
+
+namespace App\Providers;
+
+use Illuminate\Support\Facades\Gate;
+use Laravel\Telescope\IncomingEntry;
+use Laravel\Telescope\Telescope;
+use Laravel\Telescope\TelescopeApplicationServiceProvider;
+
+class TelescopeServiceProvider extends TelescopeApplicationServiceProvider
+{
+    /**
+     * Register any application services.
+     */
+    public function register(): void
+    {
+        // Telescope::night();
+
+        $this->hideSensitiveRequestDetails();
+
+        $isLocal = $this->app->environment('local');
+
+        Telescope::filter(function (IncomingEntry $entry) use ($isLocal) {
+            return $isLocal ||
+                   $entry->isReportableException() ||
+                   $entry->isFailedRequest() ||
+                   $entry->isFailedJob() ||
+                   $entry->isScheduledTask() ||
+                   $entry->hasMonitoredTag();
+        });
+    }
+
+    /**
+     * Prevent sensitive request details from being logged by Telescope.
+     */
+    protected function hideSensitiveRequestDetails(): void
+    {
+        if ($this->app->environment('local')) {
+            return;
+        }
+
+        Telescope::hideRequestParameters(['_token']);
+
+        Telescope::hideRequestHeaders([
+            'cookie',
+            'x-csrf-token',
+            'x-xsrf-token',
+        ]);
+    }
+
+    /**
+     * Register the Telescope gate.
+     *
+     * This gate determines who can access Telescope in non-local environments.
+     */
+    protected function gate(): void
+    {
+        Gate::define('viewTelescope', function ($user) {
+            return in_array($user->email, [
+                "peterguo@lpchku.com"
+            ]);
+        });
+    }
+}

+ 5 - 0
app/Services/File/Upload/FilesUploadTrait.php

@@ -8,8 +8,11 @@ use App\Libraries\BIM\BIMFactory;
 use App\Libraries\ChunkedUpload\ChunkedUploadFactory;
 use App\Models\BimFile;
 use App\Models\ContainerContent;
+use App\Models\Enums\ActionObjectType;
 use App\Models\Enums\FileObjectType;
+use App\Models\Enums\ObjectAction;
 use App\Models\File;
+use App\Repositories\ActionRepository;
 use App\Services\NamingRule\NamingRuleCheck;
 use Illuminate\Http\Request;
 use Illuminate\Http\UploadedFile;
@@ -177,6 +180,8 @@ trait FilesUploadTrait
             'bim_driver' => config("bim.default"),
         ]);
 
+        ActionRepository::create($file->id, ActionObjectType::CONTAINER_FILE, ObjectAction::UPLOADED);
+
         return $file;
     }
 

+ 45 - 0
app/Services/History/Detector/FileDetector.php

@@ -0,0 +1,45 @@
+<?php
+
+namespace App\Services\History\Detector;
+
+use App\Services\History\Converter\AssetConverter;
+use App\Services\History\Converter\AssetGroupConverter;
+use App\Services\History\Converter\ConverterContact;
+use App\Services\History\Converter\EmailConverter;
+use App\Services\History\Converter\ModelConverter;
+use App\Services\History\Converter\ModelEnumConverter;
+use App\Services\History\Converter\PlanConverter;
+use App\Services\History\Converter\RequirementGroupConverter;
+use App\Services\History\Converter\UserConverter;
+use App\Services\History\Converter\WhitelistConverter;
+
+class FileDetector extends DetectorAbstract
+{
+    public static function fields(): array
+    {
+        return [
+            'created_by'
+        ];
+    }
+
+    public static function diffFields(): array
+    {
+        return [
+            'description',
+        ];
+    }
+
+    public static function converters():array
+    {
+        return [
+            "whitelist" => new WhitelistConverter(),
+        ];
+    }
+
+    public static function arrayFields(): array
+    {
+        return [
+
+        ];
+    }
+}

+ 126 - 0
app/Services/Project/ProjectBACnetService.php

@@ -0,0 +1,126 @@
+<?php
+namespace App\Services\Project;
+use GuzzleHttp\Client;
+use GuzzleHttp\Promise;
+use Illuminate\Support\Facades\Http;
+use Illuminate\Support\Facades\Log;
+
+class ProjectBACnetService {
+    protected string $baseProxyUrl;
+    protected string $username;
+    protected string $password;
+    protected array $siteDataMap = [];
+
+    public function __construct()
+    {
+        $this->baseProxyUrl = config('bacnet.base_proxy_url');
+        $this->username = config('bacnet.auth.username');
+        $this->password = config('bacnet.auth.password');
+        $this->siteDataMap = config('bacnet.site_data_map');
+    }
+
+    private function getBasicAuth(): array
+    {
+        return [
+            'auth' => [
+                $this->username,
+                $this->password
+            ]
+        ];
+    }
+
+    public function fetchDeviceObjects($siteId, $deviceId): array
+    {
+        $objectList = $this->siteDataMap[$siteId]['objects'][$deviceId] ?? [];
+        if (empty($objectList)) {
+            return [];
+        }
+        $resData = [];
+        $client = new Client();
+
+        // 创建一个包含所有请求的数组
+        $promises = [];
+        for ($i = 0; $i < count($objectList); $i++) {
+            $objectRef = $objectList[$i];
+            $url = $this->baseProxyUrl."/.bacnet/$siteId/$objectRef?alt=json";
+            $promises[$objectRef] = $client->getAsync($url, $this->getBasicAuth());
+        }
+        try {
+            // 发送并发请求并等待所有响应
+            $responses = Promise\Utils::settle($promises)->wait();
+            foreach ($responses as $response) {
+                if ($response['state'] == "fulfilled") {
+                    $data = json_decode($response['value']->getBody()->getContents(), true);
+                    $resData[] = [
+                        'displayName' => $data['displayName'],
+                        'present-value' => $data['present-value']['value'],
+                        'units' => $data['units']['value'],
+                    ];
+                }
+            }
+        } catch (\Throwable $e) {
+            Log::error('[fetchDeviceObjects] One of the batch requests failed: ' . $e->getMessage());
+        }
+
+        return $resData;
+    }
+
+    public function fetchObjectsValueMulti($siteId, $dataKey): array
+    {
+        $targetData = $this->siteDataMap[$siteId][$dataKey] ?? [];
+        if (empty($targetData)) {
+            return [];
+        }
+        $responseData = [];
+        $data = [
+            '$base' => 'Object',
+            'lifetime' => [
+                '$base' => 'Unsigned',
+                'value' => 120,
+            ],
+            'values' => [
+                '$base' => 'List',
+            ],
+        ];
+        foreach ($targetData as $dataRef) {
+            $nameKey = "$dataRef/object-name";
+            $valueKey = "$dataRef/present-value";
+            $unitsKey = "$dataRef/units";
+            $data['values'][$nameKey] = [
+                '$base' => 'Any',
+                'via' => "/.bacnet/$siteId/$nameKey",
+            ];
+            $data['values'][$valueKey] = [
+                '$base' => 'Any',
+                'via' => "/.bacnet/$siteId/$valueKey",
+            ];
+            $data['values'][$unitsKey] = [
+                '$base' => 'Any',
+                'via' => "/.bacnet/$siteId/$unitsKey",
+            ];
+        }
+        $url = $this->baseProxyUrl."/.multi?alt=json";
+        $presentValueMap = $this->siteDataMap[$siteId]["{$dataKey}-present-value-map"] ?? [];
+        $response = Http::withBasicAuth($this->username, $this->password)->post($url, $data);
+
+        if ($response->successful()) {
+            $json = json_decode($response->body(), true);
+            foreach ($targetData as $dataRef) {
+                $nameKey = "$dataRef/object-name";
+                $valueKey = "$dataRef/present-value";
+                $unitsKey = "$dataRef/units";
+
+                $objectName = $json['values'][$nameKey]['value'] ?? '';
+                $presentValue = $json['values'][$valueKey]['value'] ?? '';
+                $units = $json['values'][$unitsKey]['value'] ?? '';
+
+                $responseData[] = [
+                    'displayName' => $objectName,
+                    'present-value' => $presentValueMap[$presentValue] ?? $presentValue,
+                    'units' => $units,
+                ];
+            }
+        }
+        return $responseData;
+    }
+}

+ 4 - 1
composer.json

@@ -11,6 +11,7 @@
         "iidestiny/laravel-filesystem-oss": "^3.1",
         "laravel/framework": "^10.10",
         "laravel/sanctum": "^3.3",
+        "laravel/telescope": "^5.2",
         "laravel/tinker": "^2.8",
         "maatwebsite/excel": "^3.1",
         "overtrue/laravel-filesystem-cos": "^3.4",
@@ -65,7 +66,9 @@
     },
     "extra": {
         "laravel": {
-            "dont-discover": []
+            "dont-discover": [
+                "laravel/telescope"
+            ]
         }
     },
     "config": {

+ 78 - 3
composer.lock

@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "be3b9d766f321140954c93f9129e2ca7",
+    "content-hash": "c51ee56123f312e6ed567d80a9d6b4da",
     "packages": [
         {
             "name": "aliyuncs/oss-sdk-php",
@@ -1644,6 +1644,81 @@
             ],
             "time": "2024-09-23T13:33:08+00:00"
         },
+        {
+            "name": "laravel/telescope",
+            "version": "v5.2.5",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/laravel/telescope.git",
+                "reference": "f68386a8d816c9e3a011b8301bfd263213bf00d4"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/laravel/telescope/zipball/f68386a8d816c9e3a011b8301bfd263213bf00d4",
+                "reference": "f68386a8d816c9e3a011b8301bfd263213bf00d4",
+                "shasum": "",
+                "mirrors": [
+                    {
+                        "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
+                        "preferred": true
+                    }
+                ]
+            },
+            "require": {
+                "ext-json": "*",
+                "laravel/framework": "^8.37|^9.0|^10.0|^11.0",
+                "php": "^8.0",
+                "symfony/console": "^5.3|^6.0|^7.0",
+                "symfony/var-dumper": "^5.0|^6.0|^7.0"
+            },
+            "require-dev": {
+                "ext-gd": "*",
+                "guzzlehttp/guzzle": "^6.0|^7.0",
+                "laravel/octane": "^1.4|^2.0|dev-develop",
+                "orchestra/testbench": "^6.40|^7.37|^8.17|^9.0",
+                "phpstan/phpstan": "^1.10",
+                "phpunit/phpunit": "^9.0|^10.5"
+            },
+            "type": "library",
+            "extra": {
+                "laravel": {
+                    "providers": [
+                        "Laravel\\Telescope\\TelescopeServiceProvider"
+                    ]
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Laravel\\Telescope\\": "src/",
+                    "Laravel\\Telescope\\Database\\Factories\\": "database/factories/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Taylor Otwell",
+                    "email": "taylor@laravel.com"
+                },
+                {
+                    "name": "Mohamed Said",
+                    "email": "mohamed@laravel.com"
+                }
+            ],
+            "description": "An elegant debug assistant for the Laravel framework.",
+            "keywords": [
+                "debugging",
+                "laravel",
+                "monitoring"
+            ],
+            "support": {
+                "issues": "https://github.com/laravel/telescope/issues",
+                "source": "https://github.com/laravel/telescope/tree/v5.2.5"
+            },
+            "time": "2024-10-31T17:06:07+00:00"
+        },
         {
             "name": "laravel/tinker",
             "version": "v2.10.0",
@@ -9295,12 +9370,12 @@
     ],
     "aliases": [],
     "minimum-stability": "stable",
-    "stability-flags": [],
+    "stability-flags": {},
     "prefer-stable": true,
     "prefer-lowest": false,
     "platform": {
         "php": "^8.1"
     },
-    "platform-dev": [],
+    "platform-dev": {},
     "plugin-api-version": "2.6.0"
 }

+ 1 - 0
config/app.php

@@ -168,6 +168,7 @@ return [
         // App\Providers\BroadcastServiceProvider::class,
         App\Providers\EventServiceProvider::class,
         App\Providers\RouteServiceProvider::class,
+        App\Providers\TelescopeServiceProvider::class,
     ])->toArray(),
 
     /*

+ 173 - 0
config/bacnet.php

@@ -0,0 +1,173 @@
+<?php
+
+return [
+    'base_proxy_url' => env('BACNET_API_BASE_PROXY_URL'),
+    'site_id' => env('BACNET_API_SITE_ID', 'IFC'),
+    'auth' => [
+        'username' => env('BACNET_API_USERNAME'),
+        'password' => env('BACNET_API_PASSWORD'),
+    ],
+    'site_data_map' => [
+        /*site*/
+        'IFC' => [
+            'objects' => [
+                /*our device number*/
+                'CH1' => [
+                    /*bacnet object ref*/
+                    '600/analog-value,6',
+                    '600/analog-value,7',
+                    '600/analog-value,8',
+                    '600/analog-value,9',
+                    '500/analog-value,1407',
+                    '500/analog-value,1408',
+                ],
+                /*our device number*/
+                'CH2' => [
+                    /*bacnet object ref*/
+                    '600/analog-value,10',
+                    '600/analog-value,11',
+                    '600/analog-value,12',
+                    '600/analog-value,13',
+                    '500/analog-value,807',
+                    '500/analog-value,808',
+                ],
+                /*our device number*/
+                'CH3' => [
+                    /*bacnet object ref*/
+                    '600/analog-value,14',
+                    '600/analog-value,15',
+                    '600/analog-value,16',
+                    '600/analog-value,17',
+                    '500/analog-value,1707',
+                    '500/analog-value,1708',
+                ],
+                /*our device number*/
+                'CH4' => [
+                    /*bacnet object ref*/
+                    '600/analog-value,18',
+                    '600/analog-value,19',
+                    '600/analog-value,20',
+                    '600/analog-value,21',
+                    '500/analog-value,1507',
+                    '500/analog-value,1508',
+                ],
+                /*our device number*/
+                'CH5' => [
+                    /*bacnet object ref*/
+                    '600/analog-value,22',
+                    '600/analog-value,23',
+                    '600/analog-value,24',
+                    '600/analog-value,25',
+                    '500/analog-value,707',
+                    '500/analog-value,708',
+                ],
+                /*our device number*/
+                'CH6' => [
+                    /*bacnet object ref*/
+                    '600/analog-value,26',
+                    '600/analog-value,27',
+                    '600/analog-value,28',
+                    '600/analog-value,29',
+                    '500/analog-value,1107',
+                    '500/analog-value,1108',
+                ],
+                /*our device number*/
+                'CH7' => [
+                    /*bacnet object ref*/
+                    '600/analog-value,30',
+                    '600/analog-value,31',
+                    '600/analog-value,32',
+                    '600/analog-value,33',
+                    '500/analog-value,1207',
+                    '500/analog-value,1208',
+                ],
+                /*our device number*/
+                'CH8' => [
+                    /*bacnet object ref*/
+                    '600/analog-value,34',
+                    '600/analog-value,35',
+                    '600/analog-value,36',
+                    '600/analog-value,37',
+                    '500/analog-value,207',
+                    '500/analog-value,208',
+                ],
+                /*our device number*/
+                'CH9' => [
+                    /*bacnet object ref*/
+                    '600/analog-value,38',
+                    '600/analog-value,39',
+                    '600/analog-value,40',
+                    '600/analog-value,41',
+                    '500/analog-value,107',
+                    '500/analog-value,108',
+                ],
+                /*our device number*/
+                'CH10' => [
+                    /*bacnet object ref*/
+                    '600/analog-value,42',
+                    '600/analog-value,43',
+                    '600/analog-value,44',
+                    '600/analog-value,45',
+                    '500/analog-value,507',
+                    '500/analog-value,508',
+                ],
+            ],
+            'objectsStatus' => [
+                '600/binary-value,1',
+                '600/binary-value,2',
+                '600/binary-value,3',
+                '600/binary-value,4',
+                '600/binary-value,5',
+                '600/binary-value,6',
+                '600/binary-value,7',
+                '600/binary-value,8',
+                '600/binary-value,9',
+                '600/binary-value,10',
+            ],
+            'objectsStatus-present-value-map' => [
+                'inactive' => 'OFF',
+                'active' => 'ON',
+            ],
+            'electricity-ranking' => [
+                '500/analog-value,1407',
+                '500/analog-value,807',
+                '500/analog-value,1707',
+                '500/analog-value,1507',
+                '500/analog-value,707',
+                '500/analog-value,1107',
+                '500/analog-value,1207',
+                '500/analog-value,207',
+                '500/analog-value,107',
+                '500/analog-value,507',
+            ],
+            'environmental-monitoring' => [
+                '600/analog-value,1',
+                '600/analog-value,2',
+            ],
+            'energy-consumption' => [
+                '500/analog-value,1408',
+                '500/analog-value,808',
+                '500/analog-value,1708',
+                '500/analog-value,1508',
+                '500/analog-value,708',
+                '500/analog-value,1108',
+                '500/analog-value,1208',
+                '500/analog-value,208',
+                '500/analog-value,108',
+                '500/analog-value,508'
+            ],
+            'capacity' => [
+                '100/analog-value,31',
+                '100/analog-value,32',
+                '100/analog-value,33',
+                '100/analog-value,34',
+                '100/analog-value,35',
+                '100/analog-value,36',
+                '100/analog-value,37',
+                '100/analog-value,38',
+                '100/analog-value,39',
+                '100/analog-value,40',
+            ]
+        ]
+    ]
+];

+ 1 - 0
config/custom-field.php

@@ -8,5 +8,6 @@ return [
         'task',
 //        'project',
         'container',
+        'folder'
     ]
 ];

+ 205 - 0
config/telescope.php

@@ -0,0 +1,205 @@
+<?php
+
+use Laravel\Telescope\Http\Middleware\Authorize;
+use Laravel\Telescope\Watchers;
+
+return [
+
+    /*
+    |--------------------------------------------------------------------------
+    | Telescope Master Switch
+    |--------------------------------------------------------------------------
+    |
+    | This option may be used to disable all Telescope watchers regardless
+    | of their individual configuration, which simply provides a single
+    | and convenient way to enable or disable Telescope data storage.
+    |
+    */
+
+    'enabled' => env('TELESCOPE_ENABLED', true),
+
+    /*
+    |--------------------------------------------------------------------------
+    | Telescope Domain
+    |--------------------------------------------------------------------------
+    |
+    | This is the subdomain where Telescope will be accessible from. If the
+    | setting is null, Telescope will reside under the same domain as the
+    | application. Otherwise, this value will be used as the subdomain.
+    |
+    */
+
+    'domain' => env('TELESCOPE_DOMAIN'),
+
+    /*
+    |--------------------------------------------------------------------------
+    | Telescope Path
+    |--------------------------------------------------------------------------
+    |
+    | This is the URI path where Telescope will be accessible from. Feel free
+    | to change this path to anything you like. Note that the URI will not
+    | affect the paths of its internal API that aren't exposed to users.
+    |
+    */
+
+    'path' => env('TELESCOPE_PATH', 'telescope'),
+
+    /*
+    |--------------------------------------------------------------------------
+    | Telescope Storage Driver
+    |--------------------------------------------------------------------------
+    |
+    | This configuration options determines the storage driver that will
+    | be used to store Telescope's data. In addition, you may set any
+    | custom options as needed by the particular driver you choose.
+    |
+    */
+
+    'driver' => env('TELESCOPE_DRIVER', 'database'),
+
+    'storage' => [
+        'database' => [
+            'connection' => env('DB_CONNECTION', 'mysql'),
+            'chunk' => 1000,
+        ],
+    ],
+
+    /*
+    |--------------------------------------------------------------------------
+    | Telescope Queue
+    |--------------------------------------------------------------------------
+    |
+    | This configuration options determines the queue connection and queue
+    | which will be used to process ProcessPendingUpdate jobs. This can
+    | be changed if you would prefer to use a non-default connection.
+    |
+    */
+
+    'queue' => [
+        'connection' => env('TELESCOPE_QUEUE_CONNECTION', null),
+        'queue' => env('TELESCOPE_QUEUE', null),
+    ],
+
+    /*
+    |--------------------------------------------------------------------------
+    | Telescope Route Middleware
+    |--------------------------------------------------------------------------
+    |
+    | These middleware will be assigned to every Telescope route, giving you
+    | the chance to add your own middleware to this list or change any of
+    | the existing middleware. Or, you can simply stick with this list.
+    |
+    */
+
+    'middleware' => [
+        'web',
+        Authorize::class,
+    ],
+
+    /*
+    |--------------------------------------------------------------------------
+    | Allowed / Ignored Paths & Commands
+    |--------------------------------------------------------------------------
+    |
+    | The following array lists the URI paths and Artisan commands that will
+    | not be watched by Telescope. In addition to this list, some Laravel
+    | commands, like migrations and queue commands, are always ignored.
+    |
+    */
+
+    'only_paths' => [
+        // 'api/*'
+    ],
+
+    'ignore_paths' => [
+        'livewire*',
+        'nova-api*',
+        'pulse*',
+    ],
+
+    'ignore_commands' => [
+        //
+    ],
+
+    /*
+    |--------------------------------------------------------------------------
+    | Telescope Watchers
+    |--------------------------------------------------------------------------
+    |
+    | The following array lists the "watchers" that will be registered with
+    | Telescope. The watchers gather the application's profile data when
+    | a request or task is executed. Feel free to customize this list.
+    |
+    */
+
+    'watchers' => [
+        Watchers\BatchWatcher::class => env('TELESCOPE_BATCH_WATCHER', true),
+
+        Watchers\CacheWatcher::class => [
+            'enabled' => env('TELESCOPE_CACHE_WATCHER', true),
+            'hidden' => [],
+        ],
+
+        Watchers\ClientRequestWatcher::class => env('TELESCOPE_CLIENT_REQUEST_WATCHER', true),
+
+        Watchers\CommandWatcher::class => [
+            'enabled' => env('TELESCOPE_COMMAND_WATCHER', true),
+            'ignore' => [],
+        ],
+
+        Watchers\DumpWatcher::class => [
+            'enabled' => env('TELESCOPE_DUMP_WATCHER', true),
+            'always' => env('TELESCOPE_DUMP_WATCHER_ALWAYS', false),
+        ],
+
+        Watchers\EventWatcher::class => [
+            'enabled' => env('TELESCOPE_EVENT_WATCHER', true),
+            'ignore' => [],
+        ],
+
+        Watchers\ExceptionWatcher::class => env('TELESCOPE_EXCEPTION_WATCHER', true),
+
+        Watchers\GateWatcher::class => [
+            'enabled' => env('TELESCOPE_GATE_WATCHER', true),
+            'ignore_abilities' => [],
+            'ignore_packages' => true,
+            'ignore_paths' => [],
+        ],
+
+        Watchers\JobWatcher::class => env('TELESCOPE_JOB_WATCHER', true),
+
+        Watchers\LogWatcher::class => [
+            'enabled' => env('TELESCOPE_LOG_WATCHER', true),
+            'level' => 'error',
+        ],
+
+        Watchers\MailWatcher::class => env('TELESCOPE_MAIL_WATCHER', true),
+
+        Watchers\ModelWatcher::class => [
+            'enabled' => env('TELESCOPE_MODEL_WATCHER', true),
+            'events' => ['eloquent.*'],
+            'hydrations' => true,
+        ],
+
+        Watchers\NotificationWatcher::class => env('TELESCOPE_NOTIFICATION_WATCHER', true),
+
+        Watchers\QueryWatcher::class => [
+            'enabled' => env('TELESCOPE_QUERY_WATCHER', true),
+            'ignore_packages' => true,
+            'ignore_paths' => [],
+            'slow' => 100,
+        ],
+
+        Watchers\RedisWatcher::class => env('TELESCOPE_REDIS_WATCHER', true),
+
+        Watchers\RequestWatcher::class => [
+            'enabled' => env('TELESCOPE_REQUEST_WATCHER', true),
+            'size_limit' => env('TELESCOPE_RESPONSE_SIZE_LIMIT', 64),
+            'ignore_http_methods' => [],
+            'ignore_status_codes' => [],
+        ],
+
+        Watchers\ScheduleWatcher::class => env('TELESCOPE_SCHEDULE_WATCHER', true),
+        Watchers\ViewWatcher::class => env('TELESCOPE_VIEW_WATCHER', true),
+    ],
+];

+ 70 - 0
database/migrations/2018_08_08_100000_create_telescope_entries_table.php

@@ -0,0 +1,70 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+return new class extends Migration
+{
+    /**
+     * Get the migration connection name.
+     */
+    public function getConnection(): ?string
+    {
+        return config('telescope.storage.database.connection');
+    }
+
+    /**
+     * Run the migrations.
+     */
+    public function up(): void
+    {
+        $schema = Schema::connection($this->getConnection());
+
+        $schema->create('telescope_entries', function (Blueprint $table) {
+            $table->bigIncrements('sequence');
+            $table->uuid('uuid');
+            $table->uuid('batch_id');
+            $table->string('family_hash')->nullable();
+            $table->boolean('should_display_on_index')->default(true);
+            $table->string('type', 20);
+            $table->longText('content');
+            $table->dateTime('created_at')->nullable();
+
+            $table->unique('uuid');
+            $table->index('batch_id');
+            $table->index('family_hash');
+            $table->index('created_at');
+            $table->index(['type', 'should_display_on_index']);
+        });
+
+        $schema->create('telescope_entries_tags', function (Blueprint $table) {
+            $table->uuid('entry_uuid');
+            $table->string('tag');
+
+            $table->primary(['entry_uuid', 'tag']);
+            $table->index('tag');
+
+            $table->foreign('entry_uuid')
+                ->references('uuid')
+                ->on('telescope_entries')
+                ->onDelete('cascade');
+        });
+
+        $schema->create('telescope_monitoring', function (Blueprint $table) {
+            $table->string('tag')->primary();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     */
+    public function down(): void
+    {
+        $schema = Schema::connection($this->getConnection());
+
+        $schema->dropIfExists('telescope_entries_tags');
+        $schema->dropIfExists('telescope_entries');
+        $schema->dropIfExists('telescope_monitoring');
+    }
+};

+ 16 - 1
lang/ar.json

@@ -7,12 +7,14 @@
     "Action": "الإجراء",
     "Actions": "الإجراءات",
     "Add": "إضافة",
+    "Add :name": "إضافة :name",
     "Admin": "مدير",
     "Agree": "موافقة",
     "All rights reserved.": "جميع الحقوق محفوظة.",
     "Already Reported": "تم التبليغ مسبقاً",
     "Archive": "أرشفة",
     "Assign": "تعيين",
+    "Associate": "ربط",
     "Attach": "إرفاق",
     "Bad Gateway": "بوابة غير صالحة",
     "Bad Request": "طلب غير صالح",
@@ -36,8 +38,10 @@
     "Connection Timed Out": "انتهت مهلة الاتصال",
     "Continue": "استمرار",
     "Create": "إنشاء",
+    "Create :name": "إضافة :name",
     "Created": "تم الإنشاء",
     "Delete": "حذف",
+    "Delete :name": "حذف :name",
     "Detach": "إلغاء الإرفاق",
     "Details": "التفاصيل",
     "Disable": "تعطيل",
@@ -45,15 +49,18 @@
     "Done": "مكتمل",
     "Down": "أسفل",
     "Duplicate": "نسخ",
+    "Duplicate :name": "نسخ :name",
     "Duplicate: name": "نسخ: الاسم",
     "Edit": "تعديل",
     "Edit :name": "تعديل :name",
     "Enable": "تفعيل",
+    "errors": "أخطاء",
     "Expand": "توسيع",
     "Expand All": "توسيع الكل",
     "Expectation Failed": "فشل التوقع",
     "Explanation": "توضيح",
     "Export": "تصدير",
+    "Export :name": "تصدير :name",
     "Failed Dependency": "فشل التبعية",
     "File": "ملف",
     "Files": "ملفات",
@@ -75,7 +82,7 @@
     "IM Used": "IM مستخدمة",
     "Image": "صورة",
     "Impersonate": "انتحال الهوية",
-    "Impersonation": "التقليد",
+    "Impersonation": "الاقتباس",
     "Import": "استيراد",
     "Import :name": "استيراد :name",
     "Insufficient Storage": "مساحة تخزين غير كافية",
@@ -87,7 +94,10 @@
     "Like": "إعجاب",
     "Load": "تحميل",
     "Localize": "اللغة",
+    "Location": "موقع",
     "Locked": "مقفل",
+    "Log In": "تسجيل الدخول",
+    "Log Out": "تسجيل الخروج",
     "Login": "تسجيل الدخول",
     "Logout": "تسجيل الخروج",
     "Loop Detected": "تم الكشف عن حلقة",
@@ -134,6 +144,7 @@
     "Proxy Authentication Required": "مصادقة الوكيل مطلوبة",
     "Railgun Error": "خطأ Railgun",
     "Range Not Satisfiable": "نطاق غير مقبول",
+    "Record": "سجل",
     "Regards": "مع التحية",
     "Register": "تسجيل",
     "Request Header Fields Too Large": "حقول عنوان الطلب كبيرة جدا",
@@ -163,8 +174,11 @@
     "Show :name": "عرض :name",
     "Show All": "عرض الكل",
     "Showing": "عرض",
+    "Sign In": "تسجيل الدخول",
     "Solve": "حل",
     "SSL Handshake Failed": "فشلت مصافحة SSL",
+    "Start": "بدء",
+    "Stop": "إيقاف",
     "Submit": "إرسال",
     "Subscribe": "اشتراك",
     "Switch": "تحويل",
@@ -176,6 +190,7 @@
     "The given data was invalid.": "البيانات المدخلة غير صالحة.",
     "The response is not a streamed response.": "الاستجابة ليست استجابة متدفقة.",
     "The response is not a view.": "الاستجابة ليست صفحة عرض.",
+    "This action is unauthorized.": "هذا الإجراء غير مصرح به.",
     "This password reset link will expire in :count minutes.": "ستنتهي صلاحية رابط استعادة كلمة المرور خلال :count دقيقة.",
     "to": "إلى",
     "Toggle navigation": "إظهار/إخفاء القائمة",

+ 18 - 5
lang/ar/actions.php

@@ -11,6 +11,7 @@ return [
     'agree'           => 'موافقة',
     'archive'         => 'أرشفة',
     'assign'          => 'تعيين',
+    'associate'       => 'ربط',
     'attach'          => 'إرفاق',
     'browse'          => 'تصفح',
     'cancel'          => 'إلغاء',
@@ -39,26 +40,34 @@ return [
     'expand_all'      => 'توسيع الكل',
     'explanation'     => 'توضيح',
     'export'          => 'تصدير',
-    'file'            => 'الحقل :attribute يجب أن يكون ملفا.',
+    'file'            => 'ملف',
     'files'           => 'ملفات',
     'go_home'         => 'الانتقال للرئيسية',
     'hide'            => 'إخفاء',
     'home'            => 'الرئيسية',
-    'image'           => 'يجب أن يكون حقل :attribute صورةً.',
+    'image'           => 'صورة',
     'Impersonate'     => 'انتحال الهوية',
+    'impersonate'     => 'اقتباس شخصية',
     'Impersonation'   => 'التقليد',
+    'impersonation'   => 'الاقتباس',
     'import'          => 'استيراد',
     'introduction'    => 'مقدمة',
     'like'            => 'إعجاب',
     'load'            => 'تحميل',
     'localize'        => 'اللغة',
+    'log_in'          => 'تسجيل الدخول',
+    'log_out'         => 'تسجيل الخروج',
     'named'           => [
+        'add'       => 'أضف :name',
         'choose'    => 'اختر :name',
-        'duplicate' => 'مكرر: الاسم',
+        'create'    => 'إنشاء :name',
+        'delete'    => 'حذف :name',
+        'duplicate' => 'نسخ :name',
         'edit'      => 'تعديل :name',
+        'export'    => 'تصدير :name',
         'hide'      => 'إخفاء :name',
         'import'    => 'استيراد :name',
-        'new'       => ':name جديد',
+        'new'       => 'إنشاء :name',
         'restore'   => 'استعادة :name',
         'save'      => 'حفظ :name',
         'search'    => 'بحث :name',
@@ -72,6 +81,7 @@ return [
     'open_website'    => 'فتح على الموقع',
     'preview'         => 'معاينة',
     'price'           => 'السعر',
+    'record'          => 'سجل',
     'restore'         => 'استعادة',
     'save'            => 'حفظ',
     'save_and_close'  => 'حفظ وإغلاق',
@@ -83,7 +93,10 @@ return [
     'settings'        => 'إعدادات',
     'show'            => 'عرض',
     'show_all'        => 'عرض الكل',
+    'sign_in'         => 'تسجيل الدخول',
     'solve'           => 'حل',
+    'start'           => 'بدء',
+    'stop'            => 'إيقاف',
     'submit'          => 'إرسال',
     'subscribe'       => 'اشتراك',
     'switch'          => 'تحويل',
@@ -102,7 +115,7 @@ return [
     'unsubscribe'     => 'إلغاء الاشتراك',
     'up'              => 'أعلى',
     'update'          => 'تحديث',
-    'user'            => 'لم يتم العثور على أيّ حسابٍ بهذا العنوان الإلكتروني.',
+    'user'            => 'مستخدم',
     'view'            => 'عرض',
     'yes'             => 'نعم',
 ];

+ 46 - 5
lang/ar/validation.php

@@ -40,8 +40,8 @@ return [
     'doesnt_start_with'    => 'الحقل :attribute يجب ألّا يبدأ بأحد القيم التالية: :values.',
     'email'                => 'يجب أن يكون حقل :attribute عنوان بريد إلكتروني صحيح البُنية.',
     'ends_with'            => 'يجب أن ينتهي حقل :attribute بأحد القيم التالية: :values',
-    'enum'                 => 'حقل :attribute المختار غير صالح.',
-    'exists'               => 'القيمة المحددة :attribute غير موجودة.',
+    'enum'                 => 'قيمة حقل :attribute غير موجودة في قائمة القيم المسموح بها.',
+    'exists'               => 'قيمة الحقل :attribute غير موجودة.',
     'extensions'           => 'يجب أن يحتوي الحقل :attribute على أحد الإمتدادات التالية: :values.',
     'file'                 => 'الحقل :attribute يجب أن يكون ملفا.',
     'filled'               => 'حقل :attribute إجباري.',
@@ -59,7 +59,7 @@ return [
     ],
     'hex_color'            => 'يجب أن يحتوي الحقل :attribute على صيغة لون HEX صالحة',
     'image'                => 'يجب أن يكون حقل :attribute صورةً.',
-    'in'                   => 'حقل :attribute غير موجود.',
+    'in'                   => 'قيمة حقل :attribute غير موجودة في قائمة القيم المسموح بها.',
     'in_array'             => 'حقل :attribute غير موجود في :other.',
     'integer'              => 'يجب أن يكون حقل :attribute عددًا صحيحًا.',
     'ip'                   => 'يجب أن يكون حقل :attribute عنوان IP صحيحًا.',
@@ -102,7 +102,7 @@ return [
     'missing_with'         => 'يجب أن يكون الحقل :attribute مفقوداً عند توفر :values.',
     'missing_with_all'     => 'يجب أن يكون الحقل :attribute مفقوداً عند توفر :values.',
     'multiple_of'          => 'حقل :attribute يجب أن يكون من مضاعفات :value',
-    'not_in'               => 'عنصر الحقل :attribute غير صحيح.',
+    'not_in'               => 'يجب ألا يكون حقل :attribute موجودًا في القائمة.',
     'not_regex'            => 'صيغة حقل :attribute غير صحيحة.',
     'numeric'              => 'يجب على حقل :attribute أن يكون رقمًا.',
     'password'             => [
@@ -152,39 +152,62 @@ return [
         'affiliate_url'            => 'رابط الأفلييت',
         'age'                      => 'العمر',
         'amount'                   => 'الكمية',
+        'announcement'             => 'إعلان',
         'area'                     => 'المنطقة',
+        'audience_prize'           => 'جائزة الجمهور',
+        'audience_winner'          => 'الفائز باختيار الجمهور',
         'available'                => 'مُتاح',
         'birthday'                 => 'عيد الميلاد',
         'body'                     => 'المُحتوى',
         'city'                     => 'المدينة',
+        'company'                  => 'الشركة',
+        'compilation'              => 'التحويل البرمجي',
+        'concept'                  => 'مفهوم',
+        'conditions'               => 'شروط',
         'content'                  => 'المُحتوى',
+        'contest'                  => 'المسابقة',
         'country'                  => 'الدولة',
-        'created_at'               => 'تاريخ الإنشاء',
+        'cover'                    => 'الغلاف',
+        'created_at'               => 'تاريخ الإضافة',
         'creator'                  => 'المنشئ',
         'currency'                 => 'العملة',
         'current_password'         => 'كلمة المرور الحالية',
         'customer'                 => 'عميل',
         'date'                     => 'التاريخ',
         'date_of_birth'            => 'تاريخ الميلاد',
+        'dates'                    => 'التواريخ',
         'day'                      => 'اليوم',
         'deleted_at'               => 'تاريخ الحذف',
         'description'              => 'الوصف',
+        'display_type'             => 'نوع العرض',
         'district'                 => 'الحي',
         'duration'                 => 'المدة',
         'email'                    => 'البريد الالكتروني',
         'excerpt'                  => 'المُلخص',
         'filter'                   => 'تصفية',
+        'finished_at'              => 'تاريخ الانتهاء',
         'first_name'               => 'الاسم الأول',
         'gender'                   => 'النوع',
+        'grand_prize'              => 'الجائزة الكبرى',
         'group'                    => 'مجموعة',
         'hour'                     => 'ساعة',
         'image'                    => 'صورة',
+        'image_desktop'            => 'صورة سطح المكتب',
+        'image_main'               => 'الصورة الرئيسية',
+        'image_mobile'             => 'صورة الجوال',
+        'images'                   => 'الصور',
+        'is_audience_winner'       => 'الفائز باختيار الجمهور',
+        'is_hidden'                => 'مخفي',
         'is_subscribed'            => 'مشترك',
+        'is_visible'               => 'مرئي',
+        'is_winner'                => 'الفائز',
         'items'                    => 'العناصر',
+        'key'                      => 'مفتاح',
         'last_name'                => 'اسم العائلة',
         'lesson'                   => 'الدرس',
         'line_address_1'           => 'العنوان 1',
         'line_address_2'           => 'العنوان 2',
+        'login'                    => 'تسجيل الدخول',
         'message'                  => 'الرسالة',
         'middle_name'              => 'الاسم الأوسط',
         'minute'                   => 'دقيقة',
@@ -197,6 +220,7 @@ return [
         'password_confirmation'    => 'تأكيد كلمة المرور',
         'phone'                    => 'الهاتف',
         'photo'                    => 'الصورة',
+        'portfolio'                => 'ملف',
         'postal_code'              => 'الرمز البريدي',
         'preview'                  => 'معاينة',
         'price'                    => 'السعر',
@@ -206,20 +230,33 @@ return [
         'promo_code'               => 'رمز ترويجي',
         'province'                 => 'المحافظة',
         'quantity'                 => 'الكمية',
+        'reason'                   => 'سبب',
         'recaptcha_response_field' => 'حقل استجابة recaptcha',
+        'referee'                  => 'حكَم',
+        'referees'                 => 'حكّام',
+        'reject_reason'            => 'سبب الرفض',
         'remember'                 => 'تذكير',
         'restored_at'              => 'تاريخ الاستعادة',
         'result_text_under_image'  => 'نص النتيجة أسفل الصورة',
         'role'                     => 'الصلاحية',
+        'rule'                     => 'قاعدة',
+        'rules'                    => 'قواعد',
         'second'                   => 'ثانية',
         'sex'                      => 'الجنس',
         'shipment'                 => 'الشحنة',
         'short_text'               => 'نص مختصر',
         'size'                     => 'الحجم',
+        'skills'                   => 'مهارات',
+        'slug'                     => 'نص صديق',
+        'specialization'           => 'تخصص',
+        'started_at'               => 'تاريخ الابتداء',
         'state'                    => 'الولاية',
+        'status'                   => 'حالة',
         'street'                   => 'الشارع',
         'student'                  => 'طالب',
         'subject'                  => 'الموضوع',
+        'tag'                      => 'علامة',
+        'tags'                     => 'العلامات',
         'teacher'                  => 'معلّم',
         'terms'                    => 'الأحكام',
         'test_description'         => 'وصف الاختبار',
@@ -228,9 +265,13 @@ return [
         'text'                     => 'نص',
         'time'                     => 'الوقت',
         'title'                    => 'اللقب',
+        'type'                     => 'النوع',
         'updated_at'               => 'تاريخ التحديث',
         'user'                     => 'مستخدم',
         'username'                 => 'اسم المُستخدم',
+        'value'                    => 'قيمة',
+        'winner'                   => 'الفائز',
+        'work'                     => 'العمل',
         'year'                     => 'السنة',
     ],
 ];

+ 15 - 0
lang/en.json

@@ -7,12 +7,14 @@
     "Action": "Action",
     "Actions": "Actions",
     "Add": "Add",
+    "Add :name": "Add :name",
     "Admin": "Admin",
     "Agree": "Agree",
     "All rights reserved.": "All rights reserved.",
     "Already Reported": "Already Reported",
     "Archive": "Archive",
     "Assign": "Assign",
+    "Associate": "Associate",
     "Attach": "Attach",
     "Bad Gateway": "Bad Gateway",
     "Bad Request": "Bad Request",
@@ -36,8 +38,10 @@
     "Connection Timed Out": "Connection Timed Out",
     "Continue": "Continue",
     "Create": "Create",
+    "Create :name": "Create :name",
     "Created": "Created",
     "Delete": "Delete",
+    "Delete :name": "Delete :name",
     "Detach": "Detach",
     "Details": "Details",
     "Disable": "Disable",
@@ -45,15 +49,18 @@
     "Done": "Done",
     "Down": "Down",
     "Duplicate": "Duplicate",
+    "Duplicate :name": "Duplicate :name",
     "Duplicate: name": "Duplicate: name",
     "Edit": "Edit",
     "Edit :name": "Edit :name",
     "Enable": "Enable",
+    "errors": "errors",
     "Expand": "Expand",
     "Expand All": "Expand All",
     "Expectation Failed": "Expectation Failed",
     "Explanation": "Explanation",
     "Export": "Export",
+    "Export :name": "Export :name",
     "Failed Dependency": "Failed Dependency",
     "File": "File",
     "Files": "Files",
@@ -87,7 +94,10 @@
     "Like": "Like",
     "Load": "Load",
     "Localize": "Localize",
+    "Location": "Location",
     "Locked": "Locked",
+    "Log In": "Log In",
+    "Log Out": "Log Out",
     "Login": "Login",
     "Logout": "Logout",
     "Loop Detected": "Loop Detected",
@@ -134,6 +144,7 @@
     "Proxy Authentication Required": "Proxy Authentication Required",
     "Railgun Error": "Railgun Error",
     "Range Not Satisfiable": "Range Not Satisfiable",
+    "Record": "Record",
     "Regards": "Regards",
     "Register": "Register",
     "Request Header Fields Too Large": "Request Header Fields Too Large",
@@ -163,8 +174,11 @@
     "Show :name": "Show :name",
     "Show All": "Show All",
     "Showing": "Showing",
+    "Sign In": "Sign In",
     "Solve": "Solve",
     "SSL Handshake Failed": "SSL Handshake Failed",
+    "Start": "Start",
+    "Stop": "Stop",
     "Submit": "Submit",
     "Subscribe": "Subscribe",
     "Switch": "Switch",
@@ -176,6 +190,7 @@
     "The given data was invalid.": "The given data was invalid.",
     "The response is not a streamed response.": "The response is not a streamed response.",
     "The response is not a view.": "The response is not a view.",
+    "This action is unauthorized.": "This action is unauthorized.",
     "This password reset link will expire in :count minutes.": "This password reset link will expire in :count minutes.",
     "to": "to",
     "Toggle navigation": "Toggle navigation",

+ 17 - 4
lang/en/actions.php

@@ -11,6 +11,7 @@ return [
     'agree'           => 'Agree',
     'archive'         => 'Archive',
     'assign'          => 'Assign',
+    'associate'       => 'Associate',
     'attach'          => 'Attach',
     'browse'          => 'Browse',
     'cancel'          => 'Cancel',
@@ -39,23 +40,31 @@ return [
     'expand_all'      => 'Expand All',
     'explanation'     => 'Explanation',
     'export'          => 'Export',
-    'file'            => 'The :attribute must be a file.',
+    'file'            => 'File',
     'files'           => 'Files',
     'go_home'         => 'Go Home',
     'hide'            => 'Hide',
     'home'            => 'Home',
-    'image'           => 'The :attribute must be an image.',
+    'image'           => 'Image',
     'Impersonate'     => 'Impersonate',
+    'impersonate'     => 'Impersonate',
     'Impersonation'   => 'Impersonation',
+    'impersonation'   => 'Impersonation',
     'import'          => 'Import',
     'introduction'    => 'Introduction',
     'like'            => 'Like',
     'load'            => 'Load',
     'localize'        => 'Localize',
+    'log_in'          => 'Log In',
+    'log_out'         => 'Log Out',
     'named'           => [
+        'add'       => 'Add :name',
         'choose'    => 'Choose :name',
-        'duplicate' => 'Duplicate: name',
+        'create'    => 'Create :name',
+        'delete'    => 'Delete :name',
+        'duplicate' => 'Duplicate :name',
         'edit'      => 'Edit :name',
+        'export'    => 'Export :name',
         'hide'      => 'Hide :name',
         'import'    => 'Import :name',
         'new'       => 'New :name',
@@ -72,6 +81,7 @@ return [
     'open_website'    => 'Open on the website',
     'preview'         => 'Preview',
     'price'           => 'Price',
+    'record'          => 'Record',
     'restore'         => 'Restore',
     'save'            => 'Save',
     'save_and_close'  => 'Save & Close',
@@ -83,7 +93,10 @@ return [
     'settings'        => 'Settings',
     'show'            => 'Show',
     'show_all'        => 'Show All',
+    'sign_in'         => 'Sign In',
     'solve'           => 'Solve',
+    'start'           => 'Start',
+    'stop'            => 'Stop',
     'submit'          => 'Submit',
     'subscribe'       => 'Subscribe',
     'switch'          => 'Switch',
@@ -102,7 +115,7 @@ return [
     'unsubscribe'     => 'Unsubscribe',
     'up'              => 'Up',
     'update'          => 'Update',
-    'user'            => 'We can\'t find a user with that email address.',
+    'user'            => 'User',
     'view'            => 'View',
     'yes'             => 'Yes',
 ];

+ 45 - 4
lang/en/validation.php

@@ -40,8 +40,8 @@ return [
     'doesnt_start_with'    => 'The :attribute field must not start with one of the following: :values.',
     'email'                => 'The :attribute must be a valid email address.',
     'ends_with'            => 'The :attribute must end with one of the following: :values.',
-    'enum'                 => 'The selected :attribute is invalid.',
-    'exists'               => 'The selected :attribute is invalid.',
+    'enum'                 => 'The :attribute field value is not in the list of allowed values.',
+    'exists'               => 'The :attribute field value does not exist.',
     'extensions'           => 'The :attribute field must have one of the following extensions: :values.',
     'file'                 => 'The :attribute must be a file.',
     'filled'               => 'The :attribute field must have a value.',
@@ -59,7 +59,7 @@ return [
     ],
     'hex_color'            => 'The :attribute field must be a valid hexadecimal color.',
     'image'                => 'The :attribute must be an image.',
-    'in'                   => 'The selected :attribute is invalid.',
+    'in'                   => 'The :attribute field value is not in the list of allowed values.',
     'in_array'             => 'The :attribute field does not exist in :other.',
     'integer'              => 'The :attribute must be an integer.',
     'ip'                   => 'The :attribute must be a valid IP address.',
@@ -102,7 +102,7 @@ return [
     'missing_with'         => 'The :attribute field must be missing when :values is present.',
     'missing_with_all'     => 'The :attribute field must be missing when :values are present.',
     'multiple_of'          => 'The :attribute must be a multiple of :value.',
-    'not_in'               => 'The selected :attribute is invalid.',
+    'not_in'               => 'The :attribute field must not be in the list.',
     'not_regex'            => 'The :attribute format is invalid.',
     'numeric'              => 'The :attribute must be a number.',
     'password'             => [
@@ -152,13 +152,22 @@ return [
         'affiliate_url'            => 'affiliate URL',
         'age'                      => 'age',
         'amount'                   => 'amount',
+        'announcement'             => 'announcement',
         'area'                     => 'area',
+        'audience_prize'           => 'audience prize',
+        'audience_winner'          => 'audience winner',
         'available'                => 'available',
         'birthday'                 => 'birthday',
         'body'                     => 'body',
         'city'                     => 'city',
+        'company'                  => 'company',
+        'compilation'              => 'compilation',
+        'concept'                  => 'concept',
+        'conditions'               => 'conditions',
         'content'                  => 'content',
+        'contest'                  => 'contest',
         'country'                  => 'country',
+        'cover'                    => 'cover',
         'created_at'               => 'created at',
         'creator'                  => 'creator',
         'currency'                 => 'currency',
@@ -166,25 +175,39 @@ return [
         'customer'                 => 'customer',
         'date'                     => 'date',
         'date_of_birth'            => 'date of birth',
+        'dates'                    => 'dates',
         'day'                      => 'day',
         'deleted_at'               => 'deleted at',
         'description'              => 'description',
+        'display_type'             => 'display type',
         'district'                 => 'district',
         'duration'                 => 'duration',
         'email'                    => 'email',
         'excerpt'                  => 'excerpt',
         'filter'                   => 'filter',
+        'finished_at'              => 'finished at',
         'first_name'               => 'first name',
         'gender'                   => 'gender',
+        'grand_prize'              => 'grand prize',
         'group'                    => 'group',
         'hour'                     => 'hour',
         'image'                    => 'image',
+        'image_desktop'            => 'desktop image',
+        'image_main'               => 'main image',
+        'image_mobile'             => 'mobile image',
+        'images'                   => 'images',
+        'is_audience_winner'       => 'is audience winner',
+        'is_hidden'                => 'is hidden',
         'is_subscribed'            => 'is subscribed',
+        'is_visible'               => 'is visible',
+        'is_winner'                => 'is winner',
         'items'                    => 'items',
+        'key'                      => 'key',
         'last_name'                => 'last name',
         'lesson'                   => 'lesson',
         'line_address_1'           => 'line address 1',
         'line_address_2'           => 'line address 2',
+        'login'                    => 'login',
         'message'                  => 'message',
         'middle_name'              => 'middle name',
         'minute'                   => 'minute',
@@ -197,6 +220,7 @@ return [
         'password_confirmation'    => 'password confirmation',
         'phone'                    => 'phone',
         'photo'                    => 'photo',
+        'portfolio'                => 'portfolio',
         'postal_code'              => 'postal code',
         'preview'                  => 'preview',
         'price'                    => 'price',
@@ -206,20 +230,33 @@ return [
         'promo_code'               => 'promo code',
         'province'                 => 'province',
         'quantity'                 => 'quantity',
+        'reason'                   => 'reason',
         'recaptcha_response_field' => 'recaptcha response field',
+        'referee'                  => 'referee',
+        'referees'                 => 'referees',
+        'reject_reason'            => 'reject reason',
         'remember'                 => 'remember',
         'restored_at'              => 'restored at',
         'result_text_under_image'  => 'result text under image',
         'role'                     => 'role',
+        'rule'                     => 'rule',
+        'rules'                    => 'rules',
         'second'                   => 'second',
         'sex'                      => 'sex',
         'shipment'                 => 'shipment',
         'short_text'               => 'short text',
         'size'                     => 'size',
+        'skills'                   => 'skills',
+        'slug'                     => 'slug',
+        'specialization'           => 'specialization',
+        'started_at'               => 'started at',
         'state'                    => 'state',
+        'status'                   => 'status',
         'street'                   => 'street',
         'student'                  => 'student',
         'subject'                  => 'subject',
+        'tag'                      => 'tag',
+        'tags'                     => 'tags',
         'teacher'                  => 'teacher',
         'terms'                    => 'terms',
         'test_description'         => 'test description',
@@ -228,9 +265,13 @@ return [
         'text'                     => 'text',
         'time'                     => 'time',
         'title'                    => 'title',
+        'type'                     => 'type',
         'updated_at'               => 'updated at',
         'user'                     => 'user',
         'username'                 => 'username',
+        'value'                    => 'value',
+        'winner'                   => 'winner',
+        'work'                     => 'work',
         'year'                     => 'year',
     ],
 ];

+ 26 - 11
lang/zh_CN.json

@@ -7,12 +7,14 @@
     "Action": "操作",
     "Actions": "操作",
     "Add": "添加",
-    "Admin": "行政",
+    "Add :name": "添加 :name",
+    "Admin": "管理员",
     "Agree": "同意",
     "All rights reserved.": "版权所有。",
     "Already Reported": "已上报",
     "Archive": "档案",
     "Assign": "分配",
+    "Associate": "联系",
     "Attach": "附加",
     "Bad Gateway": "网关错误",
     "Bad Request": "请求错误",
@@ -26,7 +28,7 @@
     "Click to copy": "点击复制",
     "Client Closed Request": "客户端关闭请求",
     "Close": "关闭",
-    "Collapse": "坍塌",
+    "Collapse": "收缩",
     "Collapse All": "全部收缩",
     "Comment": "评论",
     "Confirm": "确认",
@@ -36,24 +38,29 @@
     "Connection Timed Out": "连接超时",
     "Continue": "继续请求",
     "Create": "创建",
+    "Create :name": "创建 :name 个",
     "Created": "已创建",
     "Delete": "删除",
+    "Delete :name": "删除 :name 个",
     "Detach": "分离",
     "Details": "详情",
     "Disable": "禁用",
     "Discard": "丢弃",
-    "Done": "完",
+    "Done": "完",
     "Down": "向下",
     "Duplicate": "复制",
+    "Duplicate :name": "重复:名称",
     "Duplicate: name": "重复:名称",
     "Edit": "编辑",
     "Edit :name": "编辑:name",
     "Enable": "启用",
-    "Expand": "扩张",
+    "errors": "错误",
+    "Expand": "展开",
     "Expand All": "展开全部",
     "Expectation Failed": "期望不满足",
     "Explanation": "解释",
-    "Export": "出口",
+    "Export": "导出",
+    "Export :name": "导出 :name",
     "Failed Dependency": "失败的依赖",
     "File": "文件",
     "Files": "文件",
@@ -76,8 +83,8 @@
     "Image": "图像",
     "Impersonate": "模拟登录",
     "Impersonation": "冒充",
-    "Import": "进口",
-    "Import :name": "进口 :name",
+    "Import": "导入",
+    "Import :name": "导入 :name",
     "Insufficient Storage": "存储空间不足",
     "Internal Server Error": "内部服务器错误",
     "Introduction": "介绍",
@@ -87,7 +94,10 @@
     "Like": "喜欢",
     "Load": "加载",
     "Localize": "本地化",
+    "Location": "地点",
     "Locked": "锁定",
+    "Log In": "登录",
+    "Log Out": "登出",
     "Login": "登录",
     "Logout": "登出",
     "Loop Detected": "检测到环路",
@@ -134,6 +144,7 @@
     "Proxy Authentication Required": "需要代理验证",
     "Railgun Error": "轨道炮错误",
     "Range Not Satisfiable": "请求范围不符合",
+    "Record": "记录",
     "Regards": "致敬",
     "Register": "注册",
     "Request Header Fields Too Large": "请求标头字段太大",
@@ -148,7 +159,7 @@
     "Save": "保存",
     "Save & Close": "保存并关闭",
     "Save & Return": "保存并返回",
-    "Save :name": "节省 :name",
+    "Save :name": "保存 :name",
     "Search": "搜索",
     "Search :name": "搜索 :name",
     "See Other": "见其他",
@@ -159,15 +170,18 @@
     "Service Unavailable": "服务不可用",
     "Session Has Expired": "会话已过期",
     "Settings": "设置",
-    "Show": "示",
+    "Show": "示",
     "Show :name": "显示 :name",
     "Show All": "显示所有",
     "Showing": "显示中",
+    "Sign In": "登入",
     "Solve": "解决",
     "SSL Handshake Failed": "SSL握手失败",
+    "Start": "开始",
+    "Stop": "停止",
     "Submit": "提交",
     "Subscribe": "订阅",
-    "Switch": "转变",
+    "Switch": "切换",
     "Switch To Role": "切换角色",
     "Switching Protocols": "切换协议",
     "Tag": "标签",
@@ -176,6 +190,7 @@
     "The given data was invalid.": "给定的数据无效。",
     "The response is not a streamed response.": "该响应不是流式响应。",
     "The response is not a view.": "响应不是视图。",
+    "This action is unauthorized.": "此操作未经授权。",
     "This password reset link will expire in :count minutes.": "这个重设密码链接将会在 :count 分钟后失效。",
     "to": "至",
     "Toggle navigation": "切换导航",
@@ -186,7 +201,7 @@
     "Unauthorized": "未授权",
     "Unavailable For Legal Reasons": "法律原因不可用",
     "Unknown Error": "未知错误",
-    "Unpack": "打开包装",
+    "Unpack": "打开",
     "Unprocessable Entity": "不可处理的实体",
     "Unsubscribe": "退订",
     "Unsupported Media Type": "不支持的媒体类型",

+ 18 - 18
lang/zh_CN/actions.php

@@ -7,7 +7,7 @@ return [
     'action'          => '行动',
     'actions'         => '行动',
     'add'             => '添加',
-    'admin'           => '行政',
+    'admin'           => '管理员',
     'agree'           => '同意',
     'archive'         => '档案',
     'assign'          => '分配',
@@ -20,37 +20,37 @@ return [
     'choose_image'    => '选择图片',
     'click_to_copy'   => '点击复制',
     'close'           => '关闭',
-    'collapse'        => '坍塌',
+    'collapse'        => '收缩',
     'collapse_all'    => '全部收缩',
     'comment'         => '评论',
     'confirm'         => '确认',
     'connect'         => '连接',
-    'create'          => '创',
+    'create'          => '创',
     'delete'          => '删除',
     'detach'          => '分离',
     'details'         => '细节',
     'disable'         => '禁用',
     'discard'         => '丢弃',
-    'done'            => '完',
+    'done'            => '完',
     'down'            => '向下',
     'duplicate'       => '复制',
     'edit'            => '编辑',
-    'enable'          => '使能够',
-    'expand'          => '扩张',
+    'enable'          => '启用',
+    'expand'          => '展开',
     'expand_all'      => '展开全部',
     'explanation'     => '解释',
-    'export'          => '出',
-    'file'            => ':Attribute 必须是文件',
+    'export'          => '出',
+    'file'            => '文件',
     'files'           => '文件',
     'go_home'         => '回家',
     'hide'            => '隐藏',
     'home'            => '家',
-    'image'           => ':Attribute 必须是图片。',
+    'image'           => '图像',
     'Impersonate'     => '模拟登录',
     'impersonate'     => '模仿',
     'Impersonation'   => '冒充',
     'impersonation'   => '冒充',
-    'import'          => '进口',
+    'import'          => '导入',
     'introduction'    => '介绍',
     'like'            => '喜欢',
     'load'            => '加载',
@@ -66,10 +66,10 @@ return [
         'edit'      => '编辑:name',
         'export'    => '导出 :name',
         'hide'      => '隐藏 :name',
-        'import'    => '进口 :name',
+        'import'    => '导入 :name',
         'new'       => '新 :name',
         'restore'   => '恢复:name',
-        'save'      => '节省 :name',
+        'save'      => '保存 :name',
         'search'    => '搜索 :name',
         'show'      => '显示 :name',
         'update'    => '更新:name',
@@ -83,7 +83,7 @@ return [
     'price'           => '价格',
     'record'          => '记录',
     'restore'         => '恢复',
-    'save'            => '节省',
+    'save'            => '保存',
     'save_and_close'  => '保存并关闭',
     'save_and_return' => '保存并返回',
     'search'          => '搜索',
@@ -91,7 +91,7 @@ return [
     'select_all'      => '全选',
     'send'            => '发送',
     'settings'        => '设置',
-    'show'            => '示',
+    'show'            => '示',
     'show_all'        => '显示所有',
     'sign_in'         => '登入',
     'solve'           => '解决',
@@ -99,7 +99,7 @@ return [
     'stop'            => '停止',
     'submit'          => '提交',
     'subscribe'       => '订阅',
-    'switch'          => '转变',
+    'switch'          => '切换',
     'switch_to_role'  => '切换角色',
     'tag'             => '标签',
     'tags'            => '标签',
@@ -111,11 +111,11 @@ return [
     ],
     'translate'       => '翻译',
     'translate_it'    => '翻译它',
-    'unpack'          => '打开包装',
+    'unpack'          => '打开',
     'unsubscribe'     => '退订',
     'up'              => '向上',
     'update'          => '更新',
-    'user'            => '找不到该邮箱对应的用户',
-    'view'            => '看',
+    'user'            => '用户',
+    'view'            => '看',
     'yes'             => '是的',
 ];

+ 5 - 0
lang/zh_CN/validation.php

@@ -155,14 +155,17 @@ return [
         'announcement'             => '公告',
         'area'                     => '区域',
         'audience_prize'           => '观众奖',
+        'audience_winner'          => 'audience winner',
         'available'                => '可用的',
         'birthday'                 => '生日',
         'body'                     => '身体',
         'city'                     => '城市',
+        'company'                  => 'company',
         'compilation'              => '汇编',
         'concept'                  => '概念',
         'conditions'               => '状况',
         'content'                  => '内容',
+        'contest'                  => 'contest',
         'country'                  => '国家',
         'cover'                    => '覆盖',
         'created_at'               => '创建于',
@@ -267,6 +270,8 @@ return [
         'user'                     => '用户',
         'username'                 => '用户名',
         'value'                    => '价值',
+        'winner'                   => 'winner',
+        'work'                     => 'work',
         'year'                     => '年',
     ],
 ];

+ 30 - 15
lang/zh_TW.json

@@ -7,12 +7,14 @@
     "Action": "開始!",
     "Actions": "動作",
     "Add": "新增",
+    "Add :name": "新增:name",
     "Admin": "行政",
     "Agree": "同意",
     "All rights reserved.": "版權所有。",
     "Already Reported": "已舉報",
     "Archive": "檔案",
     "Assign": "分配",
+    "Associate": "链接",
     "Attach": "附加",
     "Bad Gateway": "錯誤的網關",
     "Bad Request": "錯誤的請求",
@@ -26,9 +28,9 @@
     "Click to copy": "點選複製",
     "Client Closed Request": "客戶端關閉請求",
     "Close": "關閉",
-    "Collapse": "坍塌",
-    "Collapse All": "全部收",
-    "Comment": "評論",
+    "Collapse": "收合",
+    "Collapse All": "全部收",
+    "Comment": "留言",
     "Confirm": "確認",
     "Conflict": "衝突",
     "Connect": "連接",
@@ -36,8 +38,10 @@
     "Connection Timed Out": "連接超時",
     "Continue": "繼續",
     "Create": "建立",
+    "Create :name": "建立 :name 個",
     "Created": "已創建",
     "Delete": "刪除",
+    "Delete :name": "刪除 :name 個",
     "Detach": "分離",
     "Details": "詳情",
     "Disable": "停用",
@@ -45,18 +49,21 @@
     "Done": "完畢",
     "Down": "向下",
     "Duplicate": "複製",
+    "Duplicate :name": "重複:名稱",
     "Duplicate: name": "重複:名稱",
     "Edit": "編輯",
     "Edit :name": "編輯:name",
     "Enable": "啟用",
-    "Expand": "擴張",
+    "errors": "錯誤",
+    "Expand": "展開",
     "Expand All": "展開全部",
     "Expectation Failed": "期望失敗",
     "Explanation": "解釋",
-    "Export": "出口",
+    "Export": "匯出",
+    "Export :name": "Export :name",
     "Failed Dependency": "失敗的依賴",
-    "File": "文件",
-    "Files": "文件",
+    "File": "檔案",
+    "Files": "檔案",
     "Forbidden": "拒絕存取",
     "Found": "成立",
     "Gateway Timeout": "網關超時",
@@ -66,7 +73,7 @@
     "Hello!": "您好!",
     "Hide": "隱藏",
     "Hide :name": "隱藏 :name",
-    "Home": "",
+    "Home": "首頁",
     "HTTP Version Not Supported": "不支持 HTTP 版本",
     "I'm a teapot": "我是茶壺",
     "If you did not create an account, no further action is required.": "如果您未註冊帳號,請忽略此郵件。",
@@ -76,8 +83,8 @@
     "Image": "影像",
     "Impersonate": "模擬登入",
     "Impersonation": "冒充",
-    "Import": "進口",
-    "Import :name": "進口 :name",
+    "Import": "匯入",
+    "Import :name": "匯入 :name",
     "Insufficient Storage": "存儲空間不足",
     "Internal Server Error": "內部服務器錯誤",
     "Introduction": "介紹",
@@ -87,7 +94,10 @@
     "Like": "喜歡",
     "Load": "載入",
     "Localize": "在地化",
+    "Location": "地點",
     "Locked": "鎖定",
+    "Log In": "登入",
+    "Log Out": "登出",
     "Login": "登入",
     "Logout": "登出",
     "Loop Detected": "檢測到環路",
@@ -134,6 +144,7 @@
     "Proxy Authentication Required": "需要代理身份驗證",
     "Railgun Error": "軌道炮錯誤",
     "Range Not Satisfiable": "範圍不可滿足",
+    "Record": "記錄",
     "Regards": "致敬",
     "Register": "註冊",
     "Request Header Fields Too Large": "請求標頭字段太大",
@@ -148,7 +159,7 @@
     "Save": "儲存",
     "Save & Close": "儲存並關閉",
     "Save & Return": "儲存並返回",
-    "Save :name": "節省 :name",
+    "Save :name": "儲存 :name",
     "Search": "搜尋",
     "Search :name": "搜尋 :name",
     "See Other": "查看其他",
@@ -159,15 +170,18 @@
     "Service Unavailable": "暫時不提供服務",
     "Session Has Expired": "會話已過期",
     "Settings": "設定",
-    "Show": "示",
+    "Show": "示",
     "Show :name": "顯示 :name",
-    "Show All": "顯示所有",
+    "Show All": "顯示全部",
     "Showing": "顯示中",
+    "Sign In": "登入",
     "Solve": "解決",
     "SSL Handshake Failed": "SSL 握手失敗",
+    "Start": "開始",
+    "Stop": "停止",
     "Submit": "提交",
     "Subscribe": "訂閱",
-    "Switch": "轉變",
+    "Switch": "切換",
     "Switch To Role": "切換角色",
     "Switching Protocols": "切換協議",
     "Tag": "標籤",
@@ -176,6 +190,7 @@
     "The given data was invalid.": "給定的數據無效。",
     "The response is not a streamed response.": "該響應不是流式響應。",
     "The response is not a view.": "響應不是視圖。",
+    "This action is unauthorized.": "此操作未經授權。",
     "This password reset link will expire in :count minutes.": "重設密碼連結將會在 :count 分鐘後失效。",
     "to": "至",
     "Toggle navigation": "切換導覽",
@@ -200,7 +215,7 @@
     "Variant Also Negotiates": "變體也協商",
     "Verify Email Address": "驗證電子郵件地址",
     "View": "檢視",
-    "View :name": "查看 :name",
+    "View :name": "檢視 :name",
     "Web Server is Down": "Web 服務器已關閉",
     "Whoops!": "哎呀!",
     "Yes": "是",

+ 39 - 26
lang/zh_TW/actions.php

@@ -6,25 +6,26 @@ return [
     'accept'          => '接受',
     'action'          => '行動',
     'actions'         => '行動',
-    'add'             => '添加',
+    'add'             => '新增',
     'admin'           => '行政',
     'agree'           => '同意',
     'archive'         => '檔案',
     'assign'          => '分配',
+    'associate'       => '链接',
     'attach'          => '附',
     'browse'          => '瀏覽',
     'cancel'          => '取消',
     'choose'          => '選擇',
-    'choose_file'     => '選擇文件',
+    'choose_file'     => '選擇檔案',
     'choose_image'    => '選擇圖片',
     'click_to_copy'   => '點選複製',
     'close'           => '關閉',
-    'collapse'        => '坍塌',
-    'collapse_all'    => '全部收',
-    'comment'         => '評論',
+    'collapse'        => '收合',
+    'collapse_all'    => '全部收',
+    'comment'         => '留言',
     'confirm'         => '確認',
     'connect'         => '連接',
-    'create'          => '創造',
+    'create'          => '建立',
     'delete'          => '刪除',
     'detach'          => '分離',
     'details'         => '細節',
@@ -34,37 +35,45 @@ return [
     'down'            => '向下',
     'duplicate'       => '複製',
     'edit'            => '編輯',
-    'enable'          => '使能夠',
-    'expand'          => '擴張',
+    'enable'          => '啟用',
+    'expand'          => '展開',
     'expand_all'      => '展開全部',
     'explanation'     => '解釋',
-    'export'          => '出',
-    'file'            => ':Attribute 必須是有效的檔案',
-    'files'           => '文件',
-    'go_home'         => '回',
+    'export'          => '出',
+    'file'            => '檔案',
+    'files'           => '檔案',
+    'go_home'         => '回首頁',
     'hide'            => '隱藏',
-    'home'            => '',
-    'image'           => ':Attribute 必須是一張圖片。',
+    'home'            => '首頁',
+    'image'           => '影像',
     'Impersonate'     => '模擬登入',
+    'impersonate'     => '模仿',
     'Impersonation'   => '冒充',
-    'import'          => '進口',
+    'impersonation'   => '冒充',
+    'import'          => '匯入',
     'introduction'    => '介紹',
     'like'            => '喜歡',
     'load'            => '載入',
     'localize'        => '在地化',
+    'log_in'          => '登入',
+    'log_out'         => '登出',
     'named'           => [
+        'add'       => '新增:name',
         'choose'    => '選擇:name',
-        'duplicate' => '重複:名稱',
+        'create'    => '建立 :name 個',
+        'delete'    => '刪除 :name 個',
+        'duplicate' => '重複:name',
         'edit'      => '編輯:name',
+        'export'    => '匯出:name',
         'hide'      => '隱藏 :name',
-        'import'    => '進口 :name',
+        'import'    => '匯入:name',
         'new'       => '新 :name',
         'restore'   => '恢復:name',
-        'save'      => '節省 :name',
+        'save'      => '儲存:name',
         'search'    => '搜尋 :name',
         'show'      => '顯示 :name',
         'update'    => '更新:name',
-        'view'      => '查看 :name',
+        'view'      => '檢視:name',
     ],
     'new'             => '新的',
     'no'              => '不',
@@ -72,8 +81,9 @@ return [
     'open_website'    => '在網站上打開',
     'preview'         => '預覽',
     'price'           => '價格',
+    'record'          => '記錄',
     'restore'         => '恢復',
-    'save'            => '節省',
+    'save'            => '儲存',
     'save_and_close'  => '儲存並關閉',
     'save_and_return' => '儲存並返回',
     'search'          => '搜尋',
@@ -81,12 +91,15 @@ return [
     'select_all'      => '全選',
     'send'            => '傳送',
     'settings'        => '設定',
-    'show'            => '展示',
-    'show_all'        => '顯示所有',
+    'show'            => '顯示',
+    'show_all'        => '顯示全部',
+    'sign_in'         => '登入',
     'solve'           => '解決',
+    'start'           => '開始',
+    'stop'            => '停止',
     'submit'          => '提交',
     'subscribe'       => '訂閱',
-    'switch'          => '轉變',
+    'switch'          => '切換',
     'switch_to_role'  => '切換角色',
     'tag'             => '標籤',
     'tags'            => '標籤',
@@ -102,7 +115,7 @@ return [
     'unsubscribe'     => '退訂',
     'up'              => '向上',
     'update'          => '更新',
-    'user'            => '找不到該 E-mail 對應的使用者',
-    'view'            => '看法',
-    'yes'             => '是',
+    'user'            => '使用者',
+    'view'            => '檢視',
+    'yes'             => '是',
 ];

+ 41 - 0
lang/zh_TW/validation.php

@@ -152,13 +152,22 @@ return [
         'affiliate_url'            => '附屬網址',
         'age'                      => '年齡',
         'amount'                   => '數量',
+        'announcement'             => '公告',
         'area'                     => '區域',
+        'audience_prize'           => '觀眾獎',
+        'audience_winner'          => 'audience winner',
         'available'                => '可用的',
         'birthday'                 => '生日',
         'body'                     => '身體',
         'city'                     => '城市',
+        'company'                  => 'company',
+        'compilation'              => '彙編',
+        'concept'                  => '概念',
+        'conditions'               => '狀況',
         'content'                  => '內容',
+        'contest'                  => 'contest',
         'country'                  => '國家',
+        'cover'                    => '覆蓋',
         'created_at'               => '創建於',
         'creator'                  => '創造者',
         'currency'                 => '貨幣',
@@ -166,25 +175,39 @@ return [
         'customer'                 => '顧客',
         'date'                     => '日期',
         'date_of_birth'            => '出生日期',
+        'dates'                    => '日期',
         'day'                      => '天',
         'deleted_at'               => '刪除於',
         'description'              => '描述',
+        'display_type'             => '顯示類型',
         'district'                 => '區',
         'duration'                 => '期間',
         'email'                    => 'e-mail',
         'excerpt'                  => '摘要',
         'filter'                   => '篩選',
+        'finished_at'              => '完成於',
         'first_name'               => '名',
         'gender'                   => '性別',
+        'grand_prize'              => '大獎',
         'group'                    => '團體',
         'hour'                     => '時',
         'image'                    => '圖片',
+        'image_desktop'            => '桌面影像',
+        'image_main'               => '主圖',
+        'image_mobile'             => '移動影像',
+        'images'                   => '圖片',
+        'is_audience_winner'       => '是觀眾贏家',
+        'is_hidden'                => '被隱藏',
         'is_subscribed'            => '已訂閱',
+        'is_visible'               => '是可見的',
+        'is_winner'                => '是贏家',
         'items'                    => '專案',
+        'key'                      => '鑰匙',
         'last_name'                => '姓',
         'lesson'                   => '課',
         'line_address_1'           => '行地址 1',
         'line_address_2'           => '行地址 2',
+        'login'                    => '登入',
         'message'                  => '信息',
         'middle_name'              => '中間名字',
         'minute'                   => '分',
@@ -197,6 +220,7 @@ return [
         'password_confirmation'    => '確認密碼',
         'phone'                    => '電話',
         'photo'                    => '照片',
+        'portfolio'                => '資料夾',
         'postal_code'              => '郵政編碼',
         'preview'                  => '預覽',
         'price'                    => '價格',
@@ -206,20 +230,33 @@ return [
         'promo_code'               => '促銷代碼',
         'province'                 => '省',
         'quantity'                 => '數量',
+        'reason'                   => '原因',
         'recaptcha_response_field' => '重新驗證響應字段',
+        'referee'                  => '裁判',
+        'referees'                 => '裁判員',
+        'reject_reason'            => '拒絕理由',
         'remember'                 => '記住',
         'restored_at'              => '恢復於',
         'result_text_under_image'  => '圖片下方的結果文本',
         'role'                     => '角色',
+        'rule'                     => '規則',
+        'rules'                    => '規則',
         'second'                   => '秒',
         'sex'                      => '性別',
         'shipment'                 => '運輸',
         'short_text'               => '短文',
         'size'                     => '大小',
+        'skills'                   => '技能',
+        'slug'                     => '蛞蝓',
+        'specialization'           => '專業化',
+        'started_at'               => '開始於',
         'state'                    => '狀態',
+        'status'                   => '地位',
         'street'                   => '街道',
         'student'                  => '學生',
         'subject'                  => '主題',
+        'tag'                      => '標籤',
+        'tags'                     => '標籤',
         'teacher'                  => '老師',
         'terms'                    => '條款',
         'test_description'         => '測試說明',
@@ -228,9 +265,13 @@ return [
         'text'                     => '文本',
         'time'                     => '時間',
         'title'                    => '標題',
+        'type'                     => '類型',
         'updated_at'               => '更新於',
         'user'                     => '使用者',
         'username'                 => '使用者名稱',
+        'value'                    => '價值',
+        'winner'                   => 'winner',
+        'work'                     => 'work',
         'year'                     => '年',
     ],
 ];

Fichier diff supprimé car celui-ci est trop grand
+ 7 - 0
public/vendor/telescope/app-dark.css


Fichier diff supprimé car celui-ci est trop grand
+ 6 - 0
public/vendor/telescope/app.css


Fichier diff supprimé car celui-ci est trop grand
+ 1 - 0
public/vendor/telescope/app.js


BIN
public/vendor/telescope/favicon.ico


+ 5 - 0
public/vendor/telescope/mix-manifest.json

@@ -0,0 +1,5 @@
+{
+    "/app.js": "/app.js?id=99f84d421ae083196e0a45c3c310168b",
+    "/app-dark.css": "/app-dark.css?id=1ea407db56c5163ae29311f1f38eb7b9",
+    "/app.css": "/app.css?id=de4c978567bfd90b38d186937dee5ccf"
+}

+ 4 - 0
routes/api.php

@@ -200,6 +200,10 @@ Route::middleware(['auth:sanctum','account.limit'])->group(function () {
             ->name("project.4s");
         Route::get("project-iot", [API\ProjectController::class, "iot"])
             ->name("project.iot");
+        Route::get("project-iot/{siteName}/{deviceNumber}", [API\ProjectController::class, "fetchDeviceObjects"])
+            ->name("project.fetchDeviceObjects");
+        Route::get("project-iot/objects-values/{siteName}/{dataKey}", [API\ProjectController::class, "fetchObjectsValueMulti"])
+            ->name("project.fetchObjectsValueMulti");
 
 //        Route::get("project/{project}/not-link-asset-requirement", [API\ProjectController::class, "notLinkAssetRequirement"])
 //            ->name("project.not-link-asset-requirement"); //项目未关联的资产需求

Certains fichiers n'ont pas été affichés car il y a eu trop de fichiers modifiés dans ce diff