From f860d8d25d08968158cc9d01233d59f8b47ab07c Mon Sep 17 00:00:00 2001
From: Dhruwang Jariwala <67850763+Dhruwang@users.noreply.github.com>
Date: Thu, 14 Aug 2025 21:18:05 +0530
Subject: [PATCH] fix: link preview settings tweaks (#6418)
---
.../shareEmbedModal/link-settings-tab.tsx | 4 +-
apps/web/locales/de-DE.json | 11 +---
apps/web/locales/en-US.json | 11 +---
apps/web/locales/fr-FR.json | 11 +---
apps/web/locales/pt-BR.json | 11 +---
apps/web/locales/pt-PT.json | 11 +---
apps/web/locales/ro-RO.json | 11 +---
apps/web/locales/zh-Hant-TW.json | 11 +---
.../survey/link/contact-survey/page.test.tsx | 4 +-
.../survey/link/contact-survey/page.tsx | 4 +-
.../survey/link/lib/metadata-utils.test.ts | 12 ++--
.../modules/survey/link/lib/metadata-utils.ts | 62 +++++++++----------
apps/web/modules/survey/link/metadata.test.ts | 4 +-
apps/web/modules/survey/link/metadata.ts | 3 +-
14 files changed, 50 insertions(+), 120 deletions(-)
diff --git a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/shareEmbedModal/link-settings-tab.tsx b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/shareEmbedModal/link-settings-tab.tsx
index 4497fbdafd..7ffb9c03ec 100644
--- a/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/shareEmbedModal/link-settings-tab.tsx
+++ b/apps/web/app/(app)/environments/[environmentId]/surveys/[surveyId]/(analysis)/summary/components/shareEmbedModal/link-settings-tab.tsx
@@ -150,13 +150,13 @@ export const LinkSettingsTab = ({ isReadOnly, locale }: LinkSettingsTabProps) =>
name: "title",
label: t("environments.surveys.share.link_settings.link_title"),
description: t("environments.surveys.share.link_settings.link_title_description"),
- placeholder: t("environments.surveys.share.link_settings.link_title_placeholder"),
+ placeholder: survey.name,
},
{
name: "description",
label: t("environments.surveys.share.link_settings.link_description"),
description: t("environments.surveys.share.link_settings.link_description_description"),
- placeholder: t("environments.surveys.share.link_settings.link_description_placeholder"),
+ placeholder: "Please complete this survey.",
},
];
diff --git a/apps/web/locales/de-DE.json b/apps/web/locales/de-DE.json
index c39014f3f2..3fe40fef6b 100644
--- a/apps/web/locales/de-DE.json
+++ b/apps/web/locales/de-DE.json
@@ -141,7 +141,6 @@
"apply_filters": "Filter anwenden",
"are_you_sure": "Bist Du sicher?",
"attributes": "Attribute",
- "avatar": "Avatar",
"back": "Zurück",
"billing": "Abrechnung",
"booked": "Gebucht",
@@ -1111,9 +1110,7 @@
},
"profile": {
"account_deletion_consequences_warning": "Was passiert, wenn Du das Konto löschst",
- "avatar_update_failed": "Aktualisierung des Avatars fehlgeschlagen. Bitte versuche es erneut.",
"backup_code": "Backup-Code",
- "change_image": "Bild ändern",
"confirm_delete_account": "Lösche dein Konto mit all deinen persönlichen Informationen und Daten",
"confirm_delete_my_account": "Konto löschen",
"confirm_your_current_password_to_get_started": "Bestätige dein aktuelles Passwort, um loszulegen.",
@@ -1124,17 +1121,13 @@
"email_change_initiated": "Deine Anfrage zur Änderung der E-Mail wurde eingeleitet.",
"enable_two_factor_authentication": "Zwei-Faktor-Authentifizierung aktivieren",
"enter_the_code_from_your_authenticator_app_below": "Gib den Code aus deiner Authentifizierungs-App unten ein.",
- "file_size_must_be_less_than_10mb": "Dateigröße muss weniger als 10MB sein.",
- "invalid_file_type": "Ungültiger Dateityp. Nur JPEG-, PNG- und WEBP-Dateien sind erlaubt.",
"lost_access": "Zugriff verloren",
"or_enter_the_following_code_manually": "Oder gib den folgenden Code manuell ein:",
- "organization_identification": "Hilf deiner Organisation, Dich auf Formbricks zu identifizieren",
"organizations_delete_message": "Du bist der einzige Besitzer dieser Organisationen, also werden sie auch gelöscht.",
"permanent_removal_of_all_of_your_personal_information_and_data": "Dauerhafte Entfernung all deiner persönlichen Informationen und Daten",
"personal_information": "Persönliche Informationen",
"please_enter_email_to_confirm_account_deletion": "Bitte gib {email} in das folgende Feld ein, um die endgültige Löschung deines Kontos zu bestätigen:",
"profile_updated_successfully": "Dein Profil wurde erfolgreich aktualisiert",
- "remove_image": "Bild entfernen",
"save_the_following_backup_codes_in_a_safe_place": "Speichere die folgenden Backup-Codes an einem sicheren Ort.",
"scan_the_qr_code_below_with_your_authenticator_app": "Scanne den QR-Code unten mit deiner Authentifizierungs-App.",
"security_description": "Verwalte dein Passwort und andere Sicherheitseinstellungen wie Zwei-Faktor-Authentifizierung (2FA).",
@@ -1144,10 +1137,8 @@
"two_factor_code": "Zwei-Faktor-Code",
"unlock_two_factor_authentication": "Zwei-Faktor-Authentifizierung mit einem höheren Plan freischalten",
"update_personal_info": "Persönliche Daten aktualisieren",
- "upload_image": "Bild hochladen",
"warning_cannot_delete_account": "Du bist der einzige Besitzer dieser Organisation. Bitte übertrage das Eigentum zuerst an ein anderes Mitglied.",
- "warning_cannot_undo": "Das kann nicht rückgängig gemacht werden",
- "you_must_select_a_file": "Du musst eine Datei auswählen."
+ "warning_cannot_undo": "Das kann nicht rückgängig gemacht werden"
},
"teams": {
"add_members_description": "Füge Mitglieder zum Team hinzu und bestimme ihre Rolle.",
diff --git a/apps/web/locales/en-US.json b/apps/web/locales/en-US.json
index 17efae6545..877ce7c762 100644
--- a/apps/web/locales/en-US.json
+++ b/apps/web/locales/en-US.json
@@ -141,7 +141,6 @@
"apply_filters": "Apply filters",
"are_you_sure": "Are you sure?",
"attributes": "Attributes",
- "avatar": "Avatar",
"back": "Back",
"billing": "Billing",
"booked": "Booked",
@@ -1111,9 +1110,7 @@
},
"profile": {
"account_deletion_consequences_warning": "Account deletion consequences",
- "avatar_update_failed": "Avatar update failed. Please try again.",
"backup_code": "Backup Code",
- "change_image": "Change image",
"confirm_delete_account": "Delete your account with all of your personal information and data",
"confirm_delete_my_account": "Delete My Account",
"confirm_your_current_password_to_get_started": "Confirm your current password to get started.",
@@ -1124,17 +1121,13 @@
"email_change_initiated": "Your email change request has been initiated.",
"enable_two_factor_authentication": "Enable two factor authentication",
"enter_the_code_from_your_authenticator_app_below": "Enter the code from your authenticator app below.",
- "file_size_must_be_less_than_10mb": "File size must be less than 10MB.",
- "invalid_file_type": "Invalid file type. Only JPEG, PNG, and WEBP files are allowed.",
"lost_access": "Lost access",
"or_enter_the_following_code_manually": "Or enter the following code manually:",
- "organization_identification": "Assist your organization in identifying you on Formbricks",
"organizations_delete_message": "You are the only owner of these organizations, so they will be deleted as well.",
"permanent_removal_of_all_of_your_personal_information_and_data": "Permanent removal of all of your personal information and data",
"personal_information": "Personal information",
"please_enter_email_to_confirm_account_deletion": "Please enter {email} in the following field to confirm the definitive deletion of your account:",
"profile_updated_successfully": "Your profile was updated successfully",
- "remove_image": "Remove image",
"save_the_following_backup_codes_in_a_safe_place": "Save the following backup codes in a safe place.",
"scan_the_qr_code_below_with_your_authenticator_app": "Scan the QR code below with your authenticator app.",
"security_description": "Manage your password and other security settings like two-factor authentication (2FA).",
@@ -1144,10 +1137,8 @@
"two_factor_code": "Two-Factor Code",
"unlock_two_factor_authentication": "Unlock two-factor authentication with a higher plan",
"update_personal_info": "Update your personal information",
- "upload_image": "Upload image",
"warning_cannot_delete_account": "You are the only owner of this organization. Please transfer ownership to another member first.",
- "warning_cannot_undo": "This cannot be undone",
- "you_must_select_a_file": "You must select a file."
+ "warning_cannot_undo": "This cannot be undone"
},
"teams": {
"add_members_description": "Add members to the team and determine their role.",
diff --git a/apps/web/locales/fr-FR.json b/apps/web/locales/fr-FR.json
index db6c01cb44..e09cb93c20 100644
--- a/apps/web/locales/fr-FR.json
+++ b/apps/web/locales/fr-FR.json
@@ -141,7 +141,6 @@
"apply_filters": "Appliquer des filtres",
"are_you_sure": "Es-tu sûr ?",
"attributes": "Attributs",
- "avatar": "Avatar",
"back": "Retour",
"billing": "Facturation",
"booked": "Réservé",
@@ -1111,9 +1110,7 @@
},
"profile": {
"account_deletion_consequences_warning": "Conséquences de la suppression de compte",
- "avatar_update_failed": "La mise à jour de l'avatar a échoué. Veuillez réessayer.",
"backup_code": "Code de sauvegarde",
- "change_image": "Changer l'image",
"confirm_delete_account": "Supprimez votre compte avec toutes vos informations personnelles et données.",
"confirm_delete_my_account": "Supprimer mon compte",
"confirm_your_current_password_to_get_started": "Confirmez votre mot de passe actuel pour commencer.",
@@ -1124,17 +1121,13 @@
"email_change_initiated": "Votre demande de changement d'email a été initiée.",
"enable_two_factor_authentication": "Activer l'authentification à deux facteurs",
"enter_the_code_from_your_authenticator_app_below": "Entrez le code de votre application d'authentification ci-dessous.",
- "file_size_must_be_less_than_10mb": "La taille du fichier doit être inférieure à 10 Mo.",
- "invalid_file_type": "Type de fichier invalide. Seuls les fichiers JPEG, PNG et WEBP sont autorisés.",
"lost_access": "Accès perdu",
"or_enter_the_following_code_manually": "Ou entrez le code suivant manuellement :",
- "organization_identification": "Aidez votre organisation à vous identifier sur Formbricks",
"organizations_delete_message": "Tu es le seul propriétaire de ces organisations, elles seront aussi supprimées.",
"permanent_removal_of_all_of_your_personal_information_and_data": "Suppression permanente de toutes vos informations et données personnelles.",
"personal_information": "Informations personnelles",
"please_enter_email_to_confirm_account_deletion": "Veuillez entrer {email} dans le champ suivant pour confirmer la suppression définitive de votre compte :",
"profile_updated_successfully": "Votre profil a été mis à jour avec succès.",
- "remove_image": "Supprimer l'image",
"save_the_following_backup_codes_in_a_safe_place": "Enregistrez les codes de sauvegarde suivants dans un endroit sûr.",
"scan_the_qr_code_below_with_your_authenticator_app": "Scannez le code QR ci-dessous avec votre application d'authentification.",
"security_description": "Gérez votre mot de passe et d'autres paramètres de sécurité comme l'authentification à deux facteurs (2FA).",
@@ -1144,10 +1137,8 @@
"two_factor_code": "Code à deux facteurs",
"unlock_two_factor_authentication": "Débloquez l'authentification à deux facteurs avec une offre supérieure",
"update_personal_info": "Mettez à jour vos informations personnelles",
- "upload_image": "Télécharger l'image",
"warning_cannot_delete_account": "Tu es le seul propriétaire de cette organisation. Transfère la propriété à un autre membre d'abord.",
- "warning_cannot_undo": "Ceci ne peut pas être annulé",
- "you_must_select_a_file": "Vous devez sélectionner un fichier."
+ "warning_cannot_undo": "Ceci ne peut pas être annulé"
},
"teams": {
"add_members_description": "Ajoutez des membres à l'équipe et déterminez leur rôle.",
diff --git a/apps/web/locales/pt-BR.json b/apps/web/locales/pt-BR.json
index 1d0772ef42..dde37596f1 100644
--- a/apps/web/locales/pt-BR.json
+++ b/apps/web/locales/pt-BR.json
@@ -141,7 +141,6 @@
"apply_filters": "Aplicar filtros",
"are_you_sure": "Certeza?",
"attributes": "atributos",
- "avatar": "Avatar",
"back": "Voltar",
"billing": "Faturamento",
"booked": "Reservado",
@@ -1111,9 +1110,7 @@
},
"profile": {
"account_deletion_consequences_warning": "Consequências da exclusão da conta",
- "avatar_update_failed": "Falha ao atualizar o avatar. Por favor, tente novamente.",
"backup_code": "Código de Backup",
- "change_image": "Mudar imagem",
"confirm_delete_account": "Apague sua conta com todas as suas informações pessoais e dados",
"confirm_delete_my_account": "Excluir Minha Conta",
"confirm_your_current_password_to_get_started": "Confirme sua senha atual para começar.",
@@ -1124,17 +1121,13 @@
"email_change_initiated": "Sua solicitação de alteração de e-mail foi iniciada.",
"enable_two_factor_authentication": "Ativar autenticação de dois fatores",
"enter_the_code_from_your_authenticator_app_below": "Digite o código do seu app autenticador abaixo.",
- "file_size_must_be_less_than_10mb": "O tamanho do arquivo deve ser menor que 10MB.",
- "invalid_file_type": "Tipo de arquivo inválido. Só são permitidos arquivos JPEG, PNG e WEBP.",
"lost_access": "Perdi o acesso",
"or_enter_the_following_code_manually": "Ou insira o seguinte código manualmente:",
- "organization_identification": "Ajude sua organização a te identificar no Formbricks",
"organizations_delete_message": "Você é o único dono dessas organizações, então elas também serão apagadas.",
"permanent_removal_of_all_of_your_personal_information_and_data": "Remoção permanente de todas as suas informações e dados pessoais",
"personal_information": "Informações pessoais",
"please_enter_email_to_confirm_account_deletion": "Por favor, insira {email} no campo abaixo para confirmar a exclusão definitiva da sua conta:",
"profile_updated_successfully": "Seu perfil foi atualizado com sucesso",
- "remove_image": "Remover imagem",
"save_the_following_backup_codes_in_a_safe_place": "Guarde os seguintes códigos de backup em um lugar seguro.",
"scan_the_qr_code_below_with_your_authenticator_app": "Escaneie o código QR abaixo com seu app autenticador.",
"security_description": "Gerencie sua senha e outras configurações de segurança como a autenticação de dois fatores (2FA).",
@@ -1144,10 +1137,8 @@
"two_factor_code": "Código de Dois Fatores",
"unlock_two_factor_authentication": "Desbloqueia a autenticação de dois fatores com um plano melhor",
"update_personal_info": "Atualize suas informações pessoais",
- "upload_image": "Enviar imagem",
"warning_cannot_delete_account": "Você é o único dono desta organização. Transfere a propriedade para outra pessoa primeiro.",
- "warning_cannot_undo": "Isso não pode ser desfeito",
- "you_must_select_a_file": "Você tem que selecionar um arquivo."
+ "warning_cannot_undo": "Isso não pode ser desfeito"
},
"teams": {
"add_members_description": "Adicione membros à equipe e determine sua função.",
diff --git a/apps/web/locales/pt-PT.json b/apps/web/locales/pt-PT.json
index dd7345cb2e..edce6ab083 100644
--- a/apps/web/locales/pt-PT.json
+++ b/apps/web/locales/pt-PT.json
@@ -141,7 +141,6 @@
"apply_filters": "Aplicar filtros",
"are_you_sure": "Tem a certeza?",
"attributes": "Atributos",
- "avatar": "Avatar",
"back": "Voltar",
"billing": "Faturação",
"booked": "Reservado",
@@ -1111,9 +1110,7 @@
},
"profile": {
"account_deletion_consequences_warning": "Consequências da eliminação da conta",
- "avatar_update_failed": "Falha na atualização do avatar. Por favor, tente novamente.",
"backup_code": "Código de Backup",
- "change_image": "Alterar imagem",
"confirm_delete_account": "Eliminar a sua conta com todas as suas informações e dados pessoais",
"confirm_delete_my_account": "Eliminar a Minha Conta",
"confirm_your_current_password_to_get_started": "Confirme a sua palavra-passe atual para começar.",
@@ -1124,17 +1121,13 @@
"email_change_initiated": "O seu pedido de alteração de email foi iniciado.",
"enable_two_factor_authentication": "Ativar autenticação de dois fatores",
"enter_the_code_from_your_authenticator_app_below": "Introduza o código da sua aplicação de autenticação abaixo.",
- "file_size_must_be_less_than_10mb": "O tamanho do ficheiro deve ser inferior a 10MB.",
- "invalid_file_type": "Tipo de ficheiro inválido. Apenas são permitidos ficheiros JPEG, PNG e WEBP.",
"lost_access": "Perdeu o acesso",
"or_enter_the_following_code_manually": "Ou insira o seguinte código manualmente:",
- "organization_identification": "Ajude a sua organização a identificá-lo no Formbricks",
"organizations_delete_message": "É o único proprietário destas organizações, por isso também serão eliminadas.",
"permanent_removal_of_all_of_your_personal_information_and_data": "Remoção permanente de todas as suas informações e dados pessoais",
"personal_information": "Informações pessoais",
"please_enter_email_to_confirm_account_deletion": "Por favor, insira {email} no campo seguinte para confirmar a eliminação definitiva da sua conta:",
"profile_updated_successfully": "O seu perfil foi atualizado com sucesso",
- "remove_image": "Remover imagem",
"save_the_following_backup_codes_in_a_safe_place": "Guarde os seguintes códigos de backup num local seguro.",
"scan_the_qr_code_below_with_your_authenticator_app": "Digitalize o código QR abaixo com a sua aplicação de autenticação.",
"security_description": "Gerir a sua palavra-passe e outras definições de segurança, como a autenticação de dois fatores (2FA).",
@@ -1144,10 +1137,8 @@
"two_factor_code": "Código de Dois Fatores",
"unlock_two_factor_authentication": "Desbloqueie a autenticação de dois fatores com um plano superior",
"update_personal_info": "Atualize as suas informações pessoais",
- "upload_image": "Carregar imagem",
"warning_cannot_delete_account": "É o único proprietário desta organização. Transfira a propriedade para outro membro primeiro.",
- "warning_cannot_undo": "Isto não pode ser desfeito",
- "you_must_select_a_file": "Deve selecionar um ficheiro."
+ "warning_cannot_undo": "Isto não pode ser desfeito"
},
"teams": {
"add_members_description": "Adicionar membros à equipa e determinar o seu papel.",
diff --git a/apps/web/locales/ro-RO.json b/apps/web/locales/ro-RO.json
index a2c55d26a7..af02242cb4 100644
--- a/apps/web/locales/ro-RO.json
+++ b/apps/web/locales/ro-RO.json
@@ -141,7 +141,6 @@
"apply_filters": "Aplică filtre",
"are_you_sure": "Ești sigur?",
"attributes": "Atribute",
- "avatar": "Avatar",
"back": "Înapoi",
"billing": "Facturare",
"booked": "Rezervat",
@@ -1111,9 +1110,7 @@
},
"profile": {
"account_deletion_consequences_warning": "Consecințele ștergerii contului",
- "avatar_update_failed": "Actualizarea avatarului a eșuat. Vă rugăm să încercați din nou.",
"backup_code": "Cod de rezervă",
- "change_image": "Schimbă imaginea",
"confirm_delete_account": "Șterge contul tău cu toate informațiile personale și datele tale",
"confirm_delete_my_account": "Șterge Contul Meu",
"confirm_your_current_password_to_get_started": "Confirmaţi parola curentă pentru a începe.",
@@ -1124,17 +1121,13 @@
"email_change_initiated": "Cererea dvs. de schimbare a e-mailului a fost inițiată.",
"enable_two_factor_authentication": "Activează autentificarea în doi pași",
"enter_the_code_from_your_authenticator_app_below": "Introduceți codul din aplicația dvs. de autentificare mai jos.",
- "file_size_must_be_less_than_10mb": "Dimensiunea fișierului trebuie să fie mai mică de 10MB.",
- "invalid_file_type": "Tip de fișier invalid. Sunt permise numai fișiere JPEG, PNG și WEBP.",
"lost_access": "Acces pierdut",
"or_enter_the_following_code_manually": "Sau introduceți manual următorul cod:",
- "organization_identification": "Ajutați organizația să vă identifice pe Formbricks",
"organizations_delete_message": "Ești singurul proprietar al acestor organizații, deci ele vor fi șterse și ele.",
"permanent_removal_of_all_of_your_personal_information_and_data": "Ștergerea permanentă a tuturor informațiilor și datelor tale personale",
"personal_information": "Informații personale",
"please_enter_email_to_confirm_account_deletion": "Vă rugăm să introduceți {email} în câmpul următor pentru a confirma ștergerea definitivă a contului dumneavoastră:",
"profile_updated_successfully": "Profilul dvs. a fost actualizat cu succes",
- "remove_image": "Șterge imaginea",
"save_the_following_backup_codes_in_a_safe_place": "Salvează următoarele coduri de rezervă într-un loc sigur.",
"scan_the_qr_code_below_with_your_authenticator_app": "Scanați codul QR de mai jos cu aplicația dvs. de autentificare.",
"security_description": "Gestionează parola și alte setări de securitate, precum autentificarea în doi pași (2FA).",
@@ -1144,10 +1137,8 @@
"two_factor_code": "Codul cu doi factori",
"unlock_two_factor_authentication": "Deblocați autentificarea în doi pași cu un plan superior",
"update_personal_info": "Actualizează informațiile tale personale",
- "upload_image": "Încărcați imagine",
"warning_cannot_delete_account": "Ești singurul proprietar al acestei organizații. Te rugăm să transferi proprietatea către un alt membru mai întâi.",
- "warning_cannot_undo": "Aceasta nu poate fi anulată",
- "you_must_select_a_file": "Trebuie să selectați un fișier."
+ "warning_cannot_undo": "Aceasta nu poate fi anulată"
},
"teams": {
"add_members_description": "Adaugă membri în echipă și stabilește rolul lor.",
diff --git a/apps/web/locales/zh-Hant-TW.json b/apps/web/locales/zh-Hant-TW.json
index 73eb4fc6a8..8fc715d0bb 100644
--- a/apps/web/locales/zh-Hant-TW.json
+++ b/apps/web/locales/zh-Hant-TW.json
@@ -141,7 +141,6 @@
"apply_filters": "套用篩選器",
"are_you_sure": "您確定嗎?",
"attributes": "屬性",
- "avatar": "頭像",
"back": "返回",
"billing": "帳單",
"booked": "已預訂",
@@ -1111,9 +1110,7 @@
},
"profile": {
"account_deletion_consequences_warning": "帳戶刪除後果",
- "avatar_update_failed": "頭像更新失敗。請再試一次。",
"backup_code": "備份碼",
- "change_image": "變更圖片",
"confirm_delete_account": "刪除您的帳戶以及您的所有個人資訊和資料",
"confirm_delete_my_account": "刪除我的帳戶",
"confirm_your_current_password_to_get_started": "確認您目前的密碼以開始使用。",
@@ -1124,17 +1121,13 @@
"email_change_initiated": "您的 email 更改請求已啟動。",
"enable_two_factor_authentication": "啟用雙重驗證",
"enter_the_code_from_your_authenticator_app_below": "在下方輸入您驗證器應用程式中的程式碼。",
- "file_size_must_be_less_than_10mb": "檔案大小必須小於 10MB。",
- "invalid_file_type": "無效的檔案類型。僅允許 JPEG、PNG 和 WEBP 檔案。",
"lost_access": "無法存取",
"or_enter_the_following_code_manually": "或手動輸入下列程式碼:",
- "organization_identification": "協助您的組織在 Formbricks 上識別您",
"organizations_delete_message": "您是這些組織的唯一擁有者,因此它們也 將被刪除。",
"permanent_removal_of_all_of_your_personal_information_and_data": "永久移除您的所有個人資訊和資料",
"personal_information": "個人資訊",
"please_enter_email_to_confirm_account_deletion": "請在以下欄位中輸入 '{'email'}' 以確認永久刪除您的帳戶:",
"profile_updated_successfully": "您的個人資料已成功更新",
- "remove_image": "移除圖片",
"save_the_following_backup_codes_in_a_safe_place": "將下列備份碼儲存在安全的地方。",
"scan_the_qr_code_below_with_your_authenticator_app": "使用您的驗證器應用程式掃描下方的 QR 碼。",
"security_description": "管理您的密碼和其他安全性設定,例如雙重驗證 (2FA)。",
@@ -1144,10 +1137,8 @@
"two_factor_code": "雙重驗證碼",
"unlock_two_factor_authentication": "使用更高等級的方案解鎖雙重驗證",
"update_personal_info": "更新您的個人資訊",
- "upload_image": "上傳圖片",
"warning_cannot_delete_account": "您是此組織的唯一擁有者。請先將所有權轉讓給其他成員。",
- "warning_cannot_undo": "此操作無法復原",
- "you_must_select_a_file": "您必須選取檔案。"
+ "warning_cannot_undo": "此操作無法復原"
},
"teams": {
"add_members_description": "將成員新增至團隊並確定其角色。",
diff --git a/apps/web/modules/survey/link/contact-survey/page.test.tsx b/apps/web/modules/survey/link/contact-survey/page.test.tsx
index 585730e80a..c6cec23bc1 100644
--- a/apps/web/modules/survey/link/contact-survey/page.test.tsx
+++ b/apps/web/modules/survey/link/contact-survey/page.test.tsx
@@ -92,7 +92,7 @@ describe("contact-survey page", () => {
params: Promise.resolve({ jwt: "token" }),
searchParams: Promise.resolve({}),
});
- expect(meta).toEqual({ title: "Survey", description: "Complete this survey" });
+ expect(meta).toEqual({ title: "Survey", description: "Please complete this survey." });
});
test("generateMetadata returns default when verify throws", async () => {
@@ -103,7 +103,7 @@ describe("contact-survey page", () => {
params: Promise.resolve({ jwt: "token" }),
searchParams: Promise.resolve({}),
});
- expect(meta).toEqual({ title: "Survey", description: "Complete this survey" });
+ expect(meta).toEqual({ title: "Survey", description: "Please complete this survey." });
});
test("generateMetadata returns basic metadata when token valid", async () => {
diff --git a/apps/web/modules/survey/link/contact-survey/page.tsx b/apps/web/modules/survey/link/contact-survey/page.tsx
index 063b48db04..ec86d6a77a 100644
--- a/apps/web/modules/survey/link/contact-survey/page.tsx
+++ b/apps/web/modules/survey/link/contact-survey/page.tsx
@@ -31,7 +31,7 @@ export const generateMetadata = async (props: ContactSurveyPageProps): Promise {
expect(getSurvey).toHaveBeenCalledWith(mockSurveyId);
expect(result).toEqual({
title: "Survey",
- description: "Complete this survey",
+ description: "Please complete this survey.",
survey: null,
ogImage: undefined,
});
@@ -108,10 +108,9 @@ describe("Metadata Utils", () => {
const result = await getBasicSurveyMetadata(mockSurveyId);
expect(getSurvey).toHaveBeenCalledWith(mockSurveyId);
- expect(getProjectByEnvironmentId).toHaveBeenCalledWith(mockEnvironmentId);
expect(result).toEqual({
- title: "Welcome Headline | Test Project",
- description: "Complete this survey",
+ title: "Welcome Headline",
+ description: "Please complete this survey.",
survey: mockSurvey,
ogImage: undefined,
});
@@ -129,13 +128,12 @@ describe("Metadata Utils", () => {
} as TSurvey;
vi.mocked(getSurvey).mockResolvedValue(mockSurvey);
- vi.mocked(getProjectByEnvironmentId).mockResolvedValue({ name: "Test Project" } as any);
const result = await getBasicSurveyMetadata(mockSurveyId);
expect(result).toEqual({
- title: "Test Survey | Test Project",
- description: "Complete this survey",
+ title: "Test Survey",
+ description: "Please complete this survey.",
survey: mockSurvey,
ogImage: undefined,
});
diff --git a/apps/web/modules/survey/link/lib/metadata-utils.ts b/apps/web/modules/survey/link/lib/metadata-utils.ts
index cf6acc434c..c9bb5327ec 100644
--- a/apps/web/modules/survey/link/lib/metadata-utils.ts
+++ b/apps/web/modules/survey/link/lib/metadata-utils.ts
@@ -1,8 +1,8 @@
import { IS_FORMBRICKS_CLOUD } from "@/lib/constants";
import { getPublicDomain } from "@/lib/getPublicUrl";
+import { getLocalizedValue } from "@/lib/i18n/utils";
import { COLOR_DEFAULTS } from "@/lib/styling/constants";
import { getSurvey } from "@/modules/survey/lib/survey";
-import { getProjectByEnvironmentId } from "@/modules/survey/link/lib/project";
import { Metadata } from "next";
type TBasicSurveyMetadata = {
@@ -12,22 +12,16 @@ type TBasicSurveyMetadata = {
ogImage?: string;
};
-/**
- * Utility function to encode name for URL usage
- */
-export const getNameForURL = (url: string) => url.replace(/ /g, "%20");
+export const getNameForURL = (value: string) => encodeURIComponent(value);
-/**
- * Utility function to encode brand color for URL usage
- */
-export const getBrandColorForURL = (url: string) => url.replace(/#/g, "%23");
+export const getBrandColorForURL = (value: string) => encodeURIComponent(value);
/**
* Get basic survey metadata (title and description) based on link metadata, welcome card or survey name
*/
export const getBasicSurveyMetadata = async (
surveyId: string,
- languageCode?: string
+ languageCode = "default"
): Promise => {
const survey = await getSurvey(surveyId);
@@ -35,7 +29,7 @@ export const getBasicSurveyMetadata = async (
if (!survey) {
return {
title: "Survey",
- description: "Complete this survey",
+ description: "Please complete this survey.",
survey: null,
ogImage: undefined,
};
@@ -43,38 +37,35 @@ export const getBasicSurveyMetadata = async (
const metadata = survey.metadata;
const welcomeCard = survey.welcomeCard;
+ const useDefaultLanguageCode =
+ languageCode === "default" ||
+ survey.languages.find((lang) => lang.language.code === languageCode)?.default;
// Determine language code to use for metadata
- const langCode = languageCode || "default";
+ const langCode = useDefaultLanguageCode ? "default" : languageCode;
// Set title - priority: custom link metadata > welcome card > survey name
- let title = "Survey";
- if (metadata.title?.[langCode]) {
- title = metadata.title[langCode];
- } else if (welcomeCard.enabled && welcomeCard.headline?.default) {
- title = welcomeCard.headline.default;
- } else {
- title = survey.name;
- }
+ const titleFromMetadata = metadata?.title
+ ? getLocalizedValue(metadata.title, langCode) || metadata.title.default
+ : undefined;
+ const titleFromWelcome =
+ welcomeCard?.enabled && welcomeCard.headline
+ ? getLocalizedValue(welcomeCard.headline, langCode) || welcomeCard.headline.default
+ : undefined;
+ let title = titleFromMetadata || titleFromWelcome || survey.name;
// Set description - priority: custom link metadata > welcome card > default
- let description = "Complete this survey";
- if (metadata.description?.[langCode]) {
- description = metadata.description[langCode];
- }
+ const descriptionFromMetadata = metadata?.description
+ ? getLocalizedValue(metadata.description, langCode) || metadata.description.default
+ : undefined;
+ let description = descriptionFromMetadata || "Please complete this survey.";
// Get OG image from link metadata if available
const { ogImage } = metadata;
- // Add product name in title if it's Formbricks cloud and not using custom metadata
- if (!metadata.title?.[langCode]) {
+ if (!titleFromMetadata) {
if (IS_FORMBRICKS_CLOUD) {
title = `${title} | Formbricks`;
- } else {
- const project = await getProjectByEnvironmentId(survey.environmentId);
- if (project) {
- title = `${title} | ${project.name}`;
- }
}
}
@@ -89,10 +80,13 @@ export const getBasicSurveyMetadata = async (
/**
* Generate Open Graph metadata for survey
*/
-export const getSurveyOpenGraphMetadata = (surveyId: string, surveyName: string): Metadata => {
- const brandColor = getBrandColorForURL(COLOR_DEFAULTS.brandColor); // Default color
+export const getSurveyOpenGraphMetadata = (
+ surveyId: string,
+ surveyName: string,
+ surveyBrandColor?: string
+): Metadata => {
const encodedName = getNameForURL(surveyName);
-
+ const brandColor = getBrandColorForURL(surveyBrandColor ?? COLOR_DEFAULTS.brandColor);
const ogImgURL = `/api/v1/client/og?brandColor=${brandColor}&name=${encodedName}`;
return {
diff --git a/apps/web/modules/survey/link/metadata.test.ts b/apps/web/modules/survey/link/metadata.test.ts
index 0ca428b19e..00ff1385cd 100644
--- a/apps/web/modules/survey/link/metadata.test.ts
+++ b/apps/web/modules/survey/link/metadata.test.ts
@@ -20,7 +20,7 @@ vi.mock("./lib/metadata-utils", () => ({
describe("getMetadataForLinkSurvey", () => {
const mockSurveyId = "survey-123";
const mockSurveyName = "Test Survey";
- const mockDescription = "Complete this survey";
+ const mockDescription = "Please complete this survey.";
const mockOgImageUrl = "https://example.com/custom-image.png";
beforeEach(() => {
@@ -60,7 +60,7 @@ describe("getMetadataForLinkSurvey", () => {
expect(getSurveyMetadata).toHaveBeenCalledWith(mockSurveyId);
expect(getBasicSurveyMetadata).toHaveBeenCalledWith(mockSurveyId, undefined);
- expect(getSurveyOpenGraphMetadata).toHaveBeenCalledWith(mockSurveyId, mockSurveyName);
+ expect(getSurveyOpenGraphMetadata).toHaveBeenCalledWith(mockSurveyId, mockSurveyName, undefined);
expect(result).toEqual({
title: mockSurveyName,
diff --git a/apps/web/modules/survey/link/metadata.ts b/apps/web/modules/survey/link/metadata.ts
index 3b63212249..bed68ac462 100644
--- a/apps/web/modules/survey/link/metadata.ts
+++ b/apps/web/modules/survey/link/metadata.ts
@@ -15,9 +15,10 @@ export const getMetadataForLinkSurvey = async (
// Get enhanced metadata that includes custom link metadata
const { title, description, ogImage } = await getBasicSurveyMetadata(surveyId, languageCode);
+ const surveyBrandColor = survey.styling?.brandColor?.light;
// Use the shared function for creating the base metadata but override with custom data
- const baseMetadata = getSurveyOpenGraphMetadata(survey.id, title);
+ const baseMetadata = getSurveyOpenGraphMetadata(survey.id, title, surveyBrandColor);
// Override with the custom image URL
if (baseMetadata.openGraph) {