Skip to content

Commit

Permalink
Form Translation (#616)
Browse files Browse the repository at this point in the history
* Form Translation

* Support for other languages

* Support locale for datepicker

* Apply translation on select input

* Apply translation on select input

* Improve translation

---------

Co-authored-by: Julien Nahum <[email protected]>
  • Loading branch information
chiragchhatrala and JhumanJ authored Dec 4, 2024
1 parent c927a23 commit daca692
Show file tree
Hide file tree
Showing 36 changed files with 1,589 additions and 32 deletions.
6 changes: 6 additions & 0 deletions api/app/Http/Requests/AnswerFormRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,12 @@ private function getSelectPropertyOptions($property): array

protected function prepareForValidation()
{
// Set locale based on form language
if ($this->form?->language && in_array($this->form->language, Form::LANGUAGES)) {
app()->setLocale($this->form->language);
}


$receivedData = $this->toArray();
$mergeData = [];
$countryCodeMapper = json_decode(file_get_contents(resource_path('data/country_code_mapper.json')), true);
Expand Down
1 change: 1 addition & 0 deletions api/app/Http/Requests/UserFormRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public function rules()
'visibility' => ['required', Rule::in(Form::VISIBILITY)],

// Customization
'language' => ['required', Rule::in(Form::LANGUAGES)],
'font_family' => 'string|nullable',
'theme' => ['required', Rule::in(Form::THEMES)],
'width' => ['required', Rule::in(Form::WIDTHS)],
Expand Down
1 change: 1 addition & 0 deletions api/app/Http/Resources/FormResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ private function getProtectedForm()
'dark_mode' => $this->dark_mode,
'transparent_background' => $this->transparent_background,
'color' => $this->color,
'language' => $this->language,
'theme' => $this->theme,
'is_password_protected' => true,
'has_password' => $this->has_password,
Expand Down
3 changes: 3 additions & 0 deletions api/app/Models/Forms/Form.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ class Form extends Model implements CachableAttributes

public const VISIBILITY = ['public', 'draft', 'closed'];

public const LANGUAGES = ['en', 'fr', 'hi', 'es', 'ar', 'zh', 'ja'];

protected $fillable = [
'workspace_id',
'creator_id',
Expand All @@ -52,6 +54,7 @@ class Form extends Model implements CachableAttributes
'visibility',

// Customization
'language',
'font_family',
'custom_domain',
'size',
Expand Down
6 changes: 6 additions & 0 deletions api/config/app.php
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,12 @@

'locales' => [
'en' => 'EN',
'fr' => 'FR',
'hi' => 'HI',
'es' => 'ES',
'ar' => 'AR',
'zh' => 'ZH',
'ja' => 'JA',
],

/*
Expand Down
1 change: 1 addition & 0 deletions api/database/factories/FormFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public function definition()
'title' => $this->faker->text(30),
'description' => $this->faker->randomHtml(1),
'visibility' => 'public',
'language' => 'en',
'theme' => $this->faker->randomElement(Form::THEMES),
'size' => $this->faker->randomElement(Form::SIZES),
'border_radius' => $this->faker->randomElement(Form::BORDER_RADIUS),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class () extends Migration {
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('forms', function (Blueprint $table) {
$table->string('language')->default('en');
});
}

/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('forms', function (Blueprint $table) {
$table->dropColumn('language');
});
}
};
117 changes: 117 additions & 0 deletions api/resources/lang/ar/validation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
<?php

return [
'accepted' => 'يجب قبول :attribute.',
'active_url' => ':attribute لا يُمثل رابطًا صحيحًا.',
'after' => 'يجب على :attribute أن يكون تاريخًا لاحقًا للتاريخ :date.',
'after_or_equal' => ':attribute يجب أن يكون تاريخاً لاحقاً أو مطابقاً للتاريخ :date.',
'alpha' => 'يجب أن لا يحتوي :attribute سوى على حروف.',
'alpha_dash' => 'يجب أن لا يحتوي :attribute سوى على حروف، أرقام ومطّات.',
'alpha_num' => 'يجب أن يحتوي :attribute على حروفٍ وأرقامٍ فقط.',
'array' => 'يجب أن يكون :attribute ًمصفوفة.',
'before' => 'يجب على :attribute أن يكون تاريخًا سابقًا للتاريخ :date.',
'before_or_equal' => ':attribute يجب أن يكون تاريخا سابقا أو مطابقا للتاريخ :date.',
'between' => [
'numeric' => 'يجب أن تكون قيمة :attribute بين :min و :max.',
'file' => 'يجب أن يكون حجم الملف :attribute بين :min و :max كيلوبايت.',
'string' => 'يجب أن يكون عدد حروف النّص :attribute بين :min و :max.',
'array' => 'يجب أن يحتوي :attribute على عدد من العناصر بين :min و :max.',
],
'boolean' => 'يجب أن تكون قيمة :attribute إما true أو false.',
'confirmed' => 'حقل التأكيد غير مُطابق للحقل :attribute.',
'date' => ':attribute ليس تاريخًا صحيحًا.',
'date_equals' => 'يجب أن يكون :attribute مطابقاً للتاريخ :date.',
'date_format' => 'لا يتوافق :attribute مع الشكل :format.',
'different' => 'يجب أن يكون الحقلان :attribute و :other مُختلفين.',
'digits' => 'يجب أن يحتوي :attribute على :digits رقمًا/أرقام.',
'digits_between' => 'يجب أن يحتوي :attribute بين :min و :max رقمًا/أرقام.',
'dimensions' => 'الـ :attribute يحتوي على أبعاد صورة غير صالحة.',
'distinct' => 'للحقل :attribute قيمة مُكرّرة.',
'email' => 'يجب أن يكون :attribute عنوان بريد إلكتروني صحيح البُنية.',
'ends_with' => 'يجب أن ينتهي :attribute بأحد القيم التالية: :values',
'exists' => 'القيمة المحددة :attribute غير موجودة.',
'file' => 'الـ :attribute يجب أن يكون ملفا.',
'filled' => ':attribute إجباري.',
'gt' => [
'numeric' => 'يجب أن تكون قيمة :attribute أكبر من :value.',
'file' => 'يجب أن يكون حجم الملف :attribute أكبر من :value كيلوبايت.',
'string' => 'يجب أن يكون طول النّص :attribute أكثر من :value حروفٍ/حرفًا.',
'array' => 'يجب أن يحتوي :attribute على أكثر من :value عناصر/عنصر.',
],
'gte' => [
'numeric' => 'يجب أن تكون قيمة :attribute مساوية أو أكبر من :value.',
'file' => 'يجب أن يكون حجم الملف :attribute على الأقل :value كيلوبايت.',
'string' => 'يجب أن يكون طول النص :attribute على الأقل :value حروفٍ/حرفًا.',
'array' => 'يجب أن يحتوي :attribute على الأقل على :value عُنصرًا/عناصر.',
],
'image' => 'يجب أن يكون :attribute صورةً.',
'in' => ':attribute غير موجود.',
'in_array' => ':attribute غير موجود في :other.',
'integer' => 'يجب أن يكون :attribute عددًا صحيحًا.',
'ip' => 'يجب أن يكون :attribute عنوان IP صحيحًا.',
'ipv4' => 'يجب أن يكون :attribute عنوان IPv4 صحيحًا.',
'ipv6' => 'يجب أن يكون :attribute عنوان IPv6 صحيحًا.',
'json' => 'يجب أن يكون :attribute نصًا من نوع JSON.',
'lt' => [
'numeric' => 'يجب أن تكون قيمة :attribute أصغر من :value.',
'file' => 'يجب أن يكون حجم الملف :attribute أصغر من :value كيلوبايت.',
'string' => 'يجب أن يكون طول النّص :attribute أقل من :value حروفٍ/حرفًا.',
'array' => 'يجب أن يحتوي :attribute على أقل من :value عناصر/عنصر.',
],
'lte' => [
'numeric' => 'يجب أن تكون قيمة :attribute مساوية أو أصغر من :value.',
'file' => 'يجب أن لا يتجاوز حجم الملف :attribute :value كيلوبايت.',
'string' => 'يجب أن لا يتجاوز طول النّص :attribute :value حروفٍ/حرفًا.',
'array' => 'يجب أن لا يحتوي :attribute على أكثر من :value عناصر/عنصر.',
],
'max' => [
'numeric' => 'يجب أن تكون قيمة :attribute مساوية أو أصغر من :max.',
'file' => 'يجب أن لا يتجاوز حجم الملف :attribute :max كيلوبايت.',
'string' => 'يجب أن لا يتجاوز طول النّص :attribute :max حروفٍ/حرفًا.',
'array' => 'يجب أن لا يحتوي :attribute على أكثر من :max عناصر/عنصر.',
],
'mimes' => 'يجب أن يكون ملفًا من نوع : :values.',
'mimetypes' => 'يجب أن يكون ملفًا من نوع : :values.',
'min' => [
'numeric' => 'يجب أن تكون قيمة :attribute مساوية أو أكبر من :min.',
'file' => 'يجب أن يكون حجم الملف :attribute على الأقل :min كيلوبايت.',
'string' => 'يجب أن يكون طول النص :attribute على الأقل :min حروفٍ/حرفًا.',
'array' => 'يجب أن يحتوي :attribute على الأقل على :min عُنصرًا/عناصر.',
],
'multiple_of' => ':attribute يجب أن يكون من مضاعفات :value',
'not_in' => 'العنصر :attribute غير صحيح.',
'not_regex' => 'صيغة :attribute غير صحيحة.',
'numeric' => 'يجب على :attribute أن يكون رقمًا.',
'password' => 'كلمة المرور غير صحيحة.',
'present' => 'يجب تقديم :attribute.',
'regex' => 'صيغة :attribute غير صحيحة.',
'required' => ':attribute مطلوب.',
'required_if' => ':attribute مطلوب في حال ما إذا كان :other يساوي :value.',
'required_unless' => ':attribute مطلوب في حال ما لم يكن :other يساوي :values.',
'required_with' => ':attribute مطلوب إذا توفّر :values.',
'required_with_all' => ':attribute مطلوب إذا توفّر :values.',
'required_without' => ':attribute مطلوب إذا لم يتوفّر :values.',
'required_without_all' => ':attribute مطلوب إذا لم يتوفّر :values.',
'same' => 'يجب أن يتطابق :attribute مع :other.',
'size' => [
'numeric' => 'يجب أن تكون قيمة :attribute مساوية لـ :size.',
'file' => 'يجب أن يكون حجم الملف :attribute :size كيلوبايت.',
'string' => 'يجب أن يحتوي النص :attribute على :size حروفٍ/حرفًا بالضبط.',
'array' => 'يجب أن يحتوي :attribute على :size عنصرٍ/عناصر بالضبط.',
],
'starts_with' => 'يجب أن يبدأ :attribute بأحد القيم التالية: :values',
'string' => 'يجب أن يكون :attribute نصًا.',
'timezone' => 'يجب أن يكون :attribute نطاقًا زمنيًا صحيحًا.',
'unique' => 'قيمة :attribute مُستخدمة من قبل.',
'uploaded' => 'فشل في تحميل الـ :attribute.',
'url' => 'صيغة الرابط :attribute غير صحيحة.',
'uuid' => ':attribute يجب أن يكون بصيغة UUID سليمة.',

'custom' => [
'attribute-name' => [
'rule-name' => 'رسالة-مخصصة',
],
],

'attributes' => [],
];
117 changes: 117 additions & 0 deletions api/resources/lang/fr/validation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
<?php

return [
'accepted' => 'Le champ :attribute doit être accepté.',
'active_url' => 'Le champ :attribute n\'est pas une URL valide.',
'after' => 'Le champ :attribute doit être une date postérieure au :date.',
'after_or_equal' => 'Le champ :attribute doit être une date postérieure ou égale au :date.',
'alpha' => 'Le champ :attribute doit contenir uniquement des lettres.',
'alpha_dash' => 'Le champ :attribute doit contenir uniquement des lettres, des chiffres, des tirets et des underscores.',
'alpha_num' => 'Le champ :attribute doit contenir uniquement des lettres et des chiffres.',
'array' => 'Le champ :attribute doit être un tableau.',
'before' => 'Le champ :attribute doit être une date antérieure au :date.',
'before_or_equal' => 'Le champ :attribute doit être une date antérieure ou égale au :date.',
'between' => [
'numeric' => 'La valeur de :attribute doit être comprise entre :min et :max.',
'file' => 'La taille du fichier de :attribute doit être comprise entre :min et :max kilo-octets.',
'string' => 'Le texte :attribute doit contenir entre :min et :max caractères.',
'array' => 'Le tableau :attribute doit contenir entre :min et :max éléments.',
],
'boolean' => 'Le champ :attribute doit être vrai ou faux.',
'confirmed' => 'Le champ de confirmation :attribute ne correspond pas.',
'date' => 'Le champ :attribute n\'est pas une date valide.',
'date_equals' => 'Le champ :attribute doit être une date égale à :date.',
'date_format' => 'Le champ :attribute ne correspond pas au format :format.',
'different' => 'Les champs :attribute et :other doivent être différents.',
'digits' => 'Le champ :attribute doit contenir :digits chiffres.',
'digits_between' => 'Le champ :attribute doit contenir entre :min et :max chiffres.',
'dimensions' => 'Les dimensions de l\'image :attribute ne sont pas valides.',
'distinct' => 'Le champ :attribute a une valeur en double.',
'email' => 'Le champ :attribute doit être une adresse e-mail valide.',
'ends_with' => 'Le champ :attribute doit se terminer par une des valeurs suivantes : :values.',
'exists' => 'Le champ :attribute sélectionné est invalide.',
'file' => 'Le champ :attribute doit être un fichier.',
'filled' => 'Le champ :attribute doit avoir une valeur.',
'gt' => [
'numeric' => 'La valeur de :attribute doit être supérieure à :value.',
'file' => 'La taille du fichier de :attribute doit être supérieure à :value kilo-octets.',
'string' => 'Le texte :attribute doit contenir plus de :value caractères.',
'array' => 'Le tableau :attribute doit contenir plus de :value éléments.',
],
'gte' => [
'numeric' => 'La valeur de :attribute doit être supérieure ou égale à :value.',
'file' => 'La taille du fichier de :attribute doit être supérieure ou égale à :value kilo-octets.',
'string' => 'Le texte :attribute doit contenir au moins :value caractères.',
'array' => 'Le tableau :attribute doit contenir au moins :value éléments.',
],
'image' => 'Le champ :attribute doit être une image.',
'in' => 'Le champ :attribute est invalide.',
'in_array' => 'Le champ :attribute n\'existe pas dans :other.',
'integer' => 'Le champ :attribute doit être un entier.',
'ip' => 'Le champ :attribute doit être une adresse IP valide.',
'ipv4' => 'Le champ :attribute doit être une adresse IPv4 valide.',
'ipv6' => 'Le champ :attribute doit être une adresse IPv6 valide.',
'json' => 'Le champ :attribute doit être un document JSON valide.',
'lt' => [
'numeric' => 'La valeur de :attribute doit être inférieure à :value.',
'file' => 'La taille du fichier de :attribute doit être inférieure à :value kilo-octets.',
'string' => 'Le texte :attribute doit contenir moins de :value caractères.',
'array' => 'Le tableau :attribute doit contenir moins de :value éléments.',
],
'lte' => [
'numeric' => 'La valeur de :attribute doit être inférieure ou égale à :value.',
'file' => 'La taille du fichier de :attribute doit être inférieure ou égale à :value kilo-octets.',
'string' => 'Le texte :attribute doit contenir au plus :value caractères.',
'array' => 'Le tableau :attribute doit contenir au plus :value éléments.',
],
'max' => [
'numeric' => 'La valeur de :attribute ne peut être supérieure à :max.',
'file' => 'La taille du fichier de :attribute ne peut pas dépasser :max kilo-octets.',
'string' => 'Le texte de :attribute ne peut contenir plus de :max caractères.',
'array' => 'Le tableau :attribute ne peut contenir plus de :max éléments.',
],
'mimes' => 'Le champ :attribute doit être un fichier de type : :values.',
'mimetypes' => 'Le champ :attribute doit être un fichier de type : :values.',
'min' => [
'numeric' => 'La valeur de :attribute doit être supérieure ou égale à :min.',
'file' => 'La taille du fichier de :attribute doit être supérieure à :min kilo-octets.',
'string' => 'Le texte :attribute doit contenir au moins :min caractères.',
'array' => 'Le tableau :attribute doit contenir au moins :min éléments.',
],
'multiple_of' => 'La valeur de :attribute doit être un multiple de :value',
'not_in' => 'Le champ :attribute sélectionné n\'est pas valide.',
'not_regex' => 'Le format du champ :attribute n\'est pas valide.',
'numeric' => 'Le champ :attribute doit contenir un nombre.',
'password' => 'Le mot de passe est incorrect.',
'present' => 'Le champ :attribute doit être présent.',
'regex' => 'Le format du champ :attribute est invalide.',
'required' => 'Le champ :attribute est obligatoire.',
'required_if' => 'Le champ :attribute est obligatoire quand :other est :value.',
'required_unless' => 'Le champ :attribute est obligatoire sauf si :other est :values.',
'required_with' => 'Le champ :attribute est obligatoire quand :values est présent.',
'required_with_all' => 'Le champ :attribute est obligatoire quand :values sont présents.',
'required_without' => 'Le champ :attribute est obligatoire quand :values n\'est pas présent.',
'required_without_all' => 'Le champ :attribute est requis quand aucun de :values n\'est présent.',
'same' => 'Les champs :attribute et :other doivent être identiques.',
'size' => [
'numeric' => 'La valeur de :attribute doit être :size.',
'file' => 'La taille du fichier de :attribute doit être de :size kilo-octets.',
'string' => 'Le texte de :attribute doit contenir :size caractères.',
'array' => 'Le tableau :attribute doit contenir :size éléments.',
],
'starts_with' => 'Le champ :attribute doit commencer avec une des valeurs suivantes : :values.',
'string' => 'Le champ :attribute doit être une chaîne de caractères.',
'timezone' => 'Le champ :attribute doit être un fuseau horaire valide.',
'unique' => 'La valeur du champ :attribute est déjà utilisée.',
'uploaded' => 'Le fichier du champ :attribute n\'a pu être téléversé.',
'url' => 'Le format de l\'URL de :attribute n\'est pas valide.',
'uuid' => 'Le champ :attribute doit être un UUID valide.',

'custom' => [
'attribute-name' => [
'rule-name' => 'message-personnalisé',
],
],

'attributes' => [],
];
Loading

0 comments on commit daca692

Please sign in to comment.