前言
此專案目的是實做一個實驗性質的、可雙向溝通的翻譯管理系統,目的是讓使用者可以從後台直接修改翻譯文案,並線上更新專案的語系資源。
流程
為了讓客戶端的語系資源被更新,服務端不會直接將資料發送給客戶端。而是透過 Webhook 的機制,送出一個通知給客戶端,讓客戶端主動獲取資源。流程如下:
- 服務端向客戶端發送請求,希望客戶端執行某些「事件」。
- 客戶端接收服務端請求,根據這些「事件」所定義的行為,向服務端發起請求。
- 服務端接收客戶端請求,回傳語系資源。
- 客戶端接收語系資源,產生語系檔案。
使用 Webhook 的好處是,客戶端只是被通知要做什麼,仍然保有主動權向服務端獲取資源。
專案架構
分為 5 個部分:
- lexicon-server:服務端後端
- lexicon-client:服務端前端
- lexicon-api-laravel-client:客戶端 Laravel 套件
- lexicon-api-php-client:客戶端 PHP 套件
- lexicon-demo:客戶端
1 2 3 4 5 6 7 8 9
| |----------------------|-----------|------------------------------------| | lexicon-server | | lexicon-demo | | |----------------| | | |------------------------------| | | | lexicon-client | |-----------| | lexicon-api-laravel-client | | | |----------------| | Webhook | | |------------------------| | | | |-----------| | | lexicon-api-php-client | | | | | | | |------------------------| | | | | | |------------------------------| | |----------------------|-----------|------------------------------------|
|
資料模型
主要模型有:
- User:使用者
- Team:團隊
- Project:專案
- Language:語言
- Form:語言型態
- Key:翻譯鍵
- Value:翻譯值
- Setting:設定
- Hook:客戶端 Webwook 網址
核心
發送事件
服務端的 DispatchController
控制器用於將事件發送給客戶端。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| namespace App\Http\Controllers\Api\Project;
use App\Http\Controllers\Controller; use App\Http\Requests\Project\ProjectDispatchRequest; use App\Models\Hook; use App\Models\Project; use App\Services\ProjectService; use Illuminate\Http\JsonResponse; use Illuminate\Support\Facades\Http; use Symfony\Component\HttpFoundation\Response;
class DispatchController extends Controller {
private ProjectService $projectService;
public function __construct( ProjectService $projectService ) { $this->projectService = $projectService; }
public function __invoke(ProjectDispatchRequest $request) { $project = $request->user();
$project->hooks->each(function ( $hook) use ($request) { Http::retry(3, 500) ->withHeaders([ 'Authorization' => sprintf('Bearer %s', $request->bearerToken()) ]) ->post($hook->url, [ 'events' => $request->input('events'), ]) ->throw(); });
return response()->json(null, Response::HTTP_ACCEPTED); } }
|
提供資源
客戶端接收到通知後,會使用 Lexicon 客戶端套件向服務端獲取資源,而 ProjectController
控制器會提供專案的所有翻譯鍵和翻譯值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| namespace App\Http\Controllers\Api\Project;
use App\Http\Controllers\Controller; use App\Http\Requests\Project\ProjectShowRequest; use App\Http\Resources\Project\ProjectResource as Resource; use App\Services\ProjectService;
class ProjectController extends Controller {
private ProjectService $projectService;
public function __construct( ProjectService $projectService ) { $this->projectService = $projectService; }
public function show(ProjectShowRequest $request) { $project = $this->projectService->get( $request->user(), $request, $request->input('cached', false) );
return new Resource($project); } }
|
程式碼