Form Translation (#616)

* 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 <julien@nahum.net>
This commit is contained in:
Chirag Chhatrala
2024-12-04 23:02:14 +05:30
committed by GitHub
parent c927a235f8
commit daca69267b
36 changed files with 1589 additions and 32 deletions

View File

@@ -71,6 +71,7 @@
:max-date="maxDate"
:is-dark="props.isDark"
color="form-color"
:locale="props.locale"
@update:model-value="updateModelValue"
/>
<DatePicker
@@ -84,6 +85,7 @@
:max-date="maxDate"
:is-dark="props.isDark"
color="form-color"
:locale="props.locale"
@update:model-value="updateModelValue"
/>
</template>

View File

@@ -50,7 +50,7 @@
>
<Loader class="mx-auto h-6 w-6" />
<p class="mt-2 text-center text-sm text-gray-500">
Uploading your file...
{{ $t('forms.fileInput.uploadingFile') }}
</p>
</div>
<template v-else>
@@ -95,10 +95,10 @@
</div>
<p class="mt-2 text-sm text-gray-500 font-medium select-none">
Click to choose {{ multiple ? 'file(s)' : 'a file' }} or drag here
{{ $t('forms.fileInput.chooseFiles', { n: multiple ? 1 : 0 }) }}
</p>
<p class="mt-1 text-xs text-gray-400 dark:text-gray-600 select-none">
Size limit: {{ mbLimit }}MB per file
{{ $t('forms.fileInput.sizeLimit', mbLimit) }}
</p>
</template>
</div>

View File

@@ -74,7 +74,7 @@
'!text-gray-500 !cursor-not-allowed'
]"
>
No options available.
{{ $t('forms.select.noOptionAvailable') }}
</div>
</div>

View File

@@ -25,7 +25,7 @@
>
<Loader class="mx-auto h-6 w-6" />
<p class="mt-2 text-center text-sm text-gray-500">
Uploading your file...
{{ $t('forms.fileInput.uploadingFile') }}
</p>
</div>
@@ -76,7 +76,7 @@
:class="theme.default.help"
href="#"
@click.prevent="openFileUpload"
>Upload file instead</a>
>{{ $t('forms.signatureInput.uploadFileInstead') }}</a>
</small>
<small :class="theme.default.help">
@@ -84,7 +84,7 @@
:class="theme.default.help"
href="#"
@click.prevent="clear"
>Clear</a>
>{{ $t('forms.signatureInput.clear') }}</a>
</small>
</template>

View File

@@ -49,17 +49,16 @@
class="w-6 h-6"
/>
<p class="text-center font-bold">
Allow Camera Permission
{{ $t('forms.cameraUpload.allowCameraPermission') }}
</p>
<p class="text-xs">
You need to allow camera permission before you can take pictures. Go to
browser settings to enable camera permission on this page.
{{ $t('forms.cameraUpload.allowCameraPermissionDescription') }}
</p>
<UButton
color="white"
@click.stop="cancelCamera"
>
Got it!
{{ $t('forms.cameraUpload.gotIt') }}
</UButton>
</div>
@@ -81,16 +80,16 @@
class="w-6 h-6"
/>
<p class="text-center font-bold">
Camera Device Error
{{ $t('forms.cameraUpload.cameraDeviceError') }}
</p>
<p class="text-xs">
An unknown error occurred when trying to start Webcam device.
{{ $t('forms.cameraUpload.cameraDeviceErrorDescription') }}
</p>
<UButton
color="white"
@click.stop="cancelCamera"
>
Go back
{{ $t('forms.cameraUpload.goBack') }}
</UButton>
</div>
</div>

View File

@@ -120,7 +120,7 @@
v-model="searchTerm"
type="text"
class="flex-grow ltr:pl-3 ltr:pr-7 rtl:!pr-3 rtl:pl-7 py-2 w-full focus:outline-none dark:text-white"
placeholder="Search"
:placeholder="allowCreation ? $t('forms.select.searchOrTypeToCreateNew') : $t('forms.select.search')"
>
<div
v-if="!searchTerm"
@@ -179,7 +179,7 @@
v-else-if="!loading && !(allowCreation && searchTerm)"
class="w-full text-gray-500 text-center py-2"
>
{{ (allowCreation ? 'Type something to add an option' : 'No option available') }}.
{{ (allowCreation ? $t('forms.select.typeSomethingToAddAnOption') : $t('forms.select.noOptionAvailable')) }}.
</p>
<div
v-if="allowCreation && searchTerm"
@@ -192,7 +192,7 @@
class="text-gray-900 select-none relative py-2 cursor-pointer group hover:bg-gray-100 dark:hover:bg-gray-900 rounded focus:outline-none"
@click="createOption(searchTerm)"
>
Create <span class="px-2 bg-gray-100 border border-gray-300 rounded group-hover-text-black">{{
{{ $t('forms.select.create') }} <span class="px-2 bg-gray-100 border border-gray-300 rounded group-hover-text-black">{{
searchTerm
}}</span>
</li>

View File

@@ -28,7 +28,8 @@ export const inputProps = {
help: {type: String, default: null},
helpPosition: {type: String, default: "below_input"},
color: {type: String, default: "#3B82F6"},
wrapperClass: {type: String, default: ""},
wrapperClass: { type: String, default: "" },
locale: { type: String, default: "en" },
}
export function useFormInput(props, context, options = {}) {

View File

@@ -27,7 +27,7 @@
<div v-if="isPublicFormPage && form.is_password_protected">
<p class="form-description mb-4 text-gray-700 dark:text-gray-300 px-2">
This form is protected by a password.
{{ $t('forms.password_protected') }}
</p>
<div class="form-group flex flex-wrap w-full">
<div class="relative mb-3 w-full px-2">
@@ -47,7 +47,7 @@
class="my-4"
@click="passwordEntered"
>
Submit
{{ $t('forms.submit') }}
</open-form-button>
</div>
</div>
@@ -139,7 +139,7 @@
class="text-gray-400 hover:text-gray-500 dark:text-gray-600 dark:hover:text-gray-500 cursor-pointer hover:underline text-xs"
target="_blank"
>
Powered by <span class="font-semibold">OpnForm</span>
{{ $t('forms.powered_by') }} <span class="font-semibold">{{ $t('app.name') }}</span>
</a>
</p>
</div>
@@ -186,7 +186,7 @@
href="https://opnform.com/?utm_source=form&utm_content=create_form_free"
class="text-nt-blue hover:underline"
>
Create your form for free with OpnForm
{{ $t('forms.create_form_free') }}
</a>
</p>
</div>
@@ -202,7 +202,6 @@
<script>
import OpenForm from './OpenForm.vue'
import OpenFormButton from './OpenFormButton.vue'
import FormTimer from './FormTimer.vue'
import FormCleanings from '../../pages/forms/show/FormCleanings.vue'
import VTransition from '~/components/global/transitions/VTransition.vue'
import {pendingSubmission} from "~/composables/forms/pendingSubmission.js"
@@ -211,7 +210,7 @@ import ThemeBuilder from "~/lib/forms/themes/ThemeBuilder.js"
import FirstSubmissionModal from '~/components/open/forms/components/FirstSubmissionModal.vue'
export default {
components: { VTransition, OpenFormButton, OpenForm, FormCleanings, FormTimer, FirstSubmissionModal },
components: { VTransition, OpenFormButton, OpenForm, FormCleanings, FirstSubmissionModal },
props: {
form: { type: Object, required: true },
@@ -225,8 +224,11 @@ export default {
},
setup(props) {
const { setLocale } = useI18n()
const authStore = useAuthStore()
return {
setLocale,
authStore,
authenticated: computed(() => authStore.check),
isIframe: useIsIframe(),
@@ -274,6 +276,17 @@ export default {
return this.authenticated && this.form && this.form.creator_id === this.authStore.user.id
}
},
watch: {
'form.language': {
handler(newLanguage) {
this.setLocale(newLanguage)
},
immediate: true
}
},
beforeUnmount() {
this.setLocale('en')
},
methods: {
submitForm (form, onFailure) {
@@ -346,7 +359,7 @@ export default {
if (this.passwordForm.password !== '' && this.passwordForm.password !== null) {
this.$emit('password-entered', this.passwordForm.password)
} else {
this.addPasswordError('The Password field is required.')
this.addPasswordError(this.$t('forms.password_required'))
}
},
addPasswordError (msg) {

View File

@@ -122,7 +122,7 @@
{{ currentFieldsPageBreak.next_btn_text }}
</open-form-button>
<div v-if="!currentFieldsPageBreak && !isLastPage">
Something is wrong with this form structure. If you're the form owner please contact us.
{{ $t('forms.wrong_form_structure') }}
</div>
</div>
</form>

View File

@@ -329,7 +329,8 @@ export default {
theme: this.theme,
maxCharLimit: (field.max_char_limit) ? parseInt(field.max_char_limit) : null,
showCharLimit: field.show_char_limit || false,
isDark: this.darkMode
isDark: this.darkMode,
locale: (this.form?.language) ? this.form.language : 'en'
}
if (field.type === 'matrix') {

View File

@@ -74,6 +74,14 @@
label="Uppercase Input Labels"
/>
<select-input
name="language"
class="mt-4"
:options="availableLocales"
:form="form"
label="Form Language"
/>
<EditorSectionHeader
icon="heroicons:rectangle-stack-16-solid"
title="Layout & Sizing"
@@ -215,6 +223,7 @@ const form = storeToRefs(workingFormStore).content
const isMounted = ref(false)
const confetti = useConfetti()
const showGoogleFontPicker = ref(false)
const { $i18n } = useNuxtApp()
const user = computed(() => authStore.user)
const workspace = computed(() => workspacesStore.getCurrent)
@@ -225,6 +234,10 @@ const isPro = computed(() => {
return workspace.value.is_pro
})
const availableLocales = computed(() => {
return $i18n.locales?.value.map(locale => ({ name: locale.name, value: locale.code })) ?? []
})
onMounted(() => {
isMounted.value = true
})

View File

@@ -10,6 +10,7 @@ export const initForm = (defaultValue = {}, withDefaultProperties = false) => {
properties: withDefaultProperties ? getDefaultProperties() : [],
// Customization
language: 'en',
font_family: null,
theme: "default",
width: "centered",

38
client/i18n/lang/ar.json Normal file
View File

@@ -0,0 +1,38 @@
{
"app": {
"name": "أوبنفورم"
},
"forms": {
"powered_by": "مشغل بواسطة",
"password_protected": "هذا النموذج محمي بكلمة مرور.",
"invalid_password": "كلمة مرور غير صالحة.",
"password_required": "كلمة مرور مطلوبة.",
"create_form_free": "أنشأ نموذجك مجانًا باستخدام أوبنفورم",
"submit": "إرسال",
"wrong_form_structure": "هناك خطأ في بنية هذا النموذج. إذا كنت مالك النموذج، يرجى الاتصال بنا.",
"select": {
"search": "بحث",
"searchOrTypeToCreateNew": "بحث أو اكتب شيءً لإضافة خيار",
"typeSomethingToAddAnOption": "اكتب شيءً لإضافة خيار",
"noOptionAvailable": "لا يوجد خيارات متاحة",
"create": "إنشاء"
},
"fileInput": {
"chooseFiles": "انقر لاختيار الملفات أو قم بإسقاطها هنا | انقر لاختيار ملف أو قم بإسقاطه هنا",
"sizeLimit": "الحد الأقصى للحجم: {count} ميجابايت لكل ملف",
"uploadingFile": "جاري تحميل الملف الخاص بك..."
},
"cameraUpload": {
"allowCameraPermission": "السماح بالوصول إلى الكاميرا",
"allowCameraPermissionDescription": "يجب السماح بالوصول إلى الكاميرا قبل التقاط الصور. انتقل إلى إعدادات المتصفح لتمكين الوصول إلى الكاميرا على هذه الصفحة.",
"gotIt": "فهمت!",
"cameraDeviceError": "خطأ في الكاميرا",
"cameraDeviceErrorDescription": "حدث خطأ غير معروف أثناء محاولة تشغيل كاميرا الويب.",
"goBack": "رجوع"
},
"signatureInput": {
"uploadFileInstead": "تحميل ملف بدلاً من ذلك",
"clear": "مسح"
}
}
}

38
client/i18n/lang/en.json Normal file
View File

@@ -0,0 +1,38 @@
{
"app": {
"name": "OpnForm"
},
"forms": {
"powered_by": "Powered by",
"password_protected": "This form is protected by a password.",
"invalid_password": "Invalid password.",
"password_required": "Password is required.",
"create_form_free": "Create your form for free with OpnForm",
"submit": "Submit",
"wrong_form_structure": "Something is wrong with this form structure. If you're the form owner please contact us.",
"select": {
"search": "Search",
"searchOrTypeToCreateNew": "Search or type to create new",
"typeSomethingToAddAnOption": "Type something to add an option",
"noOptionAvailable": "No option available",
"create": "Create"
},
"fileInput": {
"chooseFiles": "Click to choose file(s) or drag here | Click to choose a file or drag here",
"sizeLimit": "Size limit: {count}MB per file",
"uploadingFile": "Uploading your file..."
},
"cameraUpload": {
"allowCameraPermission": "Allow Camera Permission",
"allowCameraPermissionDescription": "You need to allow camera permission before you can take pictures. Go to browser settings to enable camera permission on this page.",
"gotIt": "Got it!",
"cameraDeviceError": "Camera Device Error",
"cameraDeviceErrorDescription": "An unknown error occurred when trying to start Webcam device.",
"goBack": "Go back"
},
"signatureInput": {
"uploadFileInstead": "Upload file instead",
"clear": "Clear"
}
}
}

38
client/i18n/lang/es.json Normal file
View File

@@ -0,0 +1,38 @@
{
"app": {
"name": "OpnForm"
},
"forms": {
"powered_by": "Desarrollado por",
"password_protected": "Este formulario está protegido por una contraseña.",
"invalid_password": "Contraseña inválida.",
"password_required": "Se requiere una contraseña.",
"create_form_free": "Crea tu formulario gratis con OpnForm",
"submit": "Enviar",
"wrong_form_structure": "Algo está mal con la estructura de este formulario. Si eres el propietario del formulario, por favor contacta con nosotros.",
"select": {
"search": "Buscar",
"searchOrTypeToCreateNew": "Buscar o escribe algo para crear una nueva opción",
"typeSomethingToAddAnOption": "Escribe algo para agregar una opción",
"noOptionAvailable": "No hay opciones disponibles",
"create": "Crear"
},
"fileInput": {
"chooseFiles": "Haga clic para elegir archivo(s) o suéltelo(s) aquí | Haga clic para elegir un archivo o suéltelo aquí",
"sizeLimit": "Tamaño límite: {count}MB por archivo",
"uploadingFile": "Subiendo su archivo..."
},
"cameraUpload": {
"allowCameraPermission": "Permitir acceso a la cámara",
"allowCameraPermissionDescription": "Debe permitir el acceso a la cámara antes de poder tomar fotos. Vaya a la configuración del navegador para habilitar el acceso a la cámara en esta página.",
"gotIt": "¡Entendido!",
"cameraDeviceError": "Error de cámara",
"cameraDeviceErrorDescription": "Se produjo un error desconocido al intentar iniciar el dispositivo de la cámara web.",
"goBack": "Volver"
},
"signatureInput": {
"uploadFileInstead": "Subir un archivo en su lugar",
"clear": "Borrar"
}
}
}

38
client/i18n/lang/fr.json Normal file
View File

@@ -0,0 +1,38 @@
{
"app": {
"name": "OpnForm"
},
"forms": {
"powered_by": "Powered by",
"password_protected": "Ce formulaire est protégé par un mot de passe.",
"invalid_password": "Mot de passe invalide.",
"password_required": "Le mot de passe est requis.",
"create_form_free": "Créez votre formulaire gratuitement avec OpnForm",
"submit": "Envoyer",
"wrong_form_structure": "Quelque chose ne va pas avec la structure de ce formulaire. Si vous êtes le propriétaire du formulaire, veuillez nous contacter.",
"select": {
"search": "Rechercher",
"searchOrTypeToCreateNew": "Rechercher ou écrivez quelque chose pour créer une nouvelle option",
"typeSomethingToAddAnOption": "Écrivez quelque chose pour ajouter une option",
"noOptionAvailable": "Aucune option disponible",
"create": "Créer"
},
"fileInput": {
"chooseFiles": "Cliquez pour choisir un/des fichier(s) ou déposez-le(s) ici | Cliquez pour choisir un fichier ou déposez-le ici",
"sizeLimit": "Taille limite: {count}MB par fichier",
"uploadingFile": "Envoi de votre fichier en cours..."
},
"cameraUpload": {
"allowCameraPermission": "Autoriser l'accès à la caméra",
"allowCameraPermissionDescription": "Vous devez autoriser l'accès à la caméra avant de pouvoir prendre des photos. Allez dans les paramètres du navigateur pour activer l'accès à la caméra sur cette page.",
"gotIt": "J'ai compris !",
"cameraDeviceError": "Erreur de caméra",
"cameraDeviceErrorDescription": "Une erreur inconnue est survenue lors de la tentative de démarrage du périphérique webcam.",
"goBack": "Retour"
},
"signatureInput": {
"uploadFileInstead": "Uploader un fichier à la place",
"clear": "Effacer"
}
}
}

38
client/i18n/lang/hi.json Normal file
View File

@@ -0,0 +1,38 @@
{
"app": {
"name": "ऑपनफॉर्म"
},
"forms": {
"powered_by": "ऑपनफॉर्म के साथ",
"password_protected": "यह फ़ॉर्म पासवर्ड से सुरक्षित है।",
"invalid_password": "अमान्य पासवर्ड।",
"password_required": "पासवर्ड आवश्यक है।",
"create_form_free": "अपनी फ़ॉर्म फ्री में ऑपनफॉर्म के साथ बनाएं",
"submit": "जमा करें",
"wrong_form_structure": "यह फ़ॉर्म संरचना में कुछ गलत है। यदि आप फ़ॉर्म का मालिक हैं, तो कृपया हमसे संपर्क करें।",
"select": {
"search": "खोजें",
"searchOrTypeToCreateNew": "खोजें या कुछ भी टाइप करें जो विकल्प जोड़ने के लिए",
"typeSomethingToAddAnOption": "कुछ भी टाइप करें जो विकल्प जोड़ने के लिए",
"noOptionAvailable": "कोई विकल्प उपलब्ध नहीं है",
"create": "बनाएं"
},
"fileInput": {
"chooseFiles": "फ़ाइलें चुनने के लिए क्लिक करें या यहां खींचें | फ़ाइल चुनने के लिए क्लिक करें या यहां खींचें",
"sizeLimit": "साइज़ सीमा: प्रति फ़ाइल {count}MB",
"uploadingFile": "आपकी फ़ाइल अपलोड हो रही है..."
},
"cameraUpload": {
"allowCameraPermission": "कैमरा एक्सेस की अनुमति दें",
"allowCameraPermissionDescription": "फ़ोटो लेने से पहले कैमरा एक्सेस की अनुमति देनी होगी। इस पेज पर कैमरा एक्सेस सक्षम करने के लिए ब्राउज़र सेटिंग्स में जाएं।",
"gotIt": "समझ गया!",
"cameraDeviceError": "कैमरा त्रुटि",
"cameraDeviceErrorDescription": "वेबकैम डिवाइस शुरू करने का प्रयास करते समय एक अज्ञात त्रुटि हुई।",
"goBack": "वापस जाएं"
},
"signatureInput": {
"uploadFileInstead": "इसके बजाय फ़ाइल अपलोड करें",
"clear": "साफ़ करें"
}
}
}

38
client/i18n/lang/ja.json Normal file
View File

@@ -0,0 +1,38 @@
{
"app": {
"name": "OpnForm"
},
"forms": {
"powered_by": "Powered by",
"password_protected": "このフォームはパスワードで保護されています。",
"invalid_password": "無効なパスワード。",
"password_required": "パスワードが必要です。",
"create_form_free": "無料でOpnFormでフォームを作成",
"submit": "送信",
"wrong_form_structure": "このフォームの構造に問題があります。フォームの所有者である場合は、お問い合わせください。",
"select": {
"search": "検索",
"searchOrTypeToCreateNew": "検索または何かを入力して新しいオプションを作成",
"typeSomethingToAddAnOption": "オプションを追加するには何かを入力してください",
"noOptionAvailable": "オプションがありません",
"create": "作成"
},
"fileInput": {
"chooseFiles": "クリックしてファイルを選択するか、ここにドロップしてください | クリックしてファイルを選択するか、ここにドロップしてください",
"sizeLimit": "サイズ制限:ファイルあたり{count}MB",
"uploadingFile": "ファイルをアップロード中..."
},
"cameraUpload": {
"allowCameraPermission": "カメラへのアクセスを許可",
"allowCameraPermissionDescription": "写真を撮影する前にカメラへのアクセスを許可する必要があります。ブラウザの設定でこのページのカメラアクセスを有効にしてください。",
"gotIt": "了解しました!",
"cameraDeviceError": "カメラエラー",
"cameraDeviceErrorDescription": "ウェブカメラデバイスの起動時に不明なエラーが発生しました。",
"goBack": "戻る"
},
"signatureInput": {
"uploadFileInstead": "代わりにファイルをアップロード",
"clear": "クリア"
}
}
}

38
client/i18n/lang/pt.json Normal file
View File

@@ -0,0 +1,38 @@
{
"app": {
"name": "OpnForm"
},
"forms": {
"powered_by": "Powered by",
"password_protected": "Este formulário está protegido por uma senha.",
"invalid_password": "Senha inválida.",
"password_required": "A senha é necessária.",
"create_form_free": "Crie seu formulário gratuitamente com OpnForm",
"submit": "Enviar",
"wrong_form_structure": "Algo está errado com a estrutura deste formulário. Se você é o proprietário do formulário, por favor entre em contato conosco.",
"select": {
"search": "Buscar",
"searchOrTypeToCreateNew": "Buscar ou escreva algo para criar uma nova opção",
"typeSomethingToAddAnOption": "Escreva algo para adicionar uma opção",
"noOptionAvailable": "Nenhuma opção disponível",
"create": "Criar"
},
"fileInput": {
"chooseFiles": "Clique para escolher arquivo(s) ou solte-os aqui | Clique para escolher um arquivo ou solte-o aqui",
"sizeLimit": "Limite de tamanho: {count}MB por arquivo",
"uploadingFile": "Enviando seu arquivo..."
},
"cameraUpload": {
"allowCameraPermission": "Permitir acesso à câmera",
"allowCameraPermissionDescription": "Você precisa permitir o acesso à câmera antes de tirar fotos. Vá para as configurações do navegador para ativar o acesso à câmera nesta página.",
"gotIt": "Entendi!",
"cameraDeviceError": "Erro de câmera",
"cameraDeviceErrorDescription": "Ocorreu um erro desconhecido ao tentar iniciar o dispositivo da webcam.",
"goBack": "Voltar"
},
"signatureInput": {
"uploadFileInstead": "Fazer upload de arquivo em vez disso",
"clear": "Limpar"
}
}
}

38
client/i18n/lang/zh.json Normal file
View File

@@ -0,0 +1,38 @@
{
"app": {
"name": "OpnForm"
},
"forms": {
"powered_by": "Powered by",
"password_protected": "此表单受密码保护。",
"invalid_password": "无效密码。",
"password_required": "密码是必需的。",
"create_form_free": "免费使用OpnForm创建表单",
"submit": "提交",
"wrong_form_structure": "此表单的结构有问题。如果您是表单所有者,请与我们联系。",
"select": {
"search": "搜索",
"searchOrTypeToCreateNew": "搜索或输入以创建新选项",
"typeSomethingToAddAnOption": "输入一些东西以添加选项",
"noOptionAvailable": "没有选项可用",
"create": "创建"
},
"fileInput": {
"chooseFiles": "点击选择文件或将文件拖放到此处 | 点击选择文件或将文件拖放到此处",
"sizeLimit": "大小限制:每个文件 {count}MB",
"uploadingFile": "正在上传您的文件..."
},
"cameraUpload": {
"allowCameraPermission": "允许访问相机",
"allowCameraPermissionDescription": "在拍照之前,您需要允许访问相机。请转到浏览器设置以启用此页面的相机访问权限。",
"gotIt": "明白了!",
"cameraDeviceError": "相机错误",
"cameraDeviceErrorDescription": "尝试启动网络摄像头设备时发生未知错误。",
"goBack": "返回"
},
"signatureInput": {
"uploadFileInstead": "改为上传文件",
"clear": "清除"
}
}
}

View File

@@ -15,11 +15,28 @@ export default defineNuxtConfig({
'@nuxtjs/sitemap',
'@nuxt/ui',
'nuxt-utm',
'@nuxtjs/i18n',
'@nuxt/icon',
...process.env.NUXT_PUBLIC_GTM_CODE ? ['@zadigetvoltaire/nuxt-gtm'] : [],
],
],
build: {
transpile: ["vue-notion", "query-builder-vue-3", "vue-signature-pad"],
},
i18n: {
locales: [
{ code: 'en', name: 'English', iso: 'en-US', file: 'en.json' },
{ code: 'fr', name: 'French', iso: 'fr-FR', file: 'fr.json' },
{ code: 'hi', name: 'Hindi', iso: 'hi-IN', file: 'hi.json' },
{ code: 'es', name: 'Spanish', iso: 'es-ES', file: 'es.json' },
{ code: 'ar', name: 'Arabic', iso: 'ar-EG', file: 'ar.json' },
{ code: 'zh', name: 'Chinese', iso: 'zh-CN', file: 'zh.json' },
{ code: 'ja', name: 'Japanese', iso: 'ja-JP', file: 'ja.json' },
],
defaultLocale: 'en',
lazy: true,
langDir: 'lang/',
strategy: 'no_prefix'
},
experimental: {
inlineRouteRules: true
},

576
client/package-lock.json generated
View File

@@ -57,6 +57,7 @@
"@nuxt/devtools": "^1.6.1",
"@nuxt/eslint-config": "^0.2.0",
"@nuxt/icon": "^1.8.2",
"@nuxtjs/i18n": "^9.0.0",
"@nuxtjs/sitemap": "^6.1.3",
"@zadigetvoltaire/nuxt-gtm": "^0.0.13",
"autoprefixer": "^10.4.20",
@@ -1530,6 +1531,358 @@
"vue": ">=3"
}
},
"node_modules/@intlify/bundle-utils": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/@intlify/bundle-utils/-/bundle-utils-9.0.0.tgz",
"integrity": "sha512-19dunbgM4wuCvi2xSai2PKhXkcKGjlbJhNWm9BCQWkUYcPmXwzptNWOE0O7OSrhNlEDxwpkHsJzZ/vLbCkpElw==",
"dev": true,
"dependencies": {
"@intlify/message-compiler": "next",
"@intlify/shared": "next",
"acorn": "^8.8.2",
"escodegen": "^2.1.0",
"estree-walker": "^2.0.2",
"jsonc-eslint-parser": "^2.3.0",
"mlly": "^1.2.0",
"source-map-js": "^1.0.1",
"yaml-eslint-parser": "^1.2.2"
},
"engines": {
"node": ">= 18"
},
"peerDependenciesMeta": {
"petite-vue-i18n": {
"optional": true
},
"vue-i18n": {
"optional": true
}
}
},
"node_modules/@intlify/bundle-utils/node_modules/estree-walker": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
"dev": true
},
"node_modules/@intlify/core": {
"version": "10.0.4",
"resolved": "https://registry.npmjs.org/@intlify/core/-/core-10.0.4.tgz",
"integrity": "sha512-YVb0Hk0vgulAhC/uq5CMUXLMcmDL+24FWcjRk2RMn2EF8ZrM3ZV9+8dGOKextntN1/RtjK3RvoHicF48vMyYkA==",
"dev": true,
"dependencies": {
"@intlify/core-base": "10.0.4",
"@intlify/shared": "10.0.4"
},
"engines": {
"node": ">= 16"
},
"funding": {
"url": "https://github.com/sponsors/kazupon"
}
},
"node_modules/@intlify/core-base": {
"version": "10.0.4",
"resolved": "https://registry.npmjs.org/@intlify/core-base/-/core-base-10.0.4.tgz",
"integrity": "sha512-GG428DkrrWCMhxRMRQZjuS7zmSUzarYcaHJqG9VB8dXAxw4iQDoKVQ7ChJRB6ZtsCsX3Jse1PEUlHrJiyQrOTg==",
"dev": true,
"dependencies": {
"@intlify/message-compiler": "10.0.4",
"@intlify/shared": "10.0.4"
},
"engines": {
"node": ">= 16"
},
"funding": {
"url": "https://github.com/sponsors/kazupon"
}
},
"node_modules/@intlify/h3": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/@intlify/h3/-/h3-0.6.0.tgz",
"integrity": "sha512-tWBm92pYLT+T2H5I2Uwz0dnylX1uRKuS6/n9CV4eTW43r/iAN2q07b0sY2cvgT61KYDetomY1pVRkzA2Rftv5g==",
"dev": true,
"dependencies": {
"@intlify/core": "^10.0.3",
"@intlify/utils": "^0.13.0"
},
"engines": {
"node": ">= 18"
},
"funding": {
"url": "https://github.com/sponsors/kazupon"
}
},
"node_modules/@intlify/message-compiler": {
"version": "10.0.4",
"resolved": "https://registry.npmjs.org/@intlify/message-compiler/-/message-compiler-10.0.4.tgz",
"integrity": "sha512-AFbhEo10DP095/45EauinQJ5hJ3rJUmuuqltGguvc3WsvezZN+g8qNHLGWKu60FHQVizMrQY7VJ+zVlBXlQQkQ==",
"dev": true,
"dependencies": {
"@intlify/shared": "10.0.4",
"source-map-js": "^1.0.2"
},
"engines": {
"node": ">= 16"
},
"funding": {
"url": "https://github.com/sponsors/kazupon"
}
},
"node_modules/@intlify/shared": {
"version": "10.0.4",
"resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-10.0.4.tgz",
"integrity": "sha512-ukFn0I01HsSgr3VYhYcvkTCLS7rGa0gw4A4AMpcy/A9xx/zRJy7PS2BElMXLwUazVFMAr5zuiTk3MQeoeGXaJg==",
"dev": true,
"engines": {
"node": ">= 16"
},
"funding": {
"url": "https://github.com/sponsors/kazupon"
}
},
"node_modules/@intlify/unplugin-vue-i18n": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/@intlify/unplugin-vue-i18n/-/unplugin-vue-i18n-5.2.0.tgz",
"integrity": "sha512-pmRiPY2Nj9mmSrixT69aO45XxGUr5fDBy/IIw4ajLlDTJm5TSmQKA5YNdsH0uxVDCPWy5tlQrF18hkDwI7UJvg==",
"dev": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.4.0",
"@intlify/bundle-utils": "^9.0.0-beta.0",
"@intlify/shared": "next",
"@intlify/vue-i18n-extensions": "^7.0.0",
"@rollup/pluginutils": "^5.1.0",
"@typescript-eslint/scope-manager": "^7.13.0",
"@typescript-eslint/typescript-estree": "^7.13.0",
"debug": "^4.3.3",
"fast-glob": "^3.2.12",
"js-yaml": "^4.1.0",
"json5": "^2.2.3",
"pathe": "^1.0.0",
"picocolors": "^1.0.0",
"source-map-js": "^1.0.2",
"unplugin": "^1.1.0",
"vue": "^3.4"
},
"engines": {
"node": ">= 18"
},
"peerDependencies": {
"petite-vue-i18n": "*",
"vue": "^3.2.25",
"vue-i18n": "*"
},
"peerDependenciesMeta": {
"petite-vue-i18n": {
"optional": true
},
"vue-i18n": {
"optional": true
}
}
},
"node_modules/@intlify/unplugin-vue-i18n/node_modules/@typescript-eslint/scope-manager": {
"version": "7.18.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.18.0.tgz",
"integrity": "sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "7.18.0",
"@typescript-eslint/visitor-keys": "7.18.0"
},
"engines": {
"node": "^18.18.0 || >=20.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@intlify/unplugin-vue-i18n/node_modules/@typescript-eslint/types": {
"version": "7.18.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.18.0.tgz",
"integrity": "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==",
"dev": true,
"engines": {
"node": "^18.18.0 || >=20.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@intlify/unplugin-vue-i18n/node_modules/@typescript-eslint/typescript-estree": {
"version": "7.18.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.18.0.tgz",
"integrity": "sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "7.18.0",
"@typescript-eslint/visitor-keys": "7.18.0",
"debug": "^4.3.4",
"globby": "^11.1.0",
"is-glob": "^4.0.3",
"minimatch": "^9.0.4",
"semver": "^7.6.0",
"ts-api-utils": "^1.3.0"
},
"engines": {
"node": "^18.18.0 || >=20.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependenciesMeta": {
"typescript": {
"optional": true
}
}
},
"node_modules/@intlify/unplugin-vue-i18n/node_modules/@typescript-eslint/visitor-keys": {
"version": "7.18.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.18.0.tgz",
"integrity": "sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "7.18.0",
"eslint-visitor-keys": "^3.4.3"
},
"engines": {
"node": "^18.18.0 || >=20.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@intlify/unplugin-vue-i18n/node_modules/globby": {
"version": "11.1.0",
"resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
"integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
"dev": true,
"dependencies": {
"array-union": "^2.1.0",
"dir-glob": "^3.0.1",
"fast-glob": "^3.2.9",
"ignore": "^5.2.0",
"merge2": "^1.4.1",
"slash": "^3.0.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@intlify/unplugin-vue-i18n/node_modules/ignore": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
"integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
"dev": true,
"engines": {
"node": ">= 4"
}
},
"node_modules/@intlify/unplugin-vue-i18n/node_modules/minimatch": {
"version": "9.0.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
"dev": true,
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": ">=16 || 14 >=14.17"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/@intlify/unplugin-vue-i18n/node_modules/slash": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
"integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/@intlify/unplugin-vue-i18n/node_modules/unplugin": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.15.0.tgz",
"integrity": "sha512-jTPIs63W+DUEDW207ztbaoO7cQ4p5aVaB823LSlxpsFEU3Mykwxf3ZGC/wzxFJeZlASZYgVrWeo7LgOrqJZ8RA==",
"dev": true,
"dependencies": {
"acorn": "^8.14.0",
"webpack-virtual-modules": "^0.6.2"
},
"engines": {
"node": ">=14.0.0"
},
"peerDependencies": {
"webpack-sources": "^3"
},
"peerDependenciesMeta": {
"webpack-sources": {
"optional": true
}
}
},
"node_modules/@intlify/unplugin-vue-i18n/node_modules/webpack-virtual-modules": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz",
"integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==",
"dev": true
},
"node_modules/@intlify/utils": {
"version": "0.13.0",
"resolved": "https://registry.npmjs.org/@intlify/utils/-/utils-0.13.0.tgz",
"integrity": "sha512-8i3uRdAxCGzuHwfmHcVjeLQBtysQB2aXl/ojoagDut5/gY5lvWCQ2+cnl2TiqE/fXj/D8EhWG/SLKA7qz4a3QA==",
"dev": true,
"engines": {
"node": ">= 18"
},
"funding": {
"url": "https://github.com/sponsors/kazupon"
}
},
"node_modules/@intlify/vue-i18n-extensions": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/@intlify/vue-i18n-extensions/-/vue-i18n-extensions-7.0.0.tgz",
"integrity": "sha512-MtvfJnb4aklpCU5Q/dkWkBT/vGsp3qERiPIwtTq5lX4PCLHtUprAJZp8wQj5ZcwDaFCU7+yVMjYbeXpIf927cA==",
"dev": true,
"dependencies": {
"@babel/parser": "^7.24.6",
"@intlify/shared": "^10.0.0",
"@vue/compiler-dom": "^3.2.45",
"vue-i18n": "^10.0.0"
},
"engines": {
"node": ">= 18"
},
"peerDependencies": {
"@intlify/shared": "^9.0.0 || ^10.0.0",
"@vue/compiler-dom": "^3.0.0",
"vue": "^3.0.0",
"vue-i18n": "^9.0.0 || ^10.0.0"
},
"peerDependenciesMeta": {
"@intlify/shared": {
"optional": true
},
"@vue/compiler-dom": {
"optional": true
},
"vue": {
"optional": true
},
"vue-i18n": {
"optional": true
}
}
},
"node_modules/@ioredis/commands": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz",
@@ -1819,6 +2172,19 @@
"node-pre-gyp": "bin/node-pre-gyp"
}
},
"node_modules/@miyaneee/rollup-plugin-json5": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@miyaneee/rollup-plugin-json5/-/rollup-plugin-json5-1.2.0.tgz",
"integrity": "sha512-JjTIaXZp9WzhUHpElrqPnl1AzBi/rvRs065F71+aTmlqvTMVkdbjZ8vfFl4nRlgJy+TPBw69ZK4pwFdmOAt4aA==",
"dev": true,
"dependencies": {
"@rollup/pluginutils": "^5.1.0",
"json5": "^2.2.3"
},
"peerDependencies": {
"rollup": "^1.20.0 || ^2.0.0 || ^3.0.0 || ^4.0.0"
}
},
"node_modules/@netlify/functions": {
"version": "2.8.2",
"resolved": "https://registry.npmjs.org/@netlify/functions/-/functions-2.8.2.tgz",
@@ -2682,6 +3048,76 @@
"semver": "^7.6.3"
}
},
"node_modules/@nuxtjs/i18n": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/@nuxtjs/i18n/-/i18n-9.0.0.tgz",
"integrity": "sha512-olAVD7ZPNVxWpOgj5VJrtWaqkVfKSDQmJENfed7t6TwDjVggPHPHMpmw4rbudDsr9cdCIBR30hvUEXm2m7s2BA==",
"dev": true,
"dependencies": {
"@intlify/h3": "^0.6.0",
"@intlify/shared": "^10.0.3",
"@intlify/unplugin-vue-i18n": "^5.2.0",
"@intlify/utils": "^0.13.0",
"@miyaneee/rollup-plugin-json5": "^1.2.0",
"@nuxt/kit": "^3.13.2",
"@rollup/plugin-yaml": "^4.1.2",
"@vue/compiler-sfc": "^3.5.5",
"debug": "^4.3.5",
"defu": "^6.1.2",
"estree-walker": "^3.0.3",
"is-https": "^4.0.0",
"knitwork": "^1.1.0",
"magic-string": "^0.30.10",
"mlly": "^1.7.1",
"pathe": "^1.1.1",
"scule": "^1.1.1",
"sucrase": "^3.35.0",
"ufo": "^1.3.1",
"unplugin": "^1.10.1",
"unplugin-vue-router": "^0.10.8",
"vue-i18n": "^10.0.3",
"vue-router": "^4.4.5"
},
"engines": {
"node": "^14.16.0 || >=16.11.0"
}
},
"node_modules/@nuxtjs/i18n/node_modules/magic-string": {
"version": "0.30.12",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.12.tgz",
"integrity": "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==",
"dev": true,
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.5.0"
}
},
"node_modules/@nuxtjs/i18n/node_modules/unplugin": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.15.0.tgz",
"integrity": "sha512-jTPIs63W+DUEDW207ztbaoO7cQ4p5aVaB823LSlxpsFEU3Mykwxf3ZGC/wzxFJeZlASZYgVrWeo7LgOrqJZ8RA==",
"dev": true,
"dependencies": {
"acorn": "^8.14.0",
"webpack-virtual-modules": "^0.6.2"
},
"engines": {
"node": ">=14.0.0"
},
"peerDependencies": {
"webpack-sources": "^3"
},
"peerDependenciesMeta": {
"webpack-sources": {
"optional": true
}
}
},
"node_modules/@nuxtjs/i18n/node_modules/webpack-virtual-modules": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz",
"integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==",
"dev": true
},
"node_modules/@nuxtjs/sitemap": {
"version": "6.1.5",
"resolved": "https://registry.npmjs.org/@nuxtjs/sitemap/-/sitemap-6.1.5.tgz",
@@ -3411,6 +3847,28 @@
}
}
},
"node_modules/@rollup/plugin-yaml": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/@rollup/plugin-yaml/-/plugin-yaml-4.1.2.tgz",
"integrity": "sha512-RpupciIeZMUqhgFE97ba0s98mOFS7CWzN3EJNhJkqSv9XLlWYtwVdtE6cDw6ASOF/sZVFS7kRJXftaqM2Vakdw==",
"dev": true,
"dependencies": {
"@rollup/pluginutils": "^5.0.1",
"js-yaml": "^4.1.0",
"tosource": "^2.0.0-alpha.3"
},
"engines": {
"node": ">=14.0.0"
},
"peerDependencies": {
"rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0"
},
"peerDependenciesMeta": {
"rollup": {
"optional": true
}
}
},
"node_modules/@rollup/pluginutils": {
"version": "5.1.3",
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.3.tgz",
@@ -5345,7 +5803,6 @@
"version": "8.14.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
"integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==",
"license": "MIT",
"bin": {
"acorn": "bin/acorn"
},
@@ -7217,6 +7674,37 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/escodegen": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz",
"integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==",
"dev": true,
"dependencies": {
"esprima": "^4.0.1",
"estraverse": "^5.2.0",
"esutils": "^2.0.2"
},
"bin": {
"escodegen": "bin/escodegen.js",
"esgenerate": "bin/esgenerate.js"
},
"engines": {
"node": ">=6.0"
},
"optionalDependencies": {
"source-map": "~0.6.1"
}
},
"node_modules/escodegen/node_modules/source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true,
"optional": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/eslint": {
"version": "8.57.1",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz",
@@ -7525,6 +8013,19 @@
"url": "https://opencollective.com/eslint"
}
},
"node_modules/esprima": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
"dev": true,
"bin": {
"esparse": "bin/esparse.js",
"esvalidate": "bin/esvalidate.js"
},
"engines": {
"node": ">=4"
}
},
"node_modules/esquery": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
@@ -8664,6 +9165,12 @@
"node": ">=0.10.0"
}
},
"node_modules/is-https": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/is-https/-/is-https-4.0.0.tgz",
"integrity": "sha512-FeMLiqf8E5g6SdiVJsPcNZX8k4h2fBs1wp5Bb6uaNxn58ufK1axBqQZdmAQsqh0t9BuwFObybrdVJh6MKyPlyg==",
"dev": true
},
"node_modules/is-inside-container": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz",
@@ -8948,6 +9455,24 @@
"node": ">=6"
}
},
"node_modules/jsonc-eslint-parser": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/jsonc-eslint-parser/-/jsonc-eslint-parser-2.4.0.tgz",
"integrity": "sha512-WYDyuc/uFcGp6YtM2H0uKmUwieOuzeE/5YocFJLnLfclZ4inf3mRn8ZVy1s7Hxji7Jxm6Ss8gqpexD/GlKoGgg==",
"dev": true,
"dependencies": {
"acorn": "^8.5.0",
"eslint-visitor-keys": "^3.0.0",
"espree": "^9.0.0",
"semver": "^7.3.5"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/ota-meshi"
}
},
"node_modules/jsonfile": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
@@ -14482,6 +15007,15 @@
"node": ">=0.6"
}
},
"node_modules/tosource": {
"version": "2.0.0-alpha.3",
"resolved": "https://registry.npmjs.org/tosource/-/tosource-2.0.0-alpha.3.tgz",
"integrity": "sha512-KAB2lrSS48y91MzFPFuDg4hLbvDiyTjOVgaK7Erw+5AmZXNq4sFRVn8r6yxSLuNs15PaokrDRpS61ERY9uZOug==",
"dev": true,
"engines": {
"node": ">=10"
}
},
"node_modules/totalist": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz",
@@ -16159,6 +16693,26 @@
"eslint": ">=6.0.0"
}
},
"node_modules/vue-i18n": {
"version": "10.0.4",
"resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-10.0.4.tgz",
"integrity": "sha512-1xkzVxqBLk2ZFOmeI+B5r1J7aD/WtNJ4j9k2mcFcQo5BnOmHBmD7z4/oZohh96AAaRZ4Q7mNQvxc9h+aT+Md3w==",
"dev": true,
"dependencies": {
"@intlify/core-base": "10.0.4",
"@intlify/shared": "10.0.4",
"@vue/devtools-api": "^6.5.0"
},
"engines": {
"node": ">= 16"
},
"funding": {
"url": "https://github.com/sponsors/kazupon"
},
"peerDependencies": {
"vue": "^3.0.0"
}
},
"node_modules/vue-json-pretty": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/vue-json-pretty/-/vue-json-pretty-2.4.0.tgz",
@@ -16424,8 +16978,24 @@
"node_modules/yaml-ast-parser": {
"version": "0.0.43",
"resolved": "https://registry.npmjs.org/yaml-ast-parser/-/yaml-ast-parser-0.0.43.tgz",
"integrity": "sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A==",
"license": "Apache-2.0"
"integrity": "sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A=="
},
"node_modules/yaml-eslint-parser": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/yaml-eslint-parser/-/yaml-eslint-parser-1.2.3.tgz",
"integrity": "sha512-4wZWvE398hCP7O8n3nXKu/vdq1HcH01ixYlCREaJL5NUMwQ0g3MaGFUBNSlmBtKmhbtVG/Cm6lyYmSVTEVil8A==",
"dev": true,
"dependencies": {
"eslint-visitor-keys": "^3.0.0",
"lodash": "^4.17.21",
"yaml": "^2.0.0"
},
"engines": {
"node": "^14.17.0 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/ota-meshi"
}
},
"node_modules/yargs": {
"version": "15.4.1",

View File

@@ -19,6 +19,7 @@
"@nuxt/devtools": "^1.6.1",
"@nuxt/eslint-config": "^0.2.0",
"@nuxt/icon": "^1.8.2",
"@nuxtjs/i18n": "^9.0.0",
"@nuxtjs/sitemap": "^6.1.3",
"@zadigetvoltaire/nuxt-gtm": "^0.0.13",
"autoprefixer": "^10.4.20",

View File

@@ -93,6 +93,7 @@ const formLoading = computed(() => formsStore.loading)
const recordLoading = computed(() => recordsStore.loading)
const slug = useRoute().params.slug
const form = computed(() => formsStore.getByKey(slug))
const $t = useI18n()
const openCompleteForm = ref(null)
@@ -106,7 +107,7 @@ const passwordEntered = function (password) {
nextTick(() => {
loadForm().then(() => {
if (form.value?.is_password_protected) {
openCompleteForm.value.addPasswordError('Invalid password.')
openCompleteForm.value.addPasswordError($t('forms.invalid_password'))
}
})
})
@@ -235,7 +236,11 @@ useOpnSeoMeta({
return (form.value && form.value?.can_be_indexed) ? null : 'noindex, nofollow'
}
})
useHead({
htmlAttrs: {
lang: (form.value?.language) ? form.value.language : 'en'
},
titleTemplate: (titleChunk) => {
if (pageMeta.value.page_title) {
// Disable template if custom SEO title