From e1b06731c417a9328f36b2d77fc653be0335e9db Mon Sep 17 00:00:00 2001 From: Seth Phat Date: Mon, 18 Sep 2023 09:24:03 +0700 Subject: [PATCH] DocKing's Localization (#25) * Migration * Models * Factory * New menu and fix bug * Awesome FE * language APIz * translationGroups APIz * translations APIz * translations APIz * Language Test * Translation Group Tests * Added tests * Languages Console UI * Languages Console UI * Translation Group Console UI * Create Translation UI * Create Translation UI * Update Translation UI * Update Translation UI * new metadata language * pivot for template and translation group * pivot for template and translation group * language renderer * Translations tests * UI fix * reverted changes --- app/Http/Controllers/LanguageController.php | 56 +++++ .../Controllers/TranslationController.php | 67 ++++++ .../TranslationGroupController.php | 61 +++++ .../Requests/DocumentTemplateStoreRequest.php | 2 + .../DocumentTemplateUpdateRequest.php | 2 + app/Http/Requests/LanguageIndexRequest.php | 23 ++ app/Http/Requests/LanguageStoreRequest.php | 22 ++ app/Http/Requests/LanguageUpdateRequest.php | 17 ++ app/Http/Requests/PdfRenderRequest.php | 6 + .../Requests/TranslationGroupIndexRequest.php | 23 ++ .../Requests/TranslationGroupStoreRequest.php | 23 ++ .../TranslationGroupUpdateRequest.php | 18 ++ app/Http/Requests/TranslationIndexRequest.php | 23 ++ app/Http/Requests/TranslationStoreRequest.php | 32 +++ .../Requests/TranslationUpdateRequest.php | 40 ++++ app/Http/Resources/LanguageResource.php | 21 ++ .../Resources/TranslationGroupResource.php | 23 ++ app/Http/Resources/TranslationResource.php | 29 +++ app/Models/DocumentTemplate.php | 3 - app/Models/Language.php | 22 ++ app/Models/Translation.php | 33 +++ app/Models/TranslationGroup.php | 29 +++ app/Providers/AppServiceProvider.php | 12 + app/Providers/RouteServiceProvider.php | 6 + app/Rules/TranslationTextRule.php | 29 +++ app/Services/PdfRenderManager.php | 4 + app/Services/Translations/DatabaseLoader.php | 40 ++++ database/factories/LanguageFactory.php | 21 ++ database/factories/TranslationFactory.php | 22 ++ .../factories/TranslationGroupFactory.php | 20 ++ ...23_09_16_065108_create_languages_table.php | 24 ++ ...065110_create_translation_groups_table.php | 25 ++ ...09_16_065119_create_translations_table.php | 26 +++ ..._071311_create_english_language_record.php | 32 +++ resources/js/console/App.vue | 106 +++++---- .../console/components/Dropdown/Dropdown.vue | 8 +- .../js/console/components/Input/Input.vue | 4 +- .../console/composable/useNavigationItems.js | 66 +++++- .../repositories/language.repository.js | 47 ++++ .../repositories/translation.repository.js | 53 +++++ .../translationGroup.repository.js | 53 +++++ resources/js/console/router.js | 20 ++ .../DocumentTemplateEdit.vue | 7 +- .../components/Settings.vue | 25 +- .../LanguagesList/LanguaguesListScreen.vue | 71 ++++++ .../components/CreateNewLanguage.vue | 96 ++++++++ .../components/DeleteLanguageButton.vue | 83 +++++++ .../components/UpdateLanguageButton.vue | 103 +++++++++ .../TranslationGroupsListScreen.vue | 94 ++++++++ .../components/CreateNewTranslationGroup.vue | 102 ++++++++ .../DeleteTranslationGroupButton.vue | 85 +++++++ .../UpdateTranslationGroupButton.vue | 113 +++++++++ .../TranslationsListScreen.vue | 134 +++++++++++ .../components/CreateNewTranslation.vue | 164 +++++++++++++ .../components/DeleteTranslationButton.vue | 83 +++++++ .../components/UpdateTranslationButton.vue | 175 ++++++++++++++ routes/api.php | 21 ++ tests/Feature/LanguageControllerTest.php | 123 ++++++++++ tests/Feature/TranslationControllerTest.php | 218 ++++++++++++++++++ .../TranslationGroupControllerTest.php | 135 +++++++++++ tests/Unit/Models/TranslationGroupTest.php | 29 +++ .../BladeTemplatingServiceTest.php | 72 +++++- 62 files changed, 3056 insertions(+), 70 deletions(-) create mode 100644 app/Http/Controllers/LanguageController.php create mode 100644 app/Http/Controllers/TranslationController.php create mode 100644 app/Http/Controllers/TranslationGroupController.php create mode 100644 app/Http/Requests/LanguageIndexRequest.php create mode 100644 app/Http/Requests/LanguageStoreRequest.php create mode 100644 app/Http/Requests/LanguageUpdateRequest.php create mode 100644 app/Http/Requests/TranslationGroupIndexRequest.php create mode 100644 app/Http/Requests/TranslationGroupStoreRequest.php create mode 100644 app/Http/Requests/TranslationGroupUpdateRequest.php create mode 100644 app/Http/Requests/TranslationIndexRequest.php create mode 100644 app/Http/Requests/TranslationStoreRequest.php create mode 100644 app/Http/Requests/TranslationUpdateRequest.php create mode 100644 app/Http/Resources/LanguageResource.php create mode 100644 app/Http/Resources/TranslationGroupResource.php create mode 100644 app/Http/Resources/TranslationResource.php create mode 100644 app/Models/Language.php create mode 100644 app/Models/Translation.php create mode 100644 app/Models/TranslationGroup.php create mode 100644 app/Rules/TranslationTextRule.php create mode 100644 app/Services/Translations/DatabaseLoader.php create mode 100644 database/factories/LanguageFactory.php create mode 100644 database/factories/TranslationFactory.php create mode 100644 database/factories/TranslationGroupFactory.php create mode 100644 database/migrations/2023_09_16_065108_create_languages_table.php create mode 100644 database/migrations/2023_09_16_065110_create_translation_groups_table.php create mode 100644 database/migrations/2023_09_16_065119_create_translations_table.php create mode 100644 database/migrations/2023_09_17_071311_create_english_language_record.php create mode 100644 resources/js/console/repositories/language.repository.js create mode 100644 resources/js/console/repositories/translation.repository.js create mode 100644 resources/js/console/repositories/translationGroup.repository.js create mode 100644 resources/js/console/screens/LanguagesList/LanguaguesListScreen.vue create mode 100644 resources/js/console/screens/LanguagesList/components/CreateNewLanguage.vue create mode 100644 resources/js/console/screens/LanguagesList/components/DeleteLanguageButton.vue create mode 100644 resources/js/console/screens/LanguagesList/components/UpdateLanguageButton.vue create mode 100644 resources/js/console/screens/TranslationGroupsList/TranslationGroupsListScreen.vue create mode 100644 resources/js/console/screens/TranslationGroupsList/components/CreateNewTranslationGroup.vue create mode 100644 resources/js/console/screens/TranslationGroupsList/components/DeleteTranslationGroupButton.vue create mode 100644 resources/js/console/screens/TranslationGroupsList/components/UpdateTranslationGroupButton.vue create mode 100644 resources/js/console/screens/TranslationsList/TranslationsListScreen.vue create mode 100644 resources/js/console/screens/TranslationsList/components/CreateNewTranslation.vue create mode 100644 resources/js/console/screens/TranslationsList/components/DeleteTranslationButton.vue create mode 100644 resources/js/console/screens/TranslationsList/components/UpdateTranslationButton.vue create mode 100644 tests/Feature/LanguageControllerTest.php create mode 100644 tests/Feature/TranslationControllerTest.php create mode 100644 tests/Feature/TranslationGroupControllerTest.php create mode 100644 tests/Unit/Models/TranslationGroupTest.php diff --git a/app/Http/Controllers/LanguageController.php b/app/Http/Controllers/LanguageController.php new file mode 100644 index 0000000..e2a55d1 --- /dev/null +++ b/app/Http/Controllers/LanguageController.php @@ -0,0 +1,56 @@ +buildQueryBuilder() + ->get(); + + return LanguageResource::collection($fonts)->response(); + } + + public function show(Language $language): JsonResponse + { + return LanguageResource::make($language)->response(); + } + + public function store(LanguageStoreRequest $request): JsonResponse + { + $language = Language::create($request->validated()); + + return new JsonResponse([ + 'uuid' => $language->uuid, + 'created' => $language->wasRecentlyCreated, + ]); + } + + public function update(LanguageUpdateRequest $request, Language $language): JsonResponse + { + $updateStatus = $language->update($request->validated()); + + return new JsonResponse([ + 'uuid' => $language->uuid, + 'updated' => $updateStatus, + ]); + } + + public function destroy(Language $language): JsonResponse + { + $deleteResult = $language->delete(); + + return new JsonResponse([ + 'uuid' => $language->uuid, + 'deleted' => $deleteResult, + ]); + } +} diff --git a/app/Http/Controllers/TranslationController.php b/app/Http/Controllers/TranslationController.php new file mode 100644 index 0000000..0a6f88c --- /dev/null +++ b/app/Http/Controllers/TranslationController.php @@ -0,0 +1,67 @@ +buildQueryBuilder() + ->with(['translationGroup']) + ->paginate(); + + return TranslationResource::collection($translations)->response(); + } + + public function show(Translation $translation): JsonResponse + { + return TranslationResource::make($translation)->response(); + } + + public function store(TranslationStoreRequest $request): JsonResponse + { + $translationGroup = TranslationGroup::find($request->validated('translation_group_id')); + $translation = Translation::create([ + ...$request->validated(), + 'key' => "{$translationGroup->key}.{$request->input('key')}", + ]); + + return new JsonResponse([ + 'uuid' => $translation->uuid, + 'created' => $translation->wasRecentlyCreated, + ]); + } + + public function update(TranslationUpdateRequest $request, Translation $translation): JsonResponse + { + $translationGroup = TranslationGroup::find($request->validated('translation_group_id')); + + $updateStatus = $translation->update([ + ...$request->validated(), + 'key' => "{$translationGroup->key}.{$request->input('key')}", + ]); + + return new JsonResponse([ + 'uuid' => $translation->uuid, + 'updated' => $updateStatus, + ]); + } + + public function destroy(Translation $translation): JsonResponse + { + $deleteResult = $translation->delete(); + + return new JsonResponse([ + 'uuid' => $translation->uuid, + 'deleted' => $deleteResult, + ]); + } +} diff --git a/app/Http/Controllers/TranslationGroupController.php b/app/Http/Controllers/TranslationGroupController.php new file mode 100644 index 0000000..947e617 --- /dev/null +++ b/app/Http/Controllers/TranslationGroupController.php @@ -0,0 +1,61 @@ +buildQueryBuilder() + ->paginate(); + + return TranslationGroupResource::collection($translationGroups)->response(); + } + + public function show(TranslationGroup $translationGroup): JsonResponse + { + return TranslationGroupResource::make($translationGroup)->response(); + } + + public function store(TranslationGroupStoreRequest $request): JsonResponse + { + $translationGroup = TranslationGroup::create($request->validated()); + + return new JsonResponse([ + 'uuid' => $translationGroup->uuid, + 'created' => $translationGroup->wasRecentlyCreated, + ]); + } + + public function update(TranslationGroupUpdateRequest $request, TranslationGroup $translationGroup): JsonResponse + { + $updateStatus = $translationGroup->update($request->validated()); + + return new JsonResponse([ + 'uuid' => $translationGroup->uuid, + 'updated' => $updateStatus, + ]); + } + + public function destroy(TranslationGroup $translationGroup): JsonResponse + { + $deleteResult = DB::transaction(function () use ($translationGroup) { + $translationGroup->translations()->delete(); + + return $translationGroup->delete(); + }); + + return new JsonResponse([ + 'uuid' => $translationGroup->uuid, + 'deleted' => $deleteResult, + ]); + } +} diff --git a/app/Http/Requests/DocumentTemplateStoreRequest.php b/app/Http/Requests/DocumentTemplateStoreRequest.php index a8c5c74..40c60fe 100644 --- a/app/Http/Requests/DocumentTemplateStoreRequest.php +++ b/app/Http/Requests/DocumentTemplateStoreRequest.php @@ -19,6 +19,8 @@ public function rules(): array ], 'title' => 'required|string', 'category' => 'required|string', + 'translation_groups' => 'nullable|array', + 'translation_groups.*' => 'uuid|exists:translation_groups,uuid', ]; } } diff --git a/app/Http/Requests/DocumentTemplateUpdateRequest.php b/app/Http/Requests/DocumentTemplateUpdateRequest.php index 5f531dd..adfc72b 100644 --- a/app/Http/Requests/DocumentTemplateUpdateRequest.php +++ b/app/Http/Requests/DocumentTemplateUpdateRequest.php @@ -16,6 +16,8 @@ public function rules(): array 'template' => 'required|string', 'default_variables' => 'required|array', 'metadata' => 'required|array', + 'translation_groups' => 'nullable|array', + 'translation_groups.*' => 'uuid|exists:translation_groups,uuid', ]; } } diff --git a/app/Http/Requests/LanguageIndexRequest.php b/app/Http/Requests/LanguageIndexRequest.php new file mode 100644 index 0000000..1803aa1 --- /dev/null +++ b/app/Http/Requests/LanguageIndexRequest.php @@ -0,0 +1,23 @@ + [ + 'required', + 'string', + Rule::unique((new Language())->getTable()), + ], + 'name' => 'required|string', + ]; + } +} diff --git a/app/Http/Requests/LanguageUpdateRequest.php b/app/Http/Requests/LanguageUpdateRequest.php new file mode 100644 index 0000000..090cd25 --- /dev/null +++ b/app/Http/Requests/LanguageUpdateRequest.php @@ -0,0 +1,17 @@ + 'required|string', + ]; + } +} diff --git a/app/Http/Requests/PdfRenderRequest.php b/app/Http/Requests/PdfRenderRequest.php index 7726c50..8c3e9cb 100644 --- a/app/Http/Requests/PdfRenderRequest.php +++ b/app/Http/Requests/PdfRenderRequest.php @@ -3,7 +3,9 @@ namespace App\Http\Requests; use App\Enums\PdfService; +use App\Models\Language; use Illuminate\Foundation\Http\FormRequest; +use Illuminate\Validation\Rule; class PdfRenderRequest extends FormRequest { @@ -16,6 +18,10 @@ public function rules(): array 'nullable', PdfService::getRequestRule(), ], + 'metadata.language' => [ + 'nullable', + Rule::in(Language::pluck('code')), + ], ]; } diff --git a/app/Http/Requests/TranslationGroupIndexRequest.php b/app/Http/Requests/TranslationGroupIndexRequest.php new file mode 100644 index 0000000..e51acfa --- /dev/null +++ b/app/Http/Requests/TranslationGroupIndexRequest.php @@ -0,0 +1,23 @@ + [ + 'required', + 'string', + Rule::unique((new TranslationGroup())->getTable()), + ], + 'name' => 'required|string', + 'description' => 'nullable|string', + ]; + } +} diff --git a/app/Http/Requests/TranslationGroupUpdateRequest.php b/app/Http/Requests/TranslationGroupUpdateRequest.php new file mode 100644 index 0000000..0faf219 --- /dev/null +++ b/app/Http/Requests/TranslationGroupUpdateRequest.php @@ -0,0 +1,18 @@ + 'required|string', + 'description' => 'nullable|string', + ]; + } +} diff --git a/app/Http/Requests/TranslationIndexRequest.php b/app/Http/Requests/TranslationIndexRequest.php new file mode 100644 index 0000000..4e67c1f --- /dev/null +++ b/app/Http/Requests/TranslationIndexRequest.php @@ -0,0 +1,23 @@ + [ + 'required', + 'string', + Rule::unique((new Translation())->getTable()), + ], + 'translation_group_id' => [ + 'required', + 'exists:translation_groups,uuid', + ], + 'name' => 'required|string', + 'text' => [ + 'required', + 'array', + new TranslationTextRule(), + ], + ]; + } +} diff --git a/app/Http/Requests/TranslationUpdateRequest.php b/app/Http/Requests/TranslationUpdateRequest.php new file mode 100644 index 0000000..cbda147 --- /dev/null +++ b/app/Http/Requests/TranslationUpdateRequest.php @@ -0,0 +1,40 @@ +route('translation'); + + return [ + 'key' => array_values(array_filter([ + 'required', + 'string', + $currentTranslation->key !== $this->input('key') + ? Rule::unique((new Translation())->getTable()) + : null, + ])), + 'translation_group_id' => [ + 'required', + 'exists:translation_groups,uuid', + ], + 'name' => 'required|string', + 'description' => 'nullable|string', + 'text' => [ + 'required', + 'array', + new TranslationTextRule(), + ], + ]; + } +} diff --git a/app/Http/Resources/LanguageResource.php b/app/Http/Resources/LanguageResource.php new file mode 100644 index 0000000..8a519c9 --- /dev/null +++ b/app/Http/Resources/LanguageResource.php @@ -0,0 +1,21 @@ + $this->uuid, + 'code' => $this->code, + 'name' => $this->name, + 'created_at' => $this->created_at?->toISOString(), + ]; + } +} diff --git a/app/Http/Resources/TranslationGroupResource.php b/app/Http/Resources/TranslationGroupResource.php new file mode 100644 index 0000000..bba0fe9 --- /dev/null +++ b/app/Http/Resources/TranslationGroupResource.php @@ -0,0 +1,23 @@ + $this->uuid, + 'key' => $this->key, + 'name' => $this->name, + 'description' => $this->description, + 'created_at' => $this->created_at?->toISOString(), + 'updated_at' => $this->created_at?->toISOString(), + ]; + } +} diff --git a/app/Http/Resources/TranslationResource.php b/app/Http/Resources/TranslationResource.php new file mode 100644 index 0000000..e30f586 --- /dev/null +++ b/app/Http/Resources/TranslationResource.php @@ -0,0 +1,29 @@ + $this->uuid, + 'key' => $this->key, + 'name' => $this->name, + 'text' => $this->text, + 'created_at' => $this->created_at?->toISOString(), + 'updated_at' => $this->created_at?->toISOString(), + + 'translation_group' => self::whenLoaded( + 'translationGroup', + fn () => TranslationGroupResource::make($this->translationGroup), + ), + ]; + } +} diff --git a/app/Models/DocumentTemplate.php b/app/Models/DocumentTemplate.php index e9c66ed..49a0fbd 100644 --- a/app/Models/DocumentTemplate.php +++ b/app/Models/DocumentTemplate.php @@ -8,9 +8,6 @@ use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\SoftDeletes; -use Illuminate\Support\Facades\Blade; -use Illuminate\Support\Str; -use Throwable; class DocumentTemplate extends Model { diff --git a/app/Models/Language.php b/app/Models/Language.php new file mode 100644 index 0000000..65dc544 --- /dev/null +++ b/app/Models/Language.php @@ -0,0 +1,22 @@ + 'array', + ]; + + public function translationGroup(): BelongsTo + { + return $this->belongsTo(TranslationGroup::class, 'translation_group_id'); + } +} diff --git a/app/Models/TranslationGroup.php b/app/Models/TranslationGroup.php new file mode 100644 index 0000000..c0a821e --- /dev/null +++ b/app/Models/TranslationGroup.php @@ -0,0 +1,29 @@ +hasMany(Translation::class, 'translation_group_id'); + } +} diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 423eada..4bbe585 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -8,10 +8,13 @@ use App\Services\TemplatingServices\BladeTemplatingService; use App\Services\TemplatingServices\MarkdownTemplatingService; use App\Services\TemplatingServices\TemplatingServiceContract; +use App\Services\Translations\DatabaseLoader; use Illuminate\Support\ServiceProvider; use App\Services\PdfRenderers\GotenbergRendererService; use App\Services\PdfRenderers\MpdfRendererService; use App\Services\PdfRenderers\WkHtmlToPdfRendererService; +use Illuminate\Translation\FileLoader; +use Illuminate\Translation\Translator; use Mpdf\Mpdf; class AppServiceProvider extends ServiceProvider @@ -40,6 +43,7 @@ public function register(): void $this->app->bind('mpdf-testing', Mpdf::class); $this->bindTemplatingServices(); + $this->bindLocalizationService(); } private function bindTemplatingServices(): void @@ -47,4 +51,12 @@ private function bindTemplatingServices(): void $this->app->singleton(BladeTemplatingService::class); $this->app->singleton(MarkdownTemplatingService::class); } + + private function bindLocalizationService(): void + { + $this->app->extend( + 'translation.loader', + fn () => new DatabaseLoader() + ); + } } diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php index c8cc8f5..da32fca 100644 --- a/app/Providers/RouteServiceProvider.php +++ b/app/Providers/RouteServiceProvider.php @@ -5,6 +5,9 @@ use App\Models\DocumentFile; use App\Models\DocumentTemplate; use App\Models\Font; +use App\Models\Language; +use App\Models\Translation; +use App\Models\TranslationGroup; use Illuminate\Cache\RateLimiting\Limit; use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider; use Illuminate\Http\Request; @@ -52,6 +55,9 @@ private function registerModelBindings(): void { Route::model('documentFile', DocumentFile::class); Route::model('font', Font::class); + Route::model('language', Language::class); + Route::model('translationGroup', TranslationGroup::class); + Route::model('translation', Translation::class); Route::bind('documentTemplateUuidKey', DocumentTemplate::getByUuidOrKey(...)); } diff --git a/app/Rules/TranslationTextRule.php b/app/Rules/TranslationTextRule.php new file mode 100644 index 0000000..f4c7ef4 --- /dev/null +++ b/app/Rules/TranslationTextRule.php @@ -0,0 +1,29 @@ +toArray(); + + $clientLangCodes = array_keys($value); + + $isOk = empty(array_diff($allLanguageCodes, $clientLangCodes)); + + if (!$isOk) { + $fail('Missing language codes in the object. Required langCodes: ' . implode(', ', $allLanguageCodes)); + } + + foreach ($value as $langCode => $langText) { + if (empty($langText)) { + $fail(sprintf('Missing text for language: %s', $langCode)); + } + } + } +} diff --git a/app/Services/PdfRenderManager.php b/app/Services/PdfRenderManager.php index 360a718..da25a57 100644 --- a/app/Services/PdfRenderManager.php +++ b/app/Services/PdfRenderManager.php @@ -30,6 +30,10 @@ public function render( array $variables = [], array $metadata = [] ): PdfRenderResult { + if (isset($metadata['language'])) { + app()->setLocale($metadata['language']); + } + return $this->getDriver($metadata['driver'] ?? null) ->render($template, $variables, $metadata); } diff --git a/app/Services/Translations/DatabaseLoader.php b/app/Services/Translations/DatabaseLoader.php new file mode 100644 index 0000000..079ef24 --- /dev/null +++ b/app/Services/Translations/DatabaseLoader.php @@ -0,0 +1,40 @@ +first(); + if (!$translationGroup) { + return []; + } + + if (is_null($namespace) || $namespace === '*') { + return $this->loadAllTranslationsFromGroup($translationGroup, $locale); + } + + return []; + } + + protected function loadAllTranslationsFromGroup(TranslationGroup $translationGroup, string $locale): array + { + return $translationGroup->translations->mapWithKeys(function (Translation $translation) use ($locale, $translationGroup) { + $keyWithoutGroup = str_replace("{$translationGroup->key}.", '', $translation->key); + + return [ + $keyWithoutGroup => $translation->text[$locale] ?? '', + ]; + })->toArray(); + } +} diff --git a/database/factories/LanguageFactory.php b/database/factories/LanguageFactory.php new file mode 100644 index 0000000..26a61e6 --- /dev/null +++ b/database/factories/LanguageFactory.php @@ -0,0 +1,21 @@ +languageCode(); + + return [ + 'code' => $langCode, + 'name' => ucfirst($langCode), + ]; + } +} diff --git a/database/factories/TranslationFactory.php b/database/factories/TranslationFactory.php new file mode 100644 index 0000000..212e905 --- /dev/null +++ b/database/factories/TranslationFactory.php @@ -0,0 +1,22 @@ + fn () => TranslationGroup::factory()->create(), + 'key' => fake()->sentence(5), + 'name' => fake()->sentence(5), + 'text' => [], + ]; + } +} diff --git a/database/factories/TranslationGroupFactory.php b/database/factories/TranslationGroupFactory.php new file mode 100644 index 0000000..dfab45d --- /dev/null +++ b/database/factories/TranslationGroupFactory.php @@ -0,0 +1,20 @@ + fake()->sentence(5), + 'name' => fake()->sentence(5), + 'description' => fake()->realText(50), + ]; + } +} diff --git a/database/migrations/2023_09_16_065108_create_languages_table.php b/database/migrations/2023_09_16_065108_create_languages_table.php new file mode 100644 index 0000000..97921bf --- /dev/null +++ b/database/migrations/2023_09_16_065108_create_languages_table.php @@ -0,0 +1,24 @@ +uuid()->primary(); + + $table->string('code')->unique(); + $table->string('name'); + + $table->timestamps(); + }); + } + + public function down(): void + { + Schema::dropIfExists('languages'); + } +}; diff --git a/database/migrations/2023_09_16_065110_create_translation_groups_table.php b/database/migrations/2023_09_16_065110_create_translation_groups_table.php new file mode 100644 index 0000000..d5bc067 --- /dev/null +++ b/database/migrations/2023_09_16_065110_create_translation_groups_table.php @@ -0,0 +1,25 @@ +uuid()->primary(); + + $table->string('key')->unique(); + $table->string('name'); + $table->string('description')->nullable(); + + $table->timestamps(); + }); + } + + public function down(): void + { + Schema::dropIfExists('translation_groups'); + } +}; diff --git a/database/migrations/2023_09_16_065119_create_translations_table.php b/database/migrations/2023_09_16_065119_create_translations_table.php new file mode 100644 index 0000000..5d6d2e4 --- /dev/null +++ b/database/migrations/2023_09_16_065119_create_translations_table.php @@ -0,0 +1,26 @@ +uuid()->primary(); + + $table->uuid('translation_group_id')->index(); + $table->string('key')->unique(); + $table->string('name'); + $table->jsonb('text'); + + $table->timestamps(); + }); + } + + public function down(): void + { + Schema::dropIfExists('translations'); + } +}; diff --git a/database/migrations/2023_09_17_071311_create_english_language_record.php b/database/migrations/2023_09_17_071311_create_english_language_record.php new file mode 100644 index 0000000..4bcbde3 --- /dev/null +++ b/database/migrations/2023_09_17_071311_create_english_language_record.php @@ -0,0 +1,32 @@ +runningUnitTests()) { + return; + } + + DB::table('languages') + ->insertOrIgnore([ + 'uuid' => Str::orderedUuid()->toString(), + 'code' => 'en', + 'name' => 'English', + ]); + } + + public function down(): void + { + if (app()->runningUnitTests()) { + return; + } + + DB::table('languages') + ->where('code', 'en') + ->delete(); + } +}; diff --git a/resources/js/console/App.vue b/resources/js/console/App.vue index 61fa836..644cc41 100644 --- a/resources/js/console/App.vue +++ b/resources/js/console/App.vue @@ -108,43 +108,6 @@ -
  • -
    - Your teams -
    - -
  • {{ item.name }} + + + + +
  • + + +
  • + + @@ -283,8 +304,9 @@ + DocKing User +