Compare commits

...

16 Commits

Author SHA1 Message Date
pandeymangg
9525e48da6 chore: merge with main 2025-10-17 23:37:06 +05:30
pandeymangg
defbcad5d7 fix: remove zod import and move to types package 2025-10-17 23:12:53 +05:30
Johannes
11a42c8757 fix to validate email and url with zod, add missing error message via lingo 2025-10-17 15:47:14 +02:00
Aashish
e030cd6cb5 Update open-text-question.tsx
safer, lookbehind-free equivalent:
2025-10-13 14:02:12 +05:30
Aashish
d2f5e21bb6 Update open-text-question.tsx
updated instant brwoser feedback
2025-10-13 13:46:00 +05:30
Aashish
bd218bf96d Update open-text-question.tsx 2025-10-13 13:29:53 +05:30
Aashish-png
7be0ac23b1 Merge branch '6687-invalidEmail' of https://github.com/Aashish-png/formbricks into 6687-invalidEmail 2025-10-13 10:30:18 +05:30
Aashish-png
378f45a102 fix:other invalid format as well 2025-10-13 10:25:48 +05:30
Aashish
8b3e093a81 Update open-text-question.tsx
removed this line input.setCustomValidity("");

since it was alreayd happening inside the handleInputChange
2025-10-13 00:23:33 +05:30
Aashish-png
ae676a340f fixed invalid email #6687 2025-10-13 00:01:44 +05:30
pandeymangg
b5fa058444 adds tests 2025-10-08 12:56:12 +05:30
pandeymangg
1615614d7d useClickOutside 2025-10-07 11:20:16 +05:30
pandeymangg
714f0400b9 removes gitignore addition 2025-10-07 11:15:07 +05:30
pandeymangg
b50ff8335f fixes isDOMElement function 2025-10-07 11:14:16 +05:30
Raghuraj Pratap Singh
f92f4a0fcd Merge branch 'formbricks:main' into fix/sentry-useClickOutside-contains-error 2025-10-01 21:11:39 +05:30
Raghuraj Pratap Singh
f08a10eefc fix: prevent TypeError in useClickOutside hook during component unmounting
- Add DOM element validation before calling contains() method
- Fix race condition where ref.current becomes non-DOM object during React unmounting
- Apply fix to both apps/web and packages/surveys useClickOutside hooks
- Resolves Sentry issue FORMBRICKS-CLOUD-3WH

The issue occurred when React temporarily assigns non-DOM objects to refs
during component unmounting, causing "t.contains is not a function" error.
The fix adds proper validation to ensure contains() is only called on
actual DOM elements.
2025-10-01 15:31:38 +05:30
30 changed files with 566 additions and 62 deletions

View File

@@ -1,5 +1,10 @@
import { RefObject, useEffect } from "react";
// Helper function to check if a value is a DOM element with contains method
const isDOMElement = (element: unknown): element is HTMLElement => {
return element instanceof HTMLElement;
};
// Improved version of https://usehooks.com/useOnClickOutside/
export const useClickOutside = (
ref: RefObject<HTMLElement | HTMLDivElement | null>,
@@ -13,14 +18,14 @@ export const useClickOutside = (
// Do nothing if `mousedown` or `touchstart` started inside ref element
if (startedInside || !startedWhenMounted) return;
// Do nothing if clicking ref's element or descendent elements
if (!ref.current || ref.current.contains(event.target as Node)) return;
if (!isDOMElement(ref.current) || ref.current.contains(event.target as Node)) return;
handler(event);
};
const validateEventStart = (event: MouseEvent | TouchEvent) => {
startedWhenMounted = ref.current !== null;
startedInside = ref.current !== null && ref.current.contains(event.target as Node);
startedWhenMounted = isDOMElement(ref.current);
startedInside = isDOMElement(ref.current) && ref.current.contains(event.target as Node);
};
document.addEventListener("mousedown", validateEventStart);

View File

@@ -279,6 +279,7 @@
"no_result_found": "Kein Ergebnis gefunden",
"no_results": "Keine Ergebnisse",
"no_surveys_found": "Keine Umfragen gefunden.",
"none_of_the_above": "Keine der oben genannten Optionen",
"not_authenticated": "Du bist nicht authentifiziert, um diese Aktion durchzuführen.",
"not_authorized": "Nicht berechtigt",
"not_connected": "Nicht verbunden",
@@ -1203,12 +1204,12 @@
"add_description": "Beschreibung hinzufügen",
"add_ending": "Abschluss hinzufügen",
"add_ending_below": "Abschluss unten hinzufügen",
"add_fallback": "Hinzufügen",
"add_fallback_placeholder": "Hinzufügen eines Platzhalters, der angezeigt wird, wenn die Frage übersprungen wird:",
"add_fallback_placeholder": "Platzhalter hinzufügen, falls kein Wert zur Verfügung steht.",
"add_hidden_field_id": "Verstecktes Feld ID hinzufügen",
"add_highlight_border": "Rahmen hinzufügen",
"add_highlight_border_description": "Füge deiner Umfragekarte einen äußeren Rahmen hinzu.",
"add_logic": "Logik hinzufügen",
"add_none_of_the_above": "Füge \"Keine der oben genannten Optionen\" hinzu",
"add_option": "Option hinzufügen",
"add_other": "Anderes hinzufügen",
"add_photo_or_video": "Foto oder Video hinzufügen",
@@ -1241,6 +1242,7 @@
"automatically_mark_the_survey_as_complete_after": "Umfrage automatisch als abgeschlossen markieren nach",
"back_button_label": "Zurück\"- Button ",
"background_styling": "Hintergründe",
"bold": "Fett",
"brand_color": "Markenfarbe",
"brightness": "Helligkeit",
"button_label": "Beschriftung",
@@ -1313,7 +1315,6 @@
"days_before_showing_this_survey_again": "Tage, bevor diese Umfrage erneut angezeigt wird.",
"decide_how_often_people_can_answer_this_survey": "Entscheide, wie oft Leute diese Umfrage beantworten können.",
"delete_choice": "Auswahl löschen",
"description": "Beschreibung",
"disable_the_visibility_of_survey_progress": "Deaktiviere die Sichtbarkeit des Umfragefortschritts.",
"display_an_estimate_of_completion_time_for_survey": "Zeige eine Schätzung der Fertigstellungszeit für die Umfrage an",
"display_number_of_responses_for_survey": "Anzahl der Antworten für Umfrage anzeigen",
@@ -1324,6 +1325,7 @@
"does_not_include_all_of": "Enthält nicht alle von",
"does_not_include_one_of": "Enthält nicht eines von",
"does_not_start_with": "Fängt nicht an mit",
"edit_link": "Bearbeitungslink",
"edit_recall": "Erinnerung bearbeiten",
"edit_translations": "{lang} -Übersetzungen bearbeiten",
"enable_participants_to_switch_the_survey_language_at_any_point_during_the_survey": "Teilnehmer können die Umfragesprache jederzeit während der Umfrage ändern.",
@@ -1334,13 +1336,13 @@
"ending_card_used_in_logic": "Diese Abschlusskarte wird in der Logik der Frage {questionIndex} verwendet.",
"ending_used_in_quota": "Dieses Ende wird in der \"{quotaName}\" Quote verwendet",
"ends_with": "endet mit",
"enter_fallback_value": "Ersatzwert eingeben",
"equals": "Gleich",
"equals_one_of": "Entspricht einem von",
"error_publishing_survey": "Beim Veröffentlichen der Umfrage ist ein Fehler aufgetreten.",
"error_saving_changes": "Fehler beim Speichern der Änderungen",
"even_after_they_submitted_a_response_e_g_feedback_box": "Sogar nachdem sie eine Antwort eingereicht haben (z.B. Feedback-Box)",
"everyone": "Jeder",
"fallback_for": "Ersatz für",
"fallback_missing": "Fehlender Fallback",
"fieldId_is_used_in_logic_of_question_please_remove_it_from_logic_first": "{fieldId} wird in der Logik der Frage {questionIndex} verwendet. Bitte entferne es zuerst aus der Logik.",
"fieldId_is_used_in_quota_please_remove_it_from_quota_first": "Verstecktes Feld \"{fieldId}\" wird in der \"{quotaName}\" Quote verwendet",
@@ -1397,6 +1399,9 @@
"four_points": "4 Punkte",
"heading": "Überschrift",
"hidden_field_added_successfully": "Verstecktes Feld erfolgreich hinzugefügt",
"hidden_field_used_in_recall": "Verstecktes Feld \"{hiddenField}\" wird in Frage {questionIndex} abgerufen.",
"hidden_field_used_in_recall_ending_card": "Verstecktes Feld \"{hiddenField}\" wird in der Abschlusskarte abgerufen.",
"hidden_field_used_in_recall_welcome": "Verstecktes Feld \"{hiddenField}\" wird in der Willkommenskarte abgerufen.",
"hide_advanced_settings": "Erweiterte Einstellungen ausblenden",
"hide_back_button": "'Zurück'-Button ausblenden",
"hide_back_button_description": "Den Zurück-Button in der Umfrage nicht anzeigen",
@@ -1415,6 +1420,7 @@
"inner_text": "Innerer Text",
"input_border_color": "Randfarbe des Eingabefelds",
"input_color": "Farbe des Eingabefelds",
"insert_link": "Link einfügen",
"invalid_targeting": "Ungültiges Targeting: Bitte überprüfe deine Zielgruppenfilter",
"invalid_video_url_warning": "Bitte gib eine gültige YouTube-, Vimeo- oder Loom-URL ein. Andere Video-Plattformen werden derzeit nicht unterstützt.",
"invalid_youtube_url": "Ungültige YouTube-URL",
@@ -1432,6 +1438,7 @@
"is_set": "Ist festgelegt",
"is_skipped": "Wird übersprungen",
"is_submitted": "Wird eingereicht",
"italic": "Kursiv",
"jump_to_question": "Zur Frage springen",
"keep_current_order": "Bestehende Anordnung beibehalten",
"keep_showing_while_conditions_match": "Zeige weiter, solange die Bedingungen übereinstimmen",
@@ -1458,6 +1465,7 @@
"no_images_found_for": "Keine Bilder gefunden für ''{query}\"",
"no_languages_found_add_first_one_to_get_started": "Keine Sprachen gefunden. Füge die erste hinzu, um loszulegen.",
"no_option_found": "Keine Option gefunden",
"no_recall_items_found": "Keine Erinnerungsstücke gefunden",
"no_variables_yet_add_first_one_below": "Noch keine Variablen. Füge die erste hinzu.",
"number": "Nummer",
"once_set_the_default_language_for_this_survey_can_only_be_changed_by_disabling_the_multi_language_option_and_deleting_all_translations": "Sobald die Standardsprache für diese Umfrage festgelegt ist, kann sie nur geändert werden, indem die Mehrsprachigkeitsoption deaktiviert und alle Übersetzungen gelöscht werden.",
@@ -1477,6 +1485,7 @@
"pin_can_only_contain_numbers": "PIN darf nur Zahlen enthalten.",
"pin_must_be_a_four_digit_number": "Die PIN muss eine vierstellige Zahl sein.",
"please_enter_a_file_extension": "Bitte gib eine Dateierweiterung ein.",
"please_enter_a_valid_url": "Bitte geben Sie eine gültige URL ein (z. B. https://beispiel.de)",
"please_set_a_survey_trigger": "Bitte richte einen Umfrage-Trigger ein",
"please_specify": "Bitte angeben",
"prevent_double_submission": "Doppeltes Anbschicken verhindern",
@@ -1491,6 +1500,8 @@
"question_id_updated": "Frage-ID aktualisiert",
"question_used_in_logic": "Diese Frage wird in der Logik der Frage {questionIndex} verwendet.",
"question_used_in_quota": "Diese Frage wird in der \"{quotaName}\" Quote verwendet",
"question_used_in_recall": "Diese Frage wird in Frage {questionIndex} abgerufen.",
"question_used_in_recall_ending_card": "Diese Frage wird in der Abschlusskarte abgerufen.",
"quotas": {
"add_quota": "Quote hinzufügen",
"change_quota_for_public_survey": "Quote für öffentliche Umfrage ändern?",
@@ -1525,6 +1536,8 @@
"randomize_all": "Alle Optionen zufällig anordnen",
"randomize_all_except_last": "Alle Optionen zufällig anordnen außer der letzten",
"range": "Reichweite",
"recall_data": "Daten abrufen",
"recall_information_from": "Information abrufen von ...",
"recontact_options": "Optionen zur erneuten Kontaktaufnahme",
"redirect_thank_you_card": "Weiterleitung anlegen",
"redirect_to_url": "Zu URL weiterleiten",
@@ -1602,6 +1615,7 @@
"trigger_survey_when_one_of_the_actions_is_fired": "Umfrage auslösen, wenn eine der Aktionen ausgeführt wird...",
"try_lollipop_or_mountain": "Versuch 'Lolli' oder 'Berge'...",
"type_field_id": "Feld-ID eingeben",
"underline": "Unterstreichen",
"unlock_targeting_description": "Spezifische Nutzergruppen basierend auf Attributen oder Geräteinformationen ansprechen",
"unlock_targeting_title": "Targeting mit einem höheren Plan freischalten",
"unsaved_changes_warning": "Du hast ungespeicherte Änderungen in deiner Umfrage. Möchtest Du sie speichern, bevor Du gehst?",
@@ -1618,6 +1632,9 @@
"variable_is_used_in_quota_please_remove_it_from_quota_first": "Variable \"{variableName}\" wird in der \"{quotaName}\" Quote verwendet",
"variable_name_is_already_taken_please_choose_another": "Variablenname ist bereits vergeben, bitte wähle einen anderen.",
"variable_name_must_start_with_a_letter": "Variablenname muss mit einem Buchstaben beginnen.",
"variable_used_in_recall": "Variable \"{variable}\" wird in Frage {questionIndex} abgerufen.",
"variable_used_in_recall_ending_card": "Variable \"{variable}\" wird in der Abschlusskarte abgerufen.",
"variable_used_in_recall_welcome": "Variable \"{variable}\" wird in der Willkommenskarte abgerufen.",
"verify_email_before_submission": "E-Mail vor dem Absenden überprüfen",
"verify_email_before_submission_description": "Lass nur Leute mit einer echten E-Mail antworten.",
"wait": "Warte",

View File

@@ -279,6 +279,7 @@
"no_result_found": "No result found",
"no_results": "No results",
"no_surveys_found": "No surveys found.",
"none_of_the_above": "None of the above",
"not_authenticated": "You are not authenticated to perform this action.",
"not_authorized": "Not authorized",
"not_connected": "Not Connected",
@@ -1203,12 +1204,12 @@
"add_description": "Add description",
"add_ending": "Add ending",
"add_ending_below": "Add ending below",
"add_fallback": "Add",
"add_fallback_placeholder": "Add a placeholder to show if the question gets skipped:",
"add_fallback_placeholder": "Add a placeholder to show if there is no value to recall.",
"add_hidden_field_id": "Add hidden field ID",
"add_highlight_border": "Add highlight border",
"add_highlight_border_description": "Add an outer border to your survey card.",
"add_logic": "Add logic",
"add_none_of_the_above": "Add \"None of the Above\"",
"add_option": "Add option",
"add_other": "Add \"Other\"",
"add_photo_or_video": "Add photo or video",
@@ -1241,6 +1242,7 @@
"automatically_mark_the_survey_as_complete_after": "Automatically mark the survey as complete after",
"back_button_label": "\"Back\" Button Label",
"background_styling": "Background Styling",
"bold": "Bold",
"brand_color": "Brand color",
"brightness": "Brightness",
"button_label": "Button Label",
@@ -1301,8 +1303,8 @@
"contains": "Contains",
"continue_to_settings": "Continue to Settings",
"control_which_file_types_can_be_uploaded": "Control which file types can be uploaded.",
"convert_to_multiple_choice": "Convert to Multiple Choice",
"convert_to_single_choice": "Convert to Single Choice",
"convert_to_multiple_choice": "Convert to Multi-select",
"convert_to_single_choice": "Convert to Single-select",
"country": "Country",
"create_group": "Create group",
"create_your_own_survey": "Create your own survey",
@@ -1313,7 +1315,6 @@
"days_before_showing_this_survey_again": "days before showing this survey again.",
"decide_how_often_people_can_answer_this_survey": "Decide how often people can answer this survey.",
"delete_choice": "Delete choice",
"description": "Description",
"disable_the_visibility_of_survey_progress": "Disable the visibility of survey progress.",
"display_an_estimate_of_completion_time_for_survey": "Display an estimate of completion time for survey",
"display_number_of_responses_for_survey": "Display number of responses for survey",
@@ -1324,6 +1325,7 @@
"does_not_include_all_of": "Does not include all of",
"does_not_include_one_of": "Does not include one of",
"does_not_start_with": "Does not start with",
"edit_link": "Edit link",
"edit_recall": "Edit Recall",
"edit_translations": "Edit {lang} translations",
"enable_participants_to_switch_the_survey_language_at_any_point_during_the_survey": "Enable participants to switch the survey language at any point during the survey.",
@@ -1334,13 +1336,13 @@
"ending_card_used_in_logic": "This ending card is used in logic of question {questionIndex}.",
"ending_used_in_quota": "This ending is being used in \"{quotaName}\" quota",
"ends_with": "Ends with",
"enter_fallback_value": "Enter fallback value",
"equals": "Equals",
"equals_one_of": "Equals one of",
"error_publishing_survey": "An error occured while publishing the survey.",
"error_saving_changes": "Error saving changes",
"even_after_they_submitted_a_response_e_g_feedback_box": "Even after they submitted a response (e.g. Feedback Box)",
"everyone": "Everyone",
"fallback_for": "Fallback for ",
"fallback_missing": "Fallback missing",
"fieldId_is_used_in_logic_of_question_please_remove_it_from_logic_first": "{fieldId} is used in logic of question {questionIndex}. Please remove it from logic first.",
"fieldId_is_used_in_quota_please_remove_it_from_quota_first": "Hidden field \"{fieldId}\" is being used in \"{quotaName}\" quota",
@@ -1397,6 +1399,9 @@
"four_points": "4 points",
"heading": "Heading",
"hidden_field_added_successfully": "Hidden field added successfully",
"hidden_field_used_in_recall": "Hidden field \"{hiddenField}\" is being recalled in question {questionIndex}.",
"hidden_field_used_in_recall_ending_card": "Hidden field \"{hiddenField}\" is being recalled in Ending Card",
"hidden_field_used_in_recall_welcome": "Hidden field \"{hiddenField}\" is being recalled in Welcome card.",
"hide_advanced_settings": "Hide advanced settings",
"hide_back_button": "Hide 'Back' button",
"hide_back_button_description": "Do not display the back button in the survey",
@@ -1415,6 +1420,7 @@
"inner_text": "Inner Text",
"input_border_color": "Input border color",
"input_color": "Input color",
"insert_link": "Insert link",
"invalid_targeting": "Invalid targeting: Please check your audience filters",
"invalid_video_url_warning": "Please enter a valid YouTube, Vimeo, or Loom URL. We currently do not support other video hosting providers.",
"invalid_youtube_url": "Invalid YouTube URL",
@@ -1432,6 +1438,7 @@
"is_set": "Is set",
"is_skipped": "Is skipped",
"is_submitted": "Is submitted",
"italic": "Italic",
"jump_to_question": "Jump to question",
"keep_current_order": "Keep current order",
"keep_showing_while_conditions_match": "Keep showing while conditions match",
@@ -1458,6 +1465,7 @@
"no_images_found_for": "No images found for ''{query}\"",
"no_languages_found_add_first_one_to_get_started": "No languages found. Add the first one to get started.",
"no_option_found": "No option found",
"no_recall_items_found": "No recall items found ",
"no_variables_yet_add_first_one_below": "No variables yet. Add the first one below.",
"number": "Number",
"once_set_the_default_language_for_this_survey_can_only_be_changed_by_disabling_the_multi_language_option_and_deleting_all_translations": "Once set, the default language for this survey can only be changed by disabling the multi-language option and deleting all translations.",
@@ -1477,6 +1485,7 @@
"pin_can_only_contain_numbers": "PIN can only contain numbers.",
"pin_must_be_a_four_digit_number": "PIN must be a four digit number.",
"please_enter_a_file_extension": "Please enter a file extension.",
"please_enter_a_valid_url": "Please enter a valid URL (e.g., https://example.com)",
"please_set_a_survey_trigger": "Please set a survey trigger",
"please_specify": "Please specify",
"prevent_double_submission": "Prevent double submission",
@@ -1491,6 +1500,8 @@
"question_id_updated": "Question ID updated",
"question_used_in_logic": "This question is used in logic of question {questionIndex}.",
"question_used_in_quota": "This question is being used in \"{quotaName}\" quota",
"question_used_in_recall": "This question is being recalled in question {questionIndex}.",
"question_used_in_recall_ending_card": "This question is being recalled in Ending Card",
"quotas": {
"add_quota": "Add quota",
"change_quota_for_public_survey": "Change quota for public survey?",
@@ -1525,6 +1536,8 @@
"randomize_all": "Randomize all",
"randomize_all_except_last": "Randomize all except last",
"range": "Range",
"recall_data": "Recall data",
"recall_information_from": "Recall information from ...",
"recontact_options": "Recontact Options",
"redirect_thank_you_card": "Redirect thank you card",
"redirect_to_url": "Redirect to Url",
@@ -1602,6 +1615,7 @@
"trigger_survey_when_one_of_the_actions_is_fired": "Trigger survey when one of the actions is fired...",
"try_lollipop_or_mountain": "Try 'lollipop' or 'mountain'...",
"type_field_id": "Type field id",
"underline": "Underline",
"unlock_targeting_description": "Target specific user groups based on attributes or device information",
"unlock_targeting_title": "Unlock targeting with a higher plan",
"unsaved_changes_warning": "You have unsaved changes in your survey. Would you like to save them before leaving?",
@@ -1618,6 +1632,9 @@
"variable_is_used_in_quota_please_remove_it_from_quota_first": "Variable \"{variableName}\" is being used in \"{quotaName}\" quota",
"variable_name_is_already_taken_please_choose_another": "Variable name is already taken, please choose another.",
"variable_name_must_start_with_a_letter": "Variable name must start with a letter.",
"variable_used_in_recall": "Variable \"{variable}\" is being recalled in question {questionIndex}.",
"variable_used_in_recall_ending_card": "Variable {variable} is being recalled in Ending Card",
"variable_used_in_recall_welcome": "Variable \"{variable}\" is being recalled in Welcome Card.",
"verify_email_before_submission": "Verify email before submission",
"verify_email_before_submission_description": "Only let people with a real email respond.",
"wait": "Wait",

View File

@@ -279,6 +279,7 @@
"no_result_found": "Aucun résultat trouvé",
"no_results": "Aucun résultat",
"no_surveys_found": "Aucun sondage trouvé.",
"none_of_the_above": "Aucun des éléments ci-dessus",
"not_authenticated": "Vous n'êtes pas authentifié pour effectuer cette action.",
"not_authorized": "Non autorisé",
"not_connected": "Non connecté",
@@ -1203,12 +1204,12 @@
"add_description": "Ajouter une description",
"add_ending": "Ajouter une fin",
"add_ending_below": "Ajouter une fin ci-dessous",
"add_fallback": "Ajouter",
"add_fallback_placeholder": "Ajouter un espace réservé pour montrer si la question est ignorée :",
"add_fallback_placeholder": "Ajouter un espace réservé à afficher s'il n'y a pas de valeur à rappeler.",
"add_hidden_field_id": "Ajouter un champ caché ID",
"add_highlight_border": "Ajouter une bordure de surlignage",
"add_highlight_border_description": "Ajoutez une bordure extérieure à votre carte d'enquête.",
"add_logic": "Ajouter de la logique",
"add_none_of_the_above": "Ajouter \"Aucun des éléments ci-dessus\"",
"add_option": "Ajouter une option",
"add_other": "Ajouter \"Autre",
"add_photo_or_video": "Ajouter une photo ou une vidéo",
@@ -1241,6 +1242,7 @@
"automatically_mark_the_survey_as_complete_after": "Marquer automatiquement l'enquête comme terminée après",
"back_button_label": "Label du bouton \"Retour''",
"background_styling": "Style de fond",
"bold": "Gras",
"brand_color": "Couleur de marque",
"brightness": "Luminosité",
"button_label": "Label du bouton",
@@ -1313,7 +1315,6 @@
"days_before_showing_this_survey_again": "jours avant de montrer à nouveau cette enquête.",
"decide_how_often_people_can_answer_this_survey": "Décidez à quelle fréquence les gens peuvent répondre à cette enquête.",
"delete_choice": "Supprimer l'option",
"description": "Description",
"disable_the_visibility_of_survey_progress": "Désactiver la visibilité de la progression du sondage.",
"display_an_estimate_of_completion_time_for_survey": "Afficher une estimation du temps de complétion pour l'enquête.",
"display_number_of_responses_for_survey": "Afficher le nombre de réponses pour l'enquête",
@@ -1324,6 +1325,7 @@
"does_not_include_all_of": "n'inclut pas tout",
"does_not_include_one_of": "n'inclut pas un de",
"does_not_start_with": "Ne commence pas par",
"edit_link": "Modifier le lien",
"edit_recall": "Modifier le rappel",
"edit_translations": "Modifier les traductions {lang}",
"enable_participants_to_switch_the_survey_language_at_any_point_during_the_survey": "Permettre aux participants de changer la langue de l'enquête à tout moment pendant celle-ci.",
@@ -1334,13 +1336,13 @@
"ending_card_used_in_logic": "Cette carte de fin est utilisée dans la logique de la question '{'questionIndex'}'.",
"ending_used_in_quota": "Cette fin est utilisée dans le quota \"{quotaName}\"",
"ends_with": "Se termine par",
"enter_fallback_value": "Saisir une valeur de secours",
"equals": "Égal",
"equals_one_of": "Égal à l'un de",
"error_publishing_survey": "Une erreur est survenue lors de la publication de l'enquête.",
"error_saving_changes": "Erreur lors de l'enregistrement des modifications",
"even_after_they_submitted_a_response_e_g_feedback_box": "Même après avoir soumis une réponse (par exemple, la boîte de feedback)",
"everyone": "Tout le monde",
"fallback_for": "Solution de repli pour ",
"fallback_missing": "Fallback manquant",
"fieldId_is_used_in_logic_of_question_please_remove_it_from_logic_first": "{fieldId} est utilisé dans la logique de la question {questionIndex}. Veuillez d'abord le supprimer de la logique.",
"fieldId_is_used_in_quota_please_remove_it_from_quota_first": "Le champ masqué \"{fieldId}\" est utilisé dans le quota \"{quotaName}\"",
@@ -1397,6 +1399,9 @@
"four_points": "4 points",
"heading": "En-tête",
"hidden_field_added_successfully": "Champ caché ajouté avec succès",
"hidden_field_used_in_recall": "Le champ caché \"{hiddenField}\" est rappelé dans la question {questionIndex}.",
"hidden_field_used_in_recall_ending_card": "Le champ caché \"{hiddenField}\" est rappelé dans la carte de fin.",
"hidden_field_used_in_recall_welcome": "Le champ caché \"{hiddenField}\" est rappelé dans la carte de bienvenue.",
"hide_advanced_settings": "Cacher les paramètres avancés",
"hide_back_button": "Masquer le bouton 'Retour'",
"hide_back_button_description": "Ne pas afficher le bouton retour dans l'enquête",
@@ -1415,6 +1420,7 @@
"inner_text": "Texte interne",
"input_border_color": "Couleur de bordure d'entrée",
"input_color": "Couleur d'entrée",
"insert_link": "Insérer un lien",
"invalid_targeting": "Ciblage invalide : Veuillez vérifier vos filtres d'audience",
"invalid_video_url_warning": "Merci d'entrer une URL YouTube, Vimeo ou Loom valide. Les autres plateformes vidéo ne sont pas encore supportées.",
"invalid_youtube_url": "URL YouTube invalide",
@@ -1432,6 +1438,7 @@
"is_set": "Est défini",
"is_skipped": "Est ignoré",
"is_submitted": "Est soumis",
"italic": "Italique",
"jump_to_question": "Passer à la question",
"keep_current_order": "Conserver la commande actuelle",
"keep_showing_while_conditions_match": "Continuer à afficher tant que les conditions correspondent",
@@ -1458,6 +1465,7 @@
"no_images_found_for": "Aucune image trouvée pour ''{query}\"",
"no_languages_found_add_first_one_to_get_started": "Aucune langue trouvée. Ajoutez la première pour commencer.",
"no_option_found": "Aucune option trouvée",
"no_recall_items_found": "Aucun élément de rappel trouvé",
"no_variables_yet_add_first_one_below": "Aucune variable pour le moment. Ajoutez la première ci-dessous.",
"number": "Numéro",
"once_set_the_default_language_for_this_survey_can_only_be_changed_by_disabling_the_multi_language_option_and_deleting_all_translations": "Une fois défini, la langue par défaut de cette enquête ne peut être changée qu'en désactivant l'option multilingue et en supprimant toutes les traductions.",
@@ -1477,6 +1485,7 @@
"pin_can_only_contain_numbers": "Le code PIN ne peut contenir que des chiffres.",
"pin_must_be_a_four_digit_number": "Le code PIN doit être un numéro à quatre chiffres.",
"please_enter_a_file_extension": "Veuillez entrer une extension de fichier.",
"please_enter_a_valid_url": "Veuillez entrer une URL valide (par exemple, https://example.com)",
"please_set_a_survey_trigger": "Veuillez définir un déclencheur d'enquête.",
"please_specify": "Veuillez préciser",
"prevent_double_submission": "Empêcher la double soumission",
@@ -1491,6 +1500,8 @@
"question_id_updated": "ID de la question mis à jour",
"question_used_in_logic": "Cette question est utilisée dans la logique de la question '{'questionIndex'}'.",
"question_used_in_quota": "Cette question est utilisée dans le quota \"{quotaName}\"",
"question_used_in_recall": "Cette question est rappelée dans la question {questionIndex}.",
"question_used_in_recall_ending_card": "Cette question est rappelée dans la carte de fin.",
"quotas": {
"add_quota": "Ajouter un quota",
"change_quota_for_public_survey": "Changer le quota pour le sondage public ?",
@@ -1525,6 +1536,8 @@
"randomize_all": "Randomiser tout",
"randomize_all_except_last": "Randomiser tout sauf le dernier",
"range": "Plage",
"recall_data": "Rappel des données",
"recall_information_from": "Rappeler les informations de ...",
"recontact_options": "Options de recontact",
"redirect_thank_you_card": "Carte de remerciement de redirection",
"redirect_to_url": "Rediriger vers l'URL",
@@ -1602,6 +1615,7 @@
"trigger_survey_when_one_of_the_actions_is_fired": "Déclencher l'enquête lorsqu'une des actions est déclenchée...",
"try_lollipop_or_mountain": "Essayez 'sucette' ou 'montagne'...",
"type_field_id": "Identifiant de champ de type",
"underline": "Souligner",
"unlock_targeting_description": "Cibler des groupes d'utilisateurs spécifiques en fonction des attributs ou des informations sur l'appareil",
"unlock_targeting_title": "Débloquez le ciblage avec un plan supérieur.",
"unsaved_changes_warning": "Vous avez des modifications non enregistrées dans votre enquête. Souhaitez-vous les enregistrer avant de partir ?",
@@ -1618,6 +1632,9 @@
"variable_is_used_in_quota_please_remove_it_from_quota_first": "La variable \"{variableName}\" est utilisée dans le quota \"{quotaName}\"",
"variable_name_is_already_taken_please_choose_another": "Le nom de la variable est déjà pris, veuillez en choisir un autre.",
"variable_name_must_start_with_a_letter": "Le nom de la variable doit commencer par une lettre.",
"variable_used_in_recall": "La variable \"{variable}\" est rappelée dans la question {questionIndex}.",
"variable_used_in_recall_ending_card": "La variable {variable} est rappelée dans la carte de fin.",
"variable_used_in_recall_welcome": "La variable \"{variable}\" est rappelée dans la carte de bienvenue.",
"verify_email_before_submission": "Vérifiez l'email avant la soumission",
"verify_email_before_submission_description": "Ne laissez répondre que les personnes ayant une véritable adresse e-mail.",
"wait": "Attendre",

View File

@@ -279,6 +279,7 @@
"no_result_found": "結果が見つかりません",
"no_results": "結果なし",
"no_surveys_found": "フォームが見つかりません。",
"none_of_the_above": "いずれも該当しません",
"not_authenticated": "このアクションを実行するための認証がされていません。",
"not_authorized": "権限がありません",
"not_connected": "未接続",
@@ -1203,12 +1204,12 @@
"add_description": "説明を追加",
"add_ending": "終了を追加",
"add_ending_below": "以下に終了を追加",
"add_fallback": "追加",
"add_fallback_placeholder": "質問がスキップされた場合に表示するプレースホルダーを追加:",
"add_hidden_field_id": "非表示フィールドIDを追加",
"add_highlight_border": "ハイライトボーダーを追加",
"add_highlight_border_description": "フォームカードに外側のボーダーを追加します。",
"add_logic": "ロジックを追加",
"add_none_of_the_above": "\"いずれも該当しません\" を追加",
"add_option": "オプションを追加",
"add_other": "「その他」を追加",
"add_photo_or_video": "写真または動画を追加",
@@ -1241,6 +1242,7 @@
"automatically_mark_the_survey_as_complete_after": "フォームを自動的に完了としてマークする",
"back_button_label": "「戻る」ボタンのラベル",
"background_styling": "背景のスタイル",
"bold": "太字",
"brand_color": "ブランドカラー",
"brightness": "明るさ",
"button_label": "ボタンのラベル",
@@ -1313,7 +1315,6 @@
"days_before_showing_this_survey_again": "日後にこのフォームを再度表示します。",
"decide_how_often_people_can_answer_this_survey": "このフォームに人々が何回回答できるかを決定します。",
"delete_choice": "選択肢を削除",
"description": "説明",
"disable_the_visibility_of_survey_progress": "フォームの進捗状況の表示を無効にする。",
"display_an_estimate_of_completion_time_for_survey": "フォームの完了時間の目安を表示",
"display_number_of_responses_for_survey": "フォームの回答数を表示",
@@ -1324,6 +1325,7 @@
"does_not_include_all_of": "のすべてを含まない",
"does_not_include_one_of": "のいずれも含まない",
"does_not_start_with": "で始まらない",
"edit_link": "編集 リンク",
"edit_recall": "リコールを編集",
"edit_translations": "{lang} 翻訳を編集",
"enable_participants_to_switch_the_survey_language_at_any_point_during_the_survey": "回答者がフォームの途中でいつでも言語を切り替えられるようにします。",
@@ -1334,13 +1336,13 @@
"ending_card_used_in_logic": "この終了カードは質問 {questionIndex} のロジックで使用されています。",
"ending_used_in_quota": "この 終了 は \"{quotaName}\" クォータ で使用されています",
"ends_with": "で終わる",
"enter_fallback_value": "フォールバック値を入力",
"equals": "と等しい",
"equals_one_of": "のいずれかと等しい",
"error_publishing_survey": "フォームの公開中にエラーが発生しました。",
"error_saving_changes": "変更の保存中にエラーが発生しました",
"even_after_they_submitted_a_response_e_g_feedback_box": "回答を送信した後でも(例:フィードバックボックス)",
"everyone": "全員",
"fallback_for": "のフォールバック",
"fallback_missing": "フォールバックがありません",
"fieldId_is_used_in_logic_of_question_please_remove_it_from_logic_first": "{fieldId} は質問 {questionIndex} のロジックで使用されています。まず、ロジックから削除してください。",
"fieldId_is_used_in_quota_please_remove_it_from_quota_first": "隠しフィールド \"{fieldId}\" は \"{quotaName}\" クォータ で使用されています",
@@ -1397,6 +1399,9 @@
"four_points": "4点",
"heading": "見出し",
"hidden_field_added_successfully": "非表示フィールドを正常に追加しました",
"hidden_field_used_in_recall": "隠し フィールド \"{hiddenField}\" が 質問 {questionIndex} で 呼び出され て います 。",
"hidden_field_used_in_recall_ending_card": "隠し フィールド \"{hiddenField}\" が エンディング カード で 呼び出され て います。",
"hidden_field_used_in_recall_welcome": "隠し フィールド \"{hiddenField}\" が ウェルカム カード で 呼び出され て います。",
"hide_advanced_settings": "詳細設定を非表示",
"hide_back_button": "「戻る」ボタンを非表示",
"hide_back_button_description": "フォームに「戻る」ボタンを表示しない",
@@ -1415,6 +1420,7 @@
"inner_text": "内部テキスト",
"input_border_color": "入力の枠線の色",
"input_color": "入力の色",
"insert_link": "リンク を 挿入",
"invalid_targeting": "無効なターゲティング: オーディエンスフィルターを確認してください",
"invalid_video_url_warning": "有効なYouTube、Vimeo、またはLoomのURLを入力してください。現在、他の動画ホスティングプロバイダーはサポートしていません。",
"invalid_youtube_url": "無効なYouTube URL",
@@ -1432,6 +1438,7 @@
"is_set": "設定されている",
"is_skipped": "スキップ済み",
"is_submitted": "送信済み",
"italic": "イタリック",
"jump_to_question": "質問にジャンプ",
"keep_current_order": "現在の順序を維持",
"keep_showing_while_conditions_match": "条件が一致する間、表示し続ける",
@@ -1458,6 +1465,7 @@
"no_images_found_for": "''{query}'' の画像が見つかりません",
"no_languages_found_add_first_one_to_get_started": "言語が見つかりません。始めるには、最初のものを追加してください。",
"no_option_found": "オプションが見つかりません",
"no_recall_items_found": "リコールアイテムが見つかりません ",
"no_variables_yet_add_first_one_below": "まだ変数がありません。以下で最初のものを追加してください。",
"number": "数値",
"once_set_the_default_language_for_this_survey_can_only_be_changed_by_disabling_the_multi_language_option_and_deleting_all_translations": "一度設定すると、このフォームのデフォルト言語は、多言語オプションを無効にしてすべての翻訳を削除することによってのみ変更できます。",
@@ -1477,6 +1485,7 @@
"pin_can_only_contain_numbers": "PINは数字のみでなければなりません。",
"pin_must_be_a_four_digit_number": "PINは4桁の数字でなければなりません。",
"please_enter_a_file_extension": "ファイル拡張子を入力してください。",
"please_enter_a_valid_url": "有効な URL を入力してください (例https://example.com)",
"please_set_a_survey_trigger": "フォームのトリガーを設定してください",
"please_specify": "具体的に指定してください",
"prevent_double_submission": "二重送信を防ぐ",
@@ -1491,6 +1500,8 @@
"question_id_updated": "質問IDを更新しました",
"question_used_in_logic": "この質問は質問 {questionIndex} のロジックで使用されています。",
"question_used_in_quota": "この 質問 は \"{quotaName}\" の クオータ に使用されています",
"question_used_in_recall": "この 質問 は 質問 {questionIndex} で 呼び出され て います 。",
"question_used_in_recall_ending_card": "この 質問 は エンディング カード で 呼び出され て います。",
"quotas": {
"add_quota": "クォータを追加",
"change_quota_for_public_survey": "パブリック フォームのクォータを変更しますか?",
@@ -1525,6 +1536,8 @@
"randomize_all": "すべてをランダム化",
"randomize_all_except_last": "最後を除くすべてをランダム化",
"range": "範囲",
"recall_data": "データを呼び出す",
"recall_information_from": "... からの情報を呼び戻す",
"recontact_options": "再接触オプション",
"redirect_thank_you_card": "サンクスクカードをリダイレクト",
"redirect_to_url": "URLにリダイレクト",
@@ -1602,6 +1615,7 @@
"trigger_survey_when_one_of_the_actions_is_fired": "以下のアクションのいずれかが発火したときにフォームをトリガーします...",
"try_lollipop_or_mountain": "「lollipop」や「mountain」を試してみてください...",
"type_field_id": "フィールドIDを入力",
"underline": "下線",
"unlock_targeting_description": "属性またはデバイス情報に基づいて、特定のユーザーグループをターゲットにします",
"unlock_targeting_title": "上位プランでターゲティングをアンロック",
"unsaved_changes_warning": "フォームに未保存の変更があります。離れる前に保存しますか?",
@@ -1618,6 +1632,9 @@
"variable_is_used_in_quota_please_remove_it_from_quota_first": "変数 \"{variableName}\" は \"{quotaName}\" クォータ で使用されています",
"variable_name_is_already_taken_please_choose_another": "変数名はすでに使用されています。別の名前を選択してください。",
"variable_name_must_start_with_a_letter": "変数名はアルファベットで始まらなければなりません。",
"variable_used_in_recall": "変数 \"{variable}\" が 質問 {questionIndex} で 呼び出され て います 。",
"variable_used_in_recall_ending_card": "変数 {variable} が エンディング カード で 呼び出され て います。",
"variable_used_in_recall_welcome": "変数 \"{variable}\" が ウェルカム カード で 呼び出され て います。",
"verify_email_before_submission": "送信前にメールアドレスを認証",
"verify_email_before_submission_description": "有効なメールアドレスを持つ人のみが回答できるようにする",
"wait": "待つ",

View File

@@ -279,6 +279,7 @@
"no_result_found": "Nenhum resultado encontrado",
"no_results": "Nenhum resultado",
"no_surveys_found": "Não foram encontradas pesquisas.",
"none_of_the_above": "Nenhuma das opções acima",
"not_authenticated": "Você não está autenticado para realizar essa ação.",
"not_authorized": "Não autorizado",
"not_connected": "Desconectado",
@@ -1203,12 +1204,12 @@
"add_description": "Adicionar Descrição",
"add_ending": "Adicionar final",
"add_ending_below": "Adicione o final abaixo",
"add_fallback": "Adicionar",
"add_fallback_placeholder": "Adicionar um texto padrão para mostrar se a pergunta for ignorada:",
"add_hidden_field_id": "Adicionar campo oculto ID",
"add_highlight_border": "Adicionar borda de destaque",
"add_highlight_border_description": "Adicione uma borda externa ao seu cartão de pesquisa.",
"add_logic": "Adicionar lógica",
"add_none_of_the_above": "Adicionar \"Nenhuma das opções acima\"",
"add_option": "Adicionar opção",
"add_other": "Adicionar \"Outro",
"add_photo_or_video": "Adicionar foto ou video",
@@ -1241,6 +1242,7 @@
"automatically_mark_the_survey_as_complete_after": "Marcar automaticamente a pesquisa como concluída após",
"back_button_label": "Voltar",
"background_styling": "Estilo de Fundo",
"bold": "Negrito",
"brand_color": "Cor da marca",
"brightness": "brilho",
"button_label": "Rótulo do Botão",
@@ -1313,7 +1315,6 @@
"days_before_showing_this_survey_again": "dias antes de mostrar essa pesquisa de novo.",
"decide_how_often_people_can_answer_this_survey": "Decida com que frequência as pessoas podem responder a essa pesquisa.",
"delete_choice": "Deletar opção",
"description": "Descrição",
"disable_the_visibility_of_survey_progress": "Desativar a visibilidade do progresso da pesquisa.",
"display_an_estimate_of_completion_time_for_survey": "Mostrar uma estimativa de tempo de conclusão da pesquisa",
"display_number_of_responses_for_survey": "Mostrar número de respostas da pesquisa",
@@ -1324,6 +1325,7 @@
"does_not_include_all_of": "Não inclui todos de",
"does_not_include_one_of": "Não inclui um de",
"does_not_start_with": "Não começa com",
"edit_link": "Editar link",
"edit_recall": "Editar Lembrete",
"edit_translations": "Editar traduções de {lang}",
"enable_participants_to_switch_the_survey_language_at_any_point_during_the_survey": "Permitir que os participantes mudem o idioma da pesquisa a qualquer momento durante a pesquisa.",
@@ -1334,13 +1336,13 @@
"ending_card_used_in_logic": "Esse cartão de encerramento é usado na lógica da pergunta {questionIndex}.",
"ending_used_in_quota": "Este final está sendo usado na cota \"{quotaName}\"",
"ends_with": "Termina com",
"enter_fallback_value": "Insira o valor de fallback",
"equals": "Igual",
"equals_one_of": "É igual a um de",
"error_publishing_survey": "Ocorreu um erro ao publicar a pesquisa.",
"error_saving_changes": "Erro ao salvar alterações",
"even_after_they_submitted_a_response_e_g_feedback_box": "Mesmo depois de eles enviarem uma resposta (por exemplo, Caixa de Feedback)",
"everyone": "Todo mundo",
"fallback_for": "Alternativa para",
"fallback_missing": "Faltando alternativa",
"fieldId_is_used_in_logic_of_question_please_remove_it_from_logic_first": "{fieldId} é usado na lógica da pergunta {questionIndex}. Por favor, remova-o da lógica primeiro.",
"fieldId_is_used_in_quota_please_remove_it_from_quota_first": "Campo oculto \"{fieldId}\" está sendo usado na cota \"{quotaName}\"",
@@ -1397,6 +1399,9 @@
"four_points": "4 pontos",
"heading": "Título",
"hidden_field_added_successfully": "Campo oculto adicionado com sucesso",
"hidden_field_used_in_recall": "Campo oculto \"{hiddenField}\" está sendo recordado na pergunta {questionIndex}.",
"hidden_field_used_in_recall_ending_card": "Campo oculto \"{hiddenField}\" está sendo recordado no card de Encerramento.",
"hidden_field_used_in_recall_welcome": "Campo oculto \"{hiddenField}\" está sendo recordado no card de Boas-Vindas.",
"hide_advanced_settings": "Ocultar configurações avançadas",
"hide_back_button": "Ocultar botão 'Voltar'",
"hide_back_button_description": "Não exibir o botão de voltar na pesquisa",
@@ -1415,6 +1420,7 @@
"inner_text": "Texto Interno",
"input_border_color": "Cor da borda de entrada",
"input_color": "Cor de entrada",
"insert_link": "Inserir link",
"invalid_targeting": "Segmentação inválida: Por favor, verifique os filtros do seu público",
"invalid_video_url_warning": "Por favor, insira uma URL válida do YouTube, Vimeo ou Loom. No momento, não suportamos outros provedores de vídeo.",
"invalid_youtube_url": "URL do YouTube inválida",
@@ -1432,6 +1438,7 @@
"is_set": "Está definido",
"is_skipped": "é pulado",
"is_submitted": "é submetido",
"italic": "Itálico",
"jump_to_question": "Pular para a pergunta",
"keep_current_order": "Manter pedido atual",
"keep_showing_while_conditions_match": "Continue mostrando enquanto as condições corresponderem",
@@ -1458,6 +1465,7 @@
"no_images_found_for": "Nenhuma imagem encontrada para ''{query}\"",
"no_languages_found_add_first_one_to_get_started": "Nenhum idioma encontrado. Adicione o primeiro para começar.",
"no_option_found": "Nenhuma opção encontrada",
"no_recall_items_found": "Nenhum item de recordação encontrado",
"no_variables_yet_add_first_one_below": "Ainda não há variáveis. Adicione a primeira abaixo.",
"number": "Número",
"once_set_the_default_language_for_this_survey_can_only_be_changed_by_disabling_the_multi_language_option_and_deleting_all_translations": "Depois de definido, o idioma padrão desta pesquisa só pode ser alterado desativando a opção de vários idiomas e excluindo todas as traduções.",
@@ -1477,6 +1485,7 @@
"pin_can_only_contain_numbers": "O PIN só pode conter números.",
"pin_must_be_a_four_digit_number": "O PIN deve ser um número de quatro dígitos.",
"please_enter_a_file_extension": "Por favor, insira uma extensão de arquivo.",
"please_enter_a_valid_url": "Por favor, insira uma URL válida (ex.: https://example.com)",
"please_set_a_survey_trigger": "Por favor, configure um gatilho para a pesquisa",
"please_specify": "Por favor, especifique",
"prevent_double_submission": "Evitar envio duplicado",
@@ -1491,6 +1500,8 @@
"question_id_updated": "ID da pergunta atualizado",
"question_used_in_logic": "Essa pergunta é usada na lógica da pergunta {questionIndex}.",
"question_used_in_quota": "Esta questão está sendo usada na cota \"{quotaName}\"",
"question_used_in_recall": "Esta pergunta está sendo recordada na pergunta {questionIndex}.",
"question_used_in_recall_ending_card": "Esta pergunta está sendo recordada no card de Encerramento",
"quotas": {
"add_quota": "Adicionar cota",
"change_quota_for_public_survey": "Alterar cota para pesquisa pública?",
@@ -1525,6 +1536,8 @@
"randomize_all": "Randomizar tudo",
"randomize_all_except_last": "Randomizar tudo, exceto o último",
"range": "alcance",
"recall_data": "Lembrar dados",
"recall_information_from": "Recuperar informações de ...",
"recontact_options": "Opções de Recontato",
"redirect_thank_you_card": "Redirecionar cartão de agradecimento",
"redirect_to_url": "Redirecionar para URL",
@@ -1602,6 +1615,7 @@
"trigger_survey_when_one_of_the_actions_is_fired": "Disparar pesquisa quando uma das ações for executada...",
"try_lollipop_or_mountain": "Tenta 'pirulito' ou 'montanha'...",
"type_field_id": "Digite o id do campo",
"underline": "Sublinhar",
"unlock_targeting_description": "Direcione grupos específicos de usuários com base em atributos ou informações do dispositivo",
"unlock_targeting_title": "Desbloqueie o direcionamento com um plano superior",
"unsaved_changes_warning": "Você tem alterações não salvas na sua pesquisa. Quer salvar antes de sair?",
@@ -1618,6 +1632,9 @@
"variable_is_used_in_quota_please_remove_it_from_quota_first": "Variável \"{variableName}\" está sendo usada na cota \"{quotaName}\"",
"variable_name_is_already_taken_please_choose_another": "O nome da variável já está em uso, por favor escolha outro.",
"variable_name_must_start_with_a_letter": "O nome da variável deve começar com uma letra.",
"variable_used_in_recall": "Variável \"{variable}\" está sendo recordada na pergunta {questionIndex}.",
"variable_used_in_recall_ending_card": "Variável {variable} está sendo recordada no card de Encerramento",
"variable_used_in_recall_welcome": "Variável \"{variable}\" está sendo recordada no Card de Boas-Vindas.",
"verify_email_before_submission": "Verifique o e-mail antes de enviar",
"verify_email_before_submission_description": "Deixe só quem tem um email real responder.",
"wait": "Espera",

View File

@@ -279,6 +279,7 @@
"no_result_found": "Nenhum resultado encontrado",
"no_results": "Nenhum resultado",
"no_surveys_found": "Nenhum inquérito encontrado.",
"none_of_the_above": "Nenhuma das opções acima",
"not_authenticated": "Não está autenticado para realizar esta ação.",
"not_authorized": "Não autorizado",
"not_connected": "Não Conectado",
@@ -1203,12 +1204,12 @@
"add_description": "Adicionar descrição",
"add_ending": "Adicionar encerramento",
"add_ending_below": "Adicionar encerramento abaixo",
"add_fallback": "Adicionar",
"add_fallback_placeholder": "Adicionar um espaço reservado para mostrar se a pergunta for ignorada:",
"add_fallback_placeholder": "Adicionar um espaço reservado para mostrar se não houver valor para recordar.",
"add_hidden_field_id": "Adicionar ID do campo oculto",
"add_highlight_border": "Adicionar borda de destaque",
"add_highlight_border_description": "Adicione uma borda externa ao seu cartão de inquérito.",
"add_logic": "Adicionar lógica",
"add_none_of_the_above": "Adicionar \"Nenhuma das Opções Acima\"",
"add_option": "Adicionar opção",
"add_other": "Adicionar \"Outro\"",
"add_photo_or_video": "Adicionar foto ou vídeo",
@@ -1241,6 +1242,7 @@
"automatically_mark_the_survey_as_complete_after": "Marcar automaticamente o inquérito como concluído após",
"back_button_label": "Rótulo do botão \"Voltar\"",
"background_styling": "Estilo de Fundo",
"bold": "Negrito",
"brand_color": "Cor da marca",
"brightness": "Brilho",
"button_label": "Rótulo do botão",
@@ -1301,8 +1303,8 @@
"contains": "Contém",
"continue_to_settings": "Continuar para Definições",
"control_which_file_types_can_be_uploaded": "Controlar quais tipos de ficheiros podem ser carregados.",
"convert_to_multiple_choice": "Converter para Escolha Múltipla",
"convert_to_single_choice": "Converter para Escolha Única",
"convert_to_multiple_choice": "Converter para Seleção Múltipla",
"convert_to_single_choice": "Converter para Seleção Única",
"country": "País",
"create_group": "Criar grupo",
"create_your_own_survey": "Crie o seu próprio inquérito",
@@ -1313,7 +1315,6 @@
"days_before_showing_this_survey_again": "dias antes de mostrar este inquérito novamente.",
"decide_how_often_people_can_answer_this_survey": "Decida com que frequência as pessoas podem responder a este inquérito.",
"delete_choice": "Eliminar escolha",
"description": "Descrição",
"disable_the_visibility_of_survey_progress": "Desativar a visibilidade do progresso da pesquisa.",
"display_an_estimate_of_completion_time_for_survey": "Mostrar uma estimativa do tempo de conclusão do inquérito",
"display_number_of_responses_for_survey": "Mostrar número de respostas do inquérito",
@@ -1324,6 +1325,7 @@
"does_not_include_all_of": "Não inclui todos de",
"does_not_include_one_of": "Não inclui um de",
"does_not_start_with": "Não começa com",
"edit_link": "Editar link",
"edit_recall": "Editar Lembrete",
"edit_translations": "Editar traduções {lang}",
"enable_participants_to_switch_the_survey_language_at_any_point_during_the_survey": "Permitir aos participantes mudar a língua do inquérito a qualquer momento durante o inquérito.",
@@ -1334,13 +1336,13 @@
"ending_card_used_in_logic": "Este cartão final é usado na lógica da pergunta {questionIndex}.",
"ending_used_in_quota": "Este final está a ser usado na quota \"{quotaName}\"",
"ends_with": "Termina com",
"enter_fallback_value": "Inserir valor de substituição",
"equals": "Igual",
"equals_one_of": "Igual a um de",
"error_publishing_survey": "Ocorreu um erro ao publicar o questionário.",
"error_saving_changes": "Erro ao guardar alterações",
"even_after_they_submitted_a_response_e_g_feedback_box": "Mesmo depois de terem enviado uma resposta (por exemplo, Caixa de Feedback)",
"everyone": "Todos",
"fallback_for": "Alternativa para ",
"fallback_missing": "Substituição em falta",
"fieldId_is_used_in_logic_of_question_please_remove_it_from_logic_first": "{fieldId} é usado na lógica da pergunta {questionIndex}. Por favor, remova-o da lógica primeiro.",
"fieldId_is_used_in_quota_please_remove_it_from_quota_first": "Campo oculto \"{fieldId}\" está a ser usado na quota \"{quotaName}\"",
@@ -1397,6 +1399,9 @@
"four_points": "4 pontos",
"heading": "Cabeçalho",
"hidden_field_added_successfully": "Campo oculto adicionado com sucesso",
"hidden_field_used_in_recall": "Campo oculto \"{hiddenField}\" está a ser recordado na pergunta {questionIndex}.",
"hidden_field_used_in_recall_ending_card": "Campo oculto \"{hiddenField}\" está a ser recordado no Cartão de Conclusão",
"hidden_field_used_in_recall_welcome": "Campo oculto \"{hiddenField}\" está a ser recordado no cartão de boas-vindas.",
"hide_advanced_settings": "Ocultar definições avançadas",
"hide_back_button": "Ocultar botão 'Retroceder'",
"hide_back_button_description": "Não mostrar o botão de retroceder no inquérito",
@@ -1415,6 +1420,7 @@
"inner_text": "Texto Interno",
"input_border_color": "Cor da borda do campo de entrada",
"input_color": "Cor do campo de entrada",
"insert_link": "Inserir ligação",
"invalid_targeting": "Segmentação inválida: Por favor, verifique os seus filtros de audiência",
"invalid_video_url_warning": "Por favor, insira um URL válido do YouTube, Vimeo ou Loom. Atualmente, não suportamos outros fornecedores de hospedagem de vídeo.",
"invalid_youtube_url": "URL do YouTube inválido",
@@ -1432,6 +1438,7 @@
"is_set": "Está definido",
"is_skipped": "É ignorado",
"is_submitted": "Está submetido",
"italic": "Itálico",
"jump_to_question": "Saltar para a pergunta",
"keep_current_order": "Manter ordem atual",
"keep_showing_while_conditions_match": "Continuar a mostrar enquanto as condições corresponderem",
@@ -1458,6 +1465,7 @@
"no_images_found_for": "Não foram encontradas imagens para ''{query}\"",
"no_languages_found_add_first_one_to_get_started": "Nenhuma língua encontrada. Adicione a primeira para começar.",
"no_option_found": "Nenhuma opção encontrada",
"no_recall_items_found": "Nenhum item de recordação encontrado",
"no_variables_yet_add_first_one_below": "Ainda não há variáveis. Adicione a primeira abaixo.",
"number": "Número",
"once_set_the_default_language_for_this_survey_can_only_be_changed_by_disabling_the_multi_language_option_and_deleting_all_translations": "Depois de definido, o idioma padrão desta pesquisa só pode ser alterado desativando a opção de vários idiomas e eliminando todas as traduções.",
@@ -1477,6 +1485,7 @@
"pin_can_only_contain_numbers": "O PIN só pode conter números.",
"pin_must_be_a_four_digit_number": "O PIN deve ser um número de quatro dígitos.",
"please_enter_a_file_extension": "Por favor, insira uma extensão de ficheiro.",
"please_enter_a_valid_url": "Por favor, insira um URL válido (por exemplo, https://example.com)",
"please_set_a_survey_trigger": "Por favor, defina um desencadeador de inquérito",
"please_specify": "Por favor, especifique",
"prevent_double_submission": "Impedir submissão dupla",
@@ -1491,6 +1500,8 @@
"question_id_updated": "ID da pergunta atualizado",
"question_used_in_logic": "Esta pergunta é usada na lógica da pergunta {questionIndex}.",
"question_used_in_quota": "Esta pergunta está a ser usada na quota \"{quotaName}\"",
"question_used_in_recall": "Esta pergunta está a ser recordada na pergunta {questionIndex}.",
"question_used_in_recall_ending_card": "Esta pergunta está a ser recordada no Cartão de Conclusão",
"quotas": {
"add_quota": "Adicionar quota",
"change_quota_for_public_survey": "Alterar quota para inquérito público?",
@@ -1525,6 +1536,8 @@
"randomize_all": "Aleatorizar todos",
"randomize_all_except_last": "Aleatorizar todos exceto o último",
"range": "Intervalo",
"recall_data": "Recuperar dados",
"recall_information_from": "Recordar informação de ...",
"recontact_options": "Opções de Recontacto",
"redirect_thank_you_card": "Redirecionar cartão de agradecimento",
"redirect_to_url": "Redirecionar para Url",
@@ -1602,6 +1615,7 @@
"trigger_survey_when_one_of_the_actions_is_fired": "Desencadear inquérito quando uma das ações for disparada...",
"try_lollipop_or_mountain": "Experimente 'lollipop' ou 'mountain'...",
"type_field_id": "Escreva o id do campo",
"underline": "Sublinhar",
"unlock_targeting_description": "Alvo de grupos de utilizadores específicos com base em atributos ou informações do dispositivo",
"unlock_targeting_title": "Desbloqueie a segmentação com um plano superior",
"unsaved_changes_warning": "Tem alterações não guardadas no seu inquérito. Gostaria de as guardar antes de sair?",
@@ -1618,6 +1632,9 @@
"variable_is_used_in_quota_please_remove_it_from_quota_first": "Variável \"{variableName}\" está a ser utilizada na quota \"{quotaName}\"",
"variable_name_is_already_taken_please_choose_another": "O nome da variável já está em uso, por favor escolha outro.",
"variable_name_must_start_with_a_letter": "O nome da variável deve começar com uma letra.",
"variable_used_in_recall": "Variável \"{variable}\" está a ser recordada na pergunta {questionIndex}.",
"variable_used_in_recall_ending_card": "Variável {variable} está a ser recordada no Cartão de Conclusão",
"variable_used_in_recall_welcome": "Variável \"{variable}\" está a ser recordada no cartão de boas-vindas.",
"verify_email_before_submission": "Verificar email antes da submissão",
"verify_email_before_submission_description": "Permitir apenas que pessoas com um email real respondam.",
"wait": "Aguardar",

View File

@@ -279,6 +279,7 @@
"no_result_found": "Niciun rezultat găsit",
"no_results": "Nicio rezultat",
"no_surveys_found": "Nu au fost găsite sondaje.",
"none_of_the_above": "Niciuna dintre cele de mai sus",
"not_authenticated": "Nu sunteți autentificat pentru a efectua această acțiune.",
"not_authorized": "Neautorizat",
"not_connected": "Neconectat",
@@ -1203,12 +1204,12 @@
"add_description": "Adăugați descriere",
"add_ending": "Adaugă finalizare",
"add_ending_below": "Adaugă finalizare mai jos",
"add_fallback": "Adaugă",
"add_fallback_placeholder": "Adaugă un substituent pentru a afișa dacă întrebarea este omisă:",
"add_fallback_placeholder": "Adaugă un placeholder pentru a afișa dacă nu există valoare de reamintit",
"add_hidden_field_id": "Adăugați ID câmp ascuns",
"add_highlight_border": "Adaugă bordură evidențiată",
"add_highlight_border_description": "Adaugă o margine exterioară cardului tău de sondaj.",
"add_logic": "Adaugă logică",
"add_none_of_the_above": "Adăugați \"Niciuna dintre cele de mai sus\"",
"add_option": "Adăugați opțiune",
"add_other": "Adăugați \"Altele\"",
"add_photo_or_video": "Adaugă fotografie sau video",
@@ -1241,6 +1242,7 @@
"automatically_mark_the_survey_as_complete_after": "Marcați automat sondajul ca finalizat după",
"back_button_label": "Etichetă buton \"Înapoi\"",
"background_styling": "Stilizare fundal",
"bold": "Îngroșat",
"brand_color": "Culoarea brandului",
"brightness": "Luminozitate",
"button_label": "Etichetă buton",
@@ -1301,8 +1303,8 @@
"contains": "Conține",
"continue_to_settings": "Continuă către Setări",
"control_which_file_types_can_be_uploaded": "Controlează ce tipuri de fișiere pot fi încărcate.",
"convert_to_multiple_choice": "Convertiți la alegere multiplă",
"convert_to_single_choice": "Convertiți la alegere unică",
"convert_to_multiple_choice": "Convertiți la selectare multiplă",
"convert_to_single_choice": "Convertiți la selectare unică",
"country": "Țară",
"create_group": "Creează grup",
"create_your_own_survey": "Creează-ți propriul chestionar",
@@ -1313,7 +1315,6 @@
"days_before_showing_this_survey_again": "zile înainte de a afișa din nou acest sondaj.",
"decide_how_often_people_can_answer_this_survey": "Decide cât de des pot răspunde oamenii la acest sondaj",
"delete_choice": "Șterge alegerea",
"description": "Descriere",
"disable_the_visibility_of_survey_progress": "Dezactivați vizibilitatea progresului sondajului",
"display_an_estimate_of_completion_time_for_survey": "Afișează o estimare a timpului de finalizare pentru sondaj",
"display_number_of_responses_for_survey": "Afișează numărul de răspunsuri pentru sondaj",
@@ -1324,6 +1325,7 @@
"does_not_include_all_of": "Nu include toate",
"does_not_include_one_of": "Nu include una dintre",
"does_not_start_with": "Nu începe cu",
"edit_link": "Editare legătură",
"edit_recall": "Editează Referințele",
"edit_translations": "Editează traducerile {lang}",
"enable_participants_to_switch_the_survey_language_at_any_point_during_the_survey": "Permite participanților să schimbe limba sondajului în orice moment în timpul sondajului.",
@@ -1334,13 +1336,13 @@
"ending_card_used_in_logic": "Această carte de încheiere este folosită în logica întrebării {questionIndex}.",
"ending_used_in_quota": "Finalul acesta este folosit în cota \"{quotaName}\"",
"ends_with": "Se termină cu",
"enter_fallback_value": "Introduceți valoarea implicită",
"equals": "Egal",
"equals_one_of": "Egal unu dintre",
"error_publishing_survey": "A apărut o eroare în timpul publicării sondajului.",
"error_saving_changes": "Eroare la salvarea modificărilor",
"even_after_they_submitted_a_response_e_g_feedback_box": "Chiar și după ce au furnizat un răspuns (de ex. Cutia de Feedback)",
"everyone": "Toată lumea",
"fallback_for": "Varianta de rezervă pentru",
"fallback_missing": "Rezerva lipsă",
"fieldId_is_used_in_logic_of_question_please_remove_it_from_logic_first": "{fieldId} este folosit în logică întrebării {questionIndex}. Vă rugăm să-l eliminați din logică mai întâi.",
"fieldId_is_used_in_quota_please_remove_it_from_quota_first": "Câmpul ascuns \"{fieldId}\" este folosit în cota \"{quotaName}\"",
@@ -1397,6 +1399,9 @@
"four_points": "4 puncte",
"heading": "Titlu",
"hidden_field_added_successfully": "Câmp ascuns adăugat cu succes",
"hidden_field_used_in_recall": "Câmpul ascuns \"{hiddenField}\" este reamintit în întrebarea {questionIndex}.",
"hidden_field_used_in_recall_ending_card": "Câmpul ascuns \"{hiddenField}\" este reamintit în Cardul de Încheiere.",
"hidden_field_used_in_recall_welcome": "Câmpul ascuns \"{hiddenField}\" este reamintit în cardul de bun venit.",
"hide_advanced_settings": "Ascunde setări avansate",
"hide_back_button": "Ascunde butonul 'Înapoi'",
"hide_back_button_description": "Nu afișa butonul Înapoi în sondaj",
@@ -1415,6 +1420,7 @@
"inner_text": "Text Interior",
"input_border_color": "Culoarea graniței câmpului de introducere",
"input_color": "Culoarea câmpului de introducere",
"insert_link": "Inserează link",
"invalid_targeting": "\"Targetare nevalidă: Vă rugăm să verificați filtrele pentru audiență\"",
"invalid_video_url_warning": "Vă rugăm să introduceți un URL valid de YouTube, Vimeo sau Loom. În prezent nu susținem alți furnizori de găzduire video.",
"invalid_youtube_url": "URL YouTube invalid",
@@ -1432,6 +1438,7 @@
"is_set": "Este setat",
"is_skipped": "Este sărit",
"is_submitted": "Este trimis",
"italic": "Cursiv",
"jump_to_question": "Sări la întrebare",
"keep_current_order": "Păstrați ordinea actuală",
"keep_showing_while_conditions_match": "Continuă să afișezi cât timp condițiile se potrivesc",
@@ -1458,6 +1465,7 @@
"no_images_found_for": "Nicio imagine găsită pentru ''{query}\"",
"no_languages_found_add_first_one_to_get_started": "Nu s-au găsit limbi. Adaugă prima pentru a începe.",
"no_option_found": "Nicio opțiune găsită",
"no_recall_items_found": "Nu s-au găsit elemente de reamintire",
"no_variables_yet_add_first_one_below": "Nu există variabile încă. Adăugați prima mai jos.",
"number": "Număr",
"once_set_the_default_language_for_this_survey_can_only_be_changed_by_disabling_the_multi_language_option_and_deleting_all_translations": "Odată setată, limba implicită pentru acest sondaj poate fi schimbată doar dezactivând opțiunea multi-limbă și ștergând toate traducerile.",
@@ -1477,6 +1485,7 @@
"pin_can_only_contain_numbers": "PIN-ul poate conține doar numere.",
"pin_must_be_a_four_digit_number": "PIN-ul trebuie să fie un număr de patru cifre",
"please_enter_a_file_extension": "Vă rugăm să introduceți o extensie de fișier.",
"please_enter_a_valid_url": "Vă rugăm să introduceți un URL valid (de exemplu, https://example.com)",
"please_set_a_survey_trigger": "Vă rugăm să setați un declanșator sondaj",
"please_specify": "Vă rugăm să specificați",
"prevent_double_submission": "Prevenire trimitere dublă",
@@ -1491,6 +1500,8 @@
"question_id_updated": "ID întrebare actualizat",
"question_used_in_logic": "Această întrebare este folosită în logica întrebării {questionIndex}.",
"question_used_in_quota": "Întrebarea aceasta este folosită în cota \"{quotaName}\"",
"question_used_in_recall": "Această întrebare este reamintită în întrebarea {questionIndex}.",
"question_used_in_recall_ending_card": "Această întrebare este reamintită în Cardul de Încheiere.",
"quotas": {
"add_quota": "Adăugați cotă",
"change_quota_for_public_survey": "Schimbați cota pentru sondaj public?",
@@ -1525,6 +1536,8 @@
"randomize_all": "Randomizează tot",
"randomize_all_except_last": "Randomizează tot cu excepția ultimului",
"range": "Interval",
"recall_data": "Reamintiți datele",
"recall_information_from": "Reamintiți informațiile din ...",
"recontact_options": "Opțiuni de recontactare",
"redirect_thank_you_card": "Redirecționează cardul de mulțumire",
"redirect_to_url": "Redirecționează către URL",
@@ -1602,6 +1615,7 @@
"trigger_survey_when_one_of_the_actions_is_fired": "Declanșați sondajul atunci când una dintre acțiuni este realizată...",
"try_lollipop_or_mountain": "Încercați „lollipop” sau „mountain”...",
"type_field_id": "ID câmp tip",
"underline": "Subliniază",
"unlock_targeting_description": "Vizează grupuri specifice de utilizatori pe baza atributelor sau a informațiilor despre dispozitiv",
"unlock_targeting_title": "Deblocați țintirea cu un plan superior",
"unsaved_changes_warning": "Aveți modificări nesalvate în sondajul dumneavoastră. Doriți să le salvați înainte de a pleca?",
@@ -1618,6 +1632,9 @@
"variable_is_used_in_quota_please_remove_it_from_quota_first": "Variabila \"{variableName}\" este folosită în cota \"{quotaName}\"",
"variable_name_is_already_taken_please_choose_another": "Numele variabilei este deja utilizat, vă rugăm să alegeți altul.",
"variable_name_must_start_with_a_letter": "Numele variabilei trebuie să înceapă cu o literă.",
"variable_used_in_recall": "Variabila \"{variable}\" este reamintită în întrebarea {questionIndex}.",
"variable_used_in_recall_ending_card": "Variabila {variable} este reamintită în Cardul de Încheiere.",
"variable_used_in_recall_welcome": "Variabila \"{variable}\" este reamintită în cardul de bun venit.",
"verify_email_before_submission": "Verifică emailul înainte de trimitere",
"verify_email_before_submission_description": "Permite doar persoanelor cu un email real să răspundă.",
"wait": "Așteptați",

View File

@@ -279,6 +279,7 @@
"no_result_found": "没有 结果",
"no_results": "没有 结果",
"no_surveys_found": "未找到 调查",
"none_of_the_above": "以上 都 不 是",
"not_authenticated": "您 未 认证 以 执行 该 操作。",
"not_authorized": "未授权",
"not_connected": "未连接",
@@ -1203,12 +1204,12 @@
"add_description": "添加 描述",
"add_ending": "添加结尾",
"add_ending_below": "在下方 添加 结尾",
"add_fallback": "添加",
"add_fallback_placeholder": "添加 一个 占位符,以显示该问题是否被跳过:",
"add_fallback_placeholder": "添加 占位符 显示 如果 没有 值以 回忆",
"add_hidden_field_id": "添加 隐藏 字段 ID",
"add_highlight_border": "添加 高亮 边框",
"add_highlight_border_description": "在 你的 调查 卡片 添加 外 边框。",
"add_logic": "添加逻辑",
"add_none_of_the_above": "添加 “以上 都 不 是”",
"add_option": "添加 选项",
"add_other": "添加 \"其他\"",
"add_photo_or_video": "添加 照片 或 视频",
@@ -1241,6 +1242,7 @@
"automatically_mark_the_survey_as_complete_after": "自动 标记 调查 为 完成 在",
"back_button_label": "\"返回\" 按钮标签",
"background_styling": "背景 样式",
"bold": "粗体",
"brand_color": "品牌 颜色",
"brightness": "亮度",
"button_label": "按钮标签",
@@ -1301,8 +1303,8 @@
"contains": "包含",
"continue_to_settings": "继续 到 设置",
"control_which_file_types_can_be_uploaded": "控制 可以 上传的 文件 类型",
"convert_to_multiple_choice": "转换为多选",
"convert_to_single_choice": "转换为单选",
"convert_to_multiple_choice": "转换为 多选",
"convert_to_single_choice": "转换为 单选",
"country": "国家",
"create_group": "创建 群组",
"create_your_own_survey": "创建 你 的 调查",
@@ -1313,7 +1315,6 @@
"days_before_showing_this_survey_again": "显示 此 调查 之前 的 天数。",
"decide_how_often_people_can_answer_this_survey": "决定 人 可以 回答 这份 调查 的 频率 。",
"delete_choice": "删除 选择",
"description": "描述",
"disable_the_visibility_of_survey_progress": "禁用问卷 进度 的可见性。",
"display_an_estimate_of_completion_time_for_survey": "显示 调查 预计 完成 时间",
"display_number_of_responses_for_survey": "显示 调查 响应 数量",
@@ -1324,6 +1325,7 @@
"does_not_include_all_of": "不包括所有 ",
"does_not_include_one_of": "不包括一 个",
"does_not_start_with": "不 以 开头",
"edit_link": "编辑 链接",
"edit_recall": "编辑 调用",
"edit_translations": "编辑 {lang} 翻译",
"enable_participants_to_switch_the_survey_language_at_any_point_during_the_survey": "启用 参与者 在 调查 过程中 的 任何 时间 点 切换 调查 语言。",
@@ -1334,13 +1336,13 @@
"ending_card_used_in_logic": "\"这个 结束卡片 在 问题 {questionIndex} 的 逻辑 中 使用。\"",
"ending_used_in_quota": "此 结尾 正在 被 \"{quotaName}\" 配额 使用",
"ends_with": "以...结束",
"enter_fallback_value": "输入 后备 值",
"equals": "等于",
"equals_one_of": "等于 其中 一个",
"error_publishing_survey": "发布调查时发生了错误",
"error_saving_changes": "保存 更改 时 出错",
"even_after_they_submitted_a_response_e_g_feedback_box": "即使 他们 提交 了 回复(例如 反馈框)",
"everyone": "所有 人",
"fallback_for": "后备 用于",
"fallback_missing": "备用 缺失",
"fieldId_is_used_in_logic_of_question_please_remove_it_from_logic_first": "\"{fieldId} 在 问题 {questionIndex} 的 逻辑 中 使用。请 先 从 逻辑 中 删除 它。\"",
"fieldId_is_used_in_quota_please_remove_it_from_quota_first": "隐藏 字段 \"{fieldId}\" 正在 被 \"{quotaName}\" 配额 使用",
@@ -1397,6 +1399,9 @@
"four_points": "4 分",
"heading": "标题",
"hidden_field_added_successfully": "隐藏字段 添加成功",
"hidden_field_used_in_recall": "隐藏 字段 \"{hiddenField}\" 正在召回于问题 {questionIndex}。",
"hidden_field_used_in_recall_ending_card": "隐藏 字段 \"{hiddenField}\" 正在召回于结束 卡",
"hidden_field_used_in_recall_welcome": "隐藏 字段 \"{hiddenField}\" 正在召回于欢迎 卡 。",
"hide_advanced_settings": "隐藏 高级设置",
"hide_back_button": "隐藏 \"返回\" 按钮",
"hide_back_button_description": "不 显示 调查 中 的 返回 按钮",
@@ -1415,6 +1420,7 @@
"inner_text": "内文",
"input_border_color": "输入 边框 颜色",
"input_color": "输入颜色",
"insert_link": "插入 链接",
"invalid_targeting": "无效的目标: 请检查 您 的受众过滤器",
"invalid_video_url_warning": "请输入有效的 YouTube、Vimeo 或 Loom URL 。我们目前不支持其他 视频 托管服务提供商。",
"invalid_youtube_url": "无效的 YouTube URL",
@@ -1432,6 +1438,7 @@
"is_set": "已设置",
"is_skipped": "已跳过",
"is_submitted": "已提交",
"italic": "斜体",
"jump_to_question": "跳 转 到 问题",
"keep_current_order": "保持 当前 顺序",
"keep_showing_while_conditions_match": "条件 符合 时 保持 显示",
@@ -1458,6 +1465,7 @@
"no_images_found_for": "未找到与 \"{query}\" 相关的图片",
"no_languages_found_add_first_one_to_get_started": "没有找到语言。添加第一个以开始。",
"no_option_found": "找不到选择",
"no_recall_items_found": "未 找到 召回 项目",
"no_variables_yet_add_first_one_below": "还没有变量。 在下面添加第一个。",
"number": "数字",
"once_set_the_default_language_for_this_survey_can_only_be_changed_by_disabling_the_multi_language_option_and_deleting_all_translations": "一旦设置,此调查的默认语言只能通过禁用多语言选项并删除所有翻译来更改。",
@@ -1477,6 +1485,7 @@
"pin_can_only_contain_numbers": "PIN 只能包含数字。",
"pin_must_be_a_four_digit_number": "PIN 必须是 四 位数字。",
"please_enter_a_file_extension": "请输入 文件 扩展名。",
"please_enter_a_valid_url": "请输入有效的 URL例如 https://example.com ",
"please_set_a_survey_trigger": "请 设置 一个 调查 触发",
"please_specify": "请 指定",
"prevent_double_submission": "防止 重复 提交",
@@ -1491,6 +1500,8 @@
"question_id_updated": "问题 ID 更新",
"question_used_in_logic": "\"这个 问题 在 问题 {questionIndex} 的 逻辑 中 使用。\"",
"question_used_in_quota": "此 问题 正在 被 \"{quotaName}\" 配额 使用",
"question_used_in_recall": "此问题正在召回于问题 {questionIndex}。",
"question_used_in_recall_ending_card": "此 问题 正在召回于结束 卡片。",
"quotas": {
"add_quota": "添加 配额",
"change_quota_for_public_survey": "更改 公共调查 的配额?",
@@ -1525,6 +1536,8 @@
"randomize_all": "随机排列",
"randomize_all_except_last": "随机排列,最后一个除外",
"range": "范围",
"recall_data": "调用 数据",
"recall_information_from": "从 ... 召回信息",
"recontact_options": "重新 联系 选项",
"redirect_thank_you_card": "重定向感谢卡",
"redirect_to_url": "重定向到 URL",
@@ -1602,6 +1615,7 @@
"trigger_survey_when_one_of_the_actions_is_fired": "当 其中 一个 动作 被 触发 时 启动 调查…",
"try_lollipop_or_mountain": "尝试 'lollipop' 或 'mountain' ...",
"type_field_id": "类型 字段 ID",
"underline": "下划线",
"unlock_targeting_description": "根据 属性 或 设备信息 定位 特定 用户组",
"unlock_targeting_title": "通过 更 高级 划解锁 定位",
"unsaved_changes_warning": "您在调查中有未保存的更改。离开前是否要保存?",
@@ -1618,6 +1632,9 @@
"variable_is_used_in_quota_please_remove_it_from_quota_first": "变量 \"{variableName}\" 正在 被 \"{quotaName}\" 配额 使用",
"variable_name_is_already_taken_please_choose_another": "变量名已被占用,请选择其他。",
"variable_name_must_start_with_a_letter": "变量名 必须 以字母开头。",
"variable_used_in_recall": "变量 \"{variable}\" 正在召回于问题 {questionIndex}。",
"variable_used_in_recall_ending_card": "变量 {variable} 正在召回于结束 卡片",
"variable_used_in_recall_welcome": "变量 \"{variable}\" 正在召回于欢迎 卡 。",
"verify_email_before_submission": "提交 之前 验证电子邮件",
"verify_email_before_submission_description": "仅允许 拥有 有效 电子邮件 的 人 回应。",
"wait": "等待",

View File

@@ -279,6 +279,7 @@
"no_result_found": "找不到結果",
"no_results": "沒有結果",
"no_surveys_found": "找不到問卷。",
"none_of_the_above": "以上皆非",
"not_authenticated": "您未經授權執行此操作。",
"not_authorized": "未授權",
"not_connected": "未連線",
@@ -1203,12 +1204,12 @@
"add_description": "新增描述",
"add_ending": "新增結尾",
"add_ending_below": "在下方新增結尾",
"add_fallback": "新增",
"add_fallback_placeholder": "新增用于顯示問題被跳過時的佔位符",
"add_fallback_placeholder": "新增 預設 以顯示是否沒 有 值 可 回憶 。",
"add_hidden_field_id": "新增隱藏欄位 ID",
"add_highlight_border": "新增醒目提示邊框",
"add_highlight_border_description": "在您的問卷卡片新增外邊框。",
"add_logic": "新增邏輯",
"add_none_of_the_above": "新增 \"以上皆非\"",
"add_option": "新增選項",
"add_other": "新增「其他」",
"add_photo_or_video": "新增照片或影片",
@@ -1241,6 +1242,7 @@
"automatically_mark_the_survey_as_complete_after": "在指定時間後自動將問卷標記為完成",
"back_button_label": "「返回」按鈕標籤",
"background_styling": "背景樣式設定",
"bold": "粗體",
"brand_color": "品牌顏色",
"brightness": "亮度",
"button_label": "按鈕標籤",
@@ -1313,7 +1315,6 @@
"days_before_showing_this_survey_again": "天後再次顯示此問卷。",
"decide_how_often_people_can_answer_this_survey": "決定人們可以回答此問卷的頻率。",
"delete_choice": "刪除選項",
"description": "描述",
"disable_the_visibility_of_survey_progress": "停用問卷進度的可見性。",
"display_an_estimate_of_completion_time_for_survey": "顯示問卷的估計完成時間",
"display_number_of_responses_for_survey": "顯示問卷的回應數",
@@ -1324,6 +1325,7 @@
"does_not_include_all_of": "不包含全部",
"does_not_include_one_of": "不包含其中之一",
"does_not_start_with": "不以...開頭",
"edit_link": "編輯 連結",
"edit_recall": "編輯回憶",
"edit_translations": "編輯 '{'language'}' 翻譯",
"enable_participants_to_switch_the_survey_language_at_any_point_during_the_survey": "允許參與者在問卷中的任何時間點切換問卷語言。",
@@ -1334,13 +1336,13 @@
"ending_card_used_in_logic": "此結尾卡片用於問題 '{'questionIndex'}' 的邏輯中。",
"ending_used_in_quota": "此 結尾 正被使用於 \"{quotaName}\" 配額中",
"ends_with": "結尾為",
"enter_fallback_value": "輸入 預設 值",
"equals": "等於",
"equals_one_of": "等於其中之一",
"error_publishing_survey": "發布問卷時發生錯誤。",
"error_saving_changes": "儲存變更時發生錯誤",
"even_after_they_submitted_a_response_e_g_feedback_box": "即使他們提交回應之後(例如,意見反應方塊)",
"everyone": "所有人",
"fallback_for": "備用 用於 ",
"fallback_missing": "遺失的回退",
"fieldId_is_used_in_logic_of_question_please_remove_it_from_logic_first": "'{'fieldId'}' 用於問題 '{'questionIndex'}' 的邏輯中。請先從邏輯中移除。",
"fieldId_is_used_in_quota_please_remove_it_from_quota_first": "隱藏欄位 \"{fieldId}\" 正被使用於 \"{quotaName}\" 配額中",
@@ -1397,6 +1399,9 @@
"four_points": "4 分",
"heading": "標題",
"hidden_field_added_successfully": "隱藏欄位已成功新增",
"hidden_field_used_in_recall": "隱藏欄位 \"{hiddenField}\" 於問題 {questionIndex} 中被召回。",
"hidden_field_used_in_recall_ending_card": "隱藏欄位 \"{hiddenField}\" 於結束卡中被召回。",
"hidden_field_used_in_recall_welcome": "隱藏欄位 \"{hiddenField}\" 於歡迎卡中被召回。",
"hide_advanced_settings": "隱藏進階設定",
"hide_back_button": "隱藏「Back」按鈕",
"hide_back_button_description": "不要在問卷中顯示返回按鈕",
@@ -1415,6 +1420,7 @@
"inner_text": "內部文字",
"input_border_color": "輸入邊框顏色",
"input_color": "輸入顏色",
"insert_link": "插入 連結",
"invalid_targeting": "目標設定無效:請檢查您的受眾篩選器",
"invalid_video_url_warning": "請輸入有效的 YouTube、Vimeo 或 Loom 網址。我們目前不支援其他影片託管提供者。",
"invalid_youtube_url": "無效的 YouTube 網址",
@@ -1432,6 +1438,7 @@
"is_set": "已設定",
"is_skipped": "已跳過",
"is_submitted": "已提交",
"italic": "斜體",
"jump_to_question": "跳至問題",
"keep_current_order": "保留目前順序",
"keep_showing_while_conditions_match": "在條件符合時持續顯示",
@@ -1458,6 +1465,7 @@
"no_images_found_for": "找不到「'{'query'}'」的圖片",
"no_languages_found_add_first_one_to_get_started": "找不到語言。新增第一個語言以開始使用。",
"no_option_found": "找不到選項",
"no_recall_items_found": "找不到 召回 項目",
"no_variables_yet_add_first_one_below": "尚無變數。在下方新增第一個變數。",
"number": "數字",
"once_set_the_default_language_for_this_survey_can_only_be_changed_by_disabling_the_multi_language_option_and_deleting_all_translations": "設定後,此問卷的預設語言只能藉由停用多語言選項並刪除所有翻譯來變更。",
@@ -1477,6 +1485,7 @@
"pin_can_only_contain_numbers": "PIN 碼只能包含數字。",
"pin_must_be_a_four_digit_number": "PIN 碼必須是四位數的數字。",
"please_enter_a_file_extension": "請輸入檔案副檔名。",
"please_enter_a_valid_url": "請輸入有效的 URL例如https://example.com",
"please_set_a_survey_trigger": "請設定問卷觸發器",
"please_specify": "請指定",
"prevent_double_submission": "防止重複提交",
@@ -1491,6 +1500,8 @@
"question_id_updated": "問題 ID 已更新",
"question_used_in_logic": "此問題用於問題 '{'questionIndex'}' 的邏輯中。",
"question_used_in_quota": "此問題 正被使用於 \"{quotaName}\" 配額中",
"question_used_in_recall": "此問題於問題 {questionIndex} 中被召回。",
"question_used_in_recall_ending_card": "此問題於結尾卡中被召回。",
"quotas": {
"add_quota": "新增額度",
"change_quota_for_public_survey": "更改 公開 問卷 的 額度?",
@@ -1525,6 +1536,8 @@
"randomize_all": "全部隨機排序",
"randomize_all_except_last": "全部隨機排序(最後一項除外)",
"range": "範圍",
"recall_data": "回憶數據",
"recall_information_from": "從 ... 獲取 信息",
"recontact_options": "重新聯絡選項",
"redirect_thank_you_card": "重新導向感謝卡片",
"redirect_to_url": "重新導向至網址",
@@ -1602,6 +1615,7 @@
"trigger_survey_when_one_of_the_actions_is_fired": "當觸發其中一個操作時,觸發問卷...",
"try_lollipop_or_mountain": "嘗試「棒棒糖」或「山峰」...",
"type_field_id": "輸入欄位 ID",
"underline": "下 劃 線",
"unlock_targeting_description": "根據屬性或裝置資訊鎖定特定使用者群組",
"unlock_targeting_title": "使用更高等級的方案解鎖目標設定",
"unsaved_changes_warning": "您的問卷中有未儲存的變更。您要先儲存它們再離開嗎?",
@@ -1618,6 +1632,9 @@
"variable_is_used_in_quota_please_remove_it_from_quota_first": "變數 \"{variableName}\" 正被使用於 \"{quotaName}\" 配額中",
"variable_name_is_already_taken_please_choose_another": "已使用此變數名稱,請選擇另一個名稱。",
"variable_name_must_start_with_a_letter": "變數名稱必須以字母開頭。",
"variable_used_in_recall": "變數 \"{variable}\" 於問題 {questionIndex} 中被召回。",
"variable_used_in_recall_ending_card": "變數 {variable} 於 結束 卡 中被召回。",
"variable_used_in_recall_welcome": "變數 \"{variable}\" 於 歡迎 Card 中被召回。",
"verify_email_before_submission": "提交前驗證電子郵件",
"verify_email_before_submission_description": "僅允許擁有真實電子郵件的人員回應。",
"wait": "等待",

View File

@@ -1,11 +1,11 @@
import { getEnabledLanguages } from "@/lib/i18n/utils";
import { useClickOutside } from "@/lib/utils/hooks/useClickOutside";
import { Button } from "@/modules/ui/components/button";
import { Languages } from "lucide-react";
import { useRef, useState } from "react";
import { getLanguageLabel } from "@formbricks/i18n-utils/src/utils";
import { TSurvey } from "@formbricks/types/surveys/types";
import { TUserLocale } from "@formbricks/types/user";
import { getEnabledLanguages } from "@/lib/i18n/utils";
import { useClickOutside } from "@/lib/utils/hooks/useClickOutside";
import { Button } from "@/modules/ui/components/button";
interface LanguageDropdownProps {
survey: TSurvey;

View File

@@ -54,7 +54,9 @@ checksums:
errors/invalid_device_error/message: 8813dcd0e3e41934af18d7a15f8c83f4
errors/invalid_device_error/title: 20d261b478aaba161b0853a588926e23
errors/please_book_an_appointment: 9e8acea3721f660b6a988f79c4105ab8
errors/please_enter_a_valid_email_address: 8de4bc8832b11b380bc4cbcedc16e48b
errors/please_enter_a_valid_phone_number: 1530eb9ab7d6d190bddb37667c711631
errors/please_enter_a_valid_url: e3bcfb605be4ee32aa19d9ac32bb11a4
errors/please_fill_out_this_field: 88d4fd502ae8d423277aef723afcd1a7
errors/please_rank_all_items_before_submitting: 24fb14a2550bd7ec3e253dda0997cea8
errors/please_select_a_date: 1abdc8ffb887dbbdcc0d05486cd84de7

View File

@@ -59,7 +59,9 @@
"title": "هذا الجهاز لا يدعم حماية البريد المزعج."
},
"please_book_an_appointment": "يرجى حجز موعد",
"please_enter_a_valid_email_address": "الرجاء إدخال عنوان بريد إلكتروني صالح",
"please_enter_a_valid_phone_number": "يرجى إدخال رقم هاتف صحيح",
"please_enter_a_valid_url": "الرجاء إدخال عنوان URL صالح",
"please_fill_out_this_field": "يرجى ملء هذا الحقل",
"please_rank_all_items_before_submitting": "يرجى ترتيب جميع العناصر قبل الإرسال",
"please_select_a_date": "يرجى اختيار تاريخ",

View File

@@ -59,7 +59,9 @@
"title": "Dieses Gerät unterstützt keinen Spam-Schutz."
},
"please_book_an_appointment": "Bitte vereinbaren Sie einen Termin",
"please_enter_a_valid_email_address": "Bitte geben Sie eine gültige E-Mail-Adresse ein",
"please_enter_a_valid_phone_number": "Bitte geben Sie eine gültige Telefonnummer ein",
"please_enter_a_valid_url": "Bitte geben Sie eine gültige URL ein",
"please_fill_out_this_field": "Bitte füllen Sie dieses Feld aus",
"please_rank_all_items_before_submitting": "Bitte ordnen Sie alle Elemente vor dem Absenden",
"please_select_a_date": "Bitte wählen Sie ein Datum aus",

View File

@@ -59,7 +59,9 @@
"title": "This device doesnt support spam protection."
},
"please_book_an_appointment": "Please book an appointment",
"please_enter_a_valid_email_address": "Please enter a valid email address",
"please_enter_a_valid_phone_number": "Please enter a valid phone number",
"please_enter_a_valid_url": "Please enter a valid URL",
"please_fill_out_this_field": "Please fill out this field",
"please_rank_all_items_before_submitting": "Please rank all items before submitting",
"please_select_a_date": "Please select a date",

View File

@@ -59,7 +59,9 @@
"title": "Este dispositivo no es compatible con la protección contra spam."
},
"please_book_an_appointment": "Por favor, reserve una cita",
"please_enter_a_valid_email_address": "Por favor, introduce una dirección de correo electrónico válida",
"please_enter_a_valid_phone_number": "Por favor, introduzca un número de teléfono válido",
"please_enter_a_valid_url": "Por favor, introduce una URL válida",
"please_fill_out_this_field": "Por favor, complete este campo",
"please_rank_all_items_before_submitting": "Por favor, clasifique todos los elementos antes de enviar",
"please_select_a_date": "Por favor, seleccione una fecha",

View File

@@ -59,7 +59,9 @@
"title": "Cet appareil ne prend pas en charge la protection contre le spam."
},
"please_book_an_appointment": "Veuillez prendre rendez-vous",
"please_enter_a_valid_email_address": "Veuillez saisir une adresse e-mail valide",
"please_enter_a_valid_phone_number": "Veuillez saisir un numéro de téléphone valide",
"please_enter_a_valid_url": "Veuillez saisir une URL valide",
"please_fill_out_this_field": "Veuillez remplir ce champ",
"please_rank_all_items_before_submitting": "Veuillez classer tous les éléments avant de soumettre",
"please_select_a_date": "Veuillez sélectionner une date",

View File

@@ -59,7 +59,9 @@
"title": "यह डिवाइस स्पैम सुरक्षा का समर्थन नहीं करता है।"
},
"please_book_an_appointment": "कृपया एक अपॉइंटमेंट बुक करें",
"please_enter_a_valid_email_address": "कृपया एक वैध ईमेल पता दर्ज करें",
"please_enter_a_valid_phone_number": "कृपया एक वैध फोन नंबर दर्ज करें",
"please_enter_a_valid_url": "कृपया एक वैध URL दर्ज करें",
"please_fill_out_this_field": "कृपया इस फील्ड को भरें",
"please_rank_all_items_before_submitting": "जमा करने से पहले कृपया सभी आइटम्स को रैंक करें",
"please_select_a_date": "कृपया एक तारीख चुनें",

View File

@@ -59,7 +59,9 @@
"title": "Questo dispositivo non supporta la protezione anti-spam."
},
"please_book_an_appointment": "Prenota un appuntamento",
"please_enter_a_valid_email_address": "Inserisci un indirizzo email valido",
"please_enter_a_valid_phone_number": "Inserisci un numero di telefono valido",
"please_enter_a_valid_url": "Inserisci un URL valido",
"please_fill_out_this_field": "Compila questo campo",
"please_rank_all_items_before_submitting": "Classifica tutti gli elementi prima di inviare",
"please_select_a_date": "Seleziona una data",

View File

@@ -59,7 +59,9 @@
"title": "このデバイスはスパム保護に対応していません。"
},
"please_book_an_appointment": "予約をお取りください",
"please_enter_a_valid_email_address": "有効なメールアドレスを入力してください",
"please_enter_a_valid_phone_number": "有効な電話番号を入力してください",
"please_enter_a_valid_url": "有効なURLを入力してください",
"please_fill_out_this_field": "このフィールドに入力してください",
"please_rank_all_items_before_submitting": "送信する前にすべての項目をランク付けしてください",
"please_select_a_date": "日付を選択してください",

View File

@@ -59,7 +59,9 @@
"title": "Este dispositivo não suporta proteção contra spam."
},
"please_book_an_appointment": "Por favor, marque uma consulta",
"please_enter_a_valid_email_address": "Por favor, insira um endereço de email válido",
"please_enter_a_valid_phone_number": "Por favor, insira um número de telefone válido",
"please_enter_a_valid_url": "Por favor, insira uma URL válida",
"please_fill_out_this_field": "Por favor, preencha este campo",
"please_rank_all_items_before_submitting": "Por favor, classifique todos os itens antes de enviar",
"please_select_a_date": "Por favor, selecione uma data",

View File

@@ -59,7 +59,9 @@
"title": "Acest dispozitiv nu acceptă protecția împotriva spamului."
},
"please_book_an_appointment": "Vă rugăm să faceți o programare",
"please_enter_a_valid_email_address": "Vă rugăm să introduceți o adresă de email validă",
"please_enter_a_valid_phone_number": "Vă rugăm să introduceți un număr de telefon valid",
"please_enter_a_valid_url": "Vă rugăm să introduceți un URL valid",
"please_fill_out_this_field": "Vă rugăm să completați acest câmp",
"please_rank_all_items_before_submitting": "Vă rugăm să clasificați toate elementele înainte de a trimite",
"please_select_a_date": "Vă rugăm să selectați o dată",

View File

@@ -59,7 +59,9 @@
"title": "Это устройство не поддерживает защиту от спама."
},
"please_book_an_appointment": "Пожалуйста, запишитесь на приём",
"please_enter_a_valid_email_address": "Пожалуйста, введите действительный адрес электронной почты",
"please_enter_a_valid_phone_number": "Пожалуйста, введите действительный номер телефона",
"please_enter_a_valid_url": "Пожалуйста, введите действительный URL-адрес",
"please_fill_out_this_field": "Пожалуйста, заполните это поле",
"please_rank_all_items_before_submitting": "Пожалуйста, оцените все элементы перед отправкой",
"please_select_a_date": "Пожалуйста, выберите дату",

View File

@@ -59,7 +59,9 @@
"title": "Ushbu qurilma spam himoyasini qo'llab-quvvatlamaydi."
},
"please_book_an_appointment": "Iltimos, uchrashuvni bron qiling",
"please_enter_a_valid_email_address": "Iltimos, toʻgʻri elektron pochta manzilini kiriting",
"please_enter_a_valid_phone_number": "Iltimos, to'g'ri telefon raqamini kiriting",
"please_enter_a_valid_url": "Iltimos, toʻgʻri URL manzilini kiriting",
"please_fill_out_this_field": "Iltimos, ushbu maydonni to'ldiring",
"please_rank_all_items_before_submitting": "Iltimos, yuborishdan oldin barcha elementlarni baholang",
"please_select_a_date": "Iltimos, sanani tanlang",

View File

@@ -59,7 +59,9 @@
"title": "此设备不支持垃圾邮件保护。"
},
"please_book_an_appointment": "请预约",
"please_enter_a_valid_email_address": "请输入有效的电子邮件地址",
"please_enter_a_valid_phone_number": "请输入有效的电话号码",
"please_enter_a_valid_url": "请输入有效的URL",
"please_fill_out_this_field": "请填写此字段",
"please_rank_all_items_before_submitting": "请在提交之前对所有项目进行排名",
"please_select_a_date": "请选择一个日期",

View File

@@ -1,3 +1,9 @@
import { type RefObject } from "preact";
import { useEffect, useRef, useState } from "preact/hooks";
import { useTranslation } from "react-i18next";
import { ZEmail, ZUrl } from "@formbricks/types/common";
import { type TResponseData, type TResponseTtc } from "@formbricks/types/responses";
import type { TSurveyOpenTextQuestion, TSurveyQuestionId } from "@formbricks/types/surveys/types";
import { BackButton } from "@/components/buttons/back-button";
import { SubmitButton } from "@/components/buttons/submit-button";
import { Headline } from "@/components/general/headline";
@@ -6,11 +12,6 @@ import { Subheader } from "@/components/general/subheader";
import { ScrollableContainer } from "@/components/wrappers/scrollable-container";
import { getLocalizedValue } from "@/lib/i18n";
import { getUpdatedTtc, useTtc } from "@/lib/ttc";
import { type RefObject } from "preact";
import { useEffect, useRef, useState } from "preact/hooks";
import { useTranslation } from "react-i18next";
import { type TResponseData, type TResponseTtc } from "@formbricks/types/responses";
import type { TSurveyOpenTextQuestion, TSurveyQuestionId } from "@formbricks/types/surveys/types";
interface OpenTextQuestionProps {
question: TSurveyOpenTextQuestion;
@@ -52,7 +53,6 @@ export function OpenTextQuestion({
const isCurrent = question.id === currentQuestionId;
useTtc(question.id, ttc, setTtc, startTime, setStartTime, isCurrent);
const { t } = useTranslation();
const inputRef = useRef<HTMLInputElement | HTMLTextAreaElement>(null);
useEffect(() => {
@@ -72,13 +72,38 @@ export function OpenTextQuestion({
const input = inputRef.current;
input?.setCustomValidity("");
// Check required field
if (question.required && (!value || value.trim() === "")) {
input?.setCustomValidity(t("errors.please_fill_out_this_field"));
input?.reportValidity();
return;
}
// at this point, validity is clean
// Validate input format if value is provided
if (value && value.trim() !== "") {
if (question.inputType === "email") {
if (!ZEmail.safeParse(value).success) {
input?.setCustomValidity(t("errors.please_enter_a_valid_email_address"));
input?.reportValidity();
return;
}
} else if (question.inputType === "url") {
if (!ZUrl.safeParse(value).success) {
input?.setCustomValidity(t("errors.please_enter_a_valid_url"));
input?.reportValidity();
return;
}
} else if (question.inputType === "phone") {
const phoneRegex = /^[+]?[\d\s\-()]{7,}$/;
if (!phoneRegex.test(value)) {
input?.setCustomValidity(t("errors.please_enter_a_valid_phone_number"));
input?.reportValidity();
return;
}
}
}
// All validation passed
const updatedTtc = getUpdatedTtc(ttc, question.id, performance.now() - startTime);
setTtc(updatedTtc);
onSubmit({ [question.id]: value }, updatedTtc);
@@ -114,12 +139,21 @@ export function OpenTextQuestion({
value={value ? value : ""}
type={question.inputType}
onInput={(e) => {
handleInputChange(e.currentTarget.value);
const input = e.currentTarget;
handleInputChange(input.value);
// Clear any previous validation errors while typing
input.setCustomValidity("");
}}
className="fb-border-border placeholder:fb-text-placeholder fb-text-subheading focus:fb-border-brand fb-bg-input-bg fb-rounded-custom fb-block fb-w-full fb-border fb-p-2 fb-shadow-sm focus:fb-outline-none focus:fb-ring-0 sm:fb-text-sm"
pattern={question.inputType === "phone" ? "^[0-9+][0-9+\\- ]*[0-9]$" : ".*"}
pattern=".*"
title={
question.inputType === "phone" ? t("errors.please_enter_a_valid_phone_number") : undefined
question.inputType === "phone"
? t("errors.please_enter_a_valid_phone_number")
: question.inputType === "email"
? t("errors.please_enter_a_valid_email_address")
: question.inputType === "url"
? t("errors.please_enter_a_valid_url")
: undefined
}
minLength={question.inputType === "text" ? question.charLimit?.min : undefined}
maxLength={

View File

@@ -0,0 +1,274 @@
import { render } from "@testing-library/preact";
import { useRef } from "preact/hooks";
import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
import { useClickOutside } from "./use-click-outside-hook";
describe("useClickOutside", () => {
let container: HTMLDivElement;
let outsideElement: HTMLDivElement;
beforeEach(() => {
// Create container for testing
container = document.createElement("div");
document.body.appendChild(container);
// Create an outside element
outsideElement = document.createElement("div");
outsideElement.id = "outside";
document.body.appendChild(outsideElement);
});
afterEach(() => {
// Clean up
document.body.removeChild(container);
document.body.removeChild(outsideElement);
vi.clearAllMocks();
});
test("should call handler when clicking outside the ref element", () => {
const handler = vi.fn();
const TestComponent = () => {
const ref = useRef<HTMLDivElement>(null);
useClickOutside(ref, handler);
return (
<div ref={ref} id="inside">
Inside
</div>
);
};
render(<TestComponent />, { container });
// Simulate mousedown and click outside
const mousedownEvent = new MouseEvent("mousedown", { bubbles: true });
Object.defineProperty(mousedownEvent, "target", { value: outsideElement, configurable: true });
document.dispatchEvent(mousedownEvent);
const clickEvent = new MouseEvent("click", { bubbles: true });
Object.defineProperty(clickEvent, "target", { value: outsideElement, configurable: true });
document.dispatchEvent(clickEvent);
expect(handler).toHaveBeenCalledTimes(1);
});
test("should not call handler when clicking inside the ref element", () => {
const handler = vi.fn();
const TestComponent = () => {
const ref = useRef<HTMLDivElement>(null);
useClickOutside(ref, handler);
return (
<div ref={ref} id="inside">
Inside
</div>
);
};
const { container: componentContainer } = render(<TestComponent />, { container });
const insideElement = componentContainer.querySelector("#inside")!;
// Simulate mousedown and click inside
const mousedownEvent = new MouseEvent("mousedown", { bubbles: true });
Object.defineProperty(mousedownEvent, "target", { value: insideElement, configurable: true });
document.dispatchEvent(mousedownEvent);
const clickEvent = new MouseEvent("click", { bubbles: true });
Object.defineProperty(clickEvent, "target", { value: insideElement, configurable: true });
document.dispatchEvent(clickEvent);
expect(handler).not.toHaveBeenCalled();
});
test("should not call handler when mousedown started inside (even if click is outside)", () => {
const handler = vi.fn();
const TestComponent = () => {
const ref = useRef<HTMLDivElement>(null);
useClickOutside(ref, handler);
return (
<div ref={ref} id="inside">
Inside
</div>
);
};
const { container: componentContainer } = render(<TestComponent />, { container });
const insideElement = componentContainer.querySelector("#inside")!;
// Simulate mousedown inside
const mousedownEvent = new MouseEvent("mousedown", { bubbles: true });
Object.defineProperty(mousedownEvent, "target", { value: insideElement, configurable: true });
document.dispatchEvent(mousedownEvent);
// But click outside
const clickEvent = new MouseEvent("click", { bubbles: true });
Object.defineProperty(clickEvent, "target", { value: outsideElement, configurable: true });
document.dispatchEvent(clickEvent);
expect(handler).not.toHaveBeenCalled();
});
test("should handle touch events (touchstart and click)", () => {
const handler = vi.fn();
const TestComponent = () => {
const ref = useRef<HTMLDivElement>(null);
useClickOutside(ref, handler);
return (
<div ref={ref} id="inside">
Inside
</div>
);
};
render(<TestComponent />, { container });
// Simulate touchstart and click outside
const touchstartEvent = new TouchEvent("touchstart", { bubbles: true });
Object.defineProperty(touchstartEvent, "target", { value: outsideElement, configurable: true });
document.dispatchEvent(touchstartEvent);
const clickEvent = new MouseEvent("click", { bubbles: true });
Object.defineProperty(clickEvent, "target", { value: outsideElement, configurable: true });
document.dispatchEvent(clickEvent);
expect(handler).toHaveBeenCalledTimes(1);
});
test("should not call handler when touchstart started inside", () => {
const handler = vi.fn();
const TestComponent = () => {
const ref = useRef<HTMLDivElement>(null);
useClickOutside(ref, handler);
return (
<div ref={ref} id="inside">
Inside
</div>
);
};
const { container: componentContainer } = render(<TestComponent />, { container });
const insideElement = componentContainer.querySelector("#inside")!;
// Simulate touchstart inside
const touchstartEvent = new TouchEvent("touchstart", { bubbles: true });
Object.defineProperty(touchstartEvent, "target", { value: insideElement, configurable: true });
document.dispatchEvent(touchstartEvent);
// Click outside
const clickEvent = new MouseEvent("click", { bubbles: true });
Object.defineProperty(clickEvent, "target", { value: outsideElement, configurable: true });
document.dispatchEvent(clickEvent);
expect(handler).not.toHaveBeenCalled();
});
test("should handle clicks on descendant elements", () => {
const handler = vi.fn();
const TestComponent = () => {
const ref = useRef<HTMLDivElement>(null);
useClickOutside(ref, handler);
return (
<div ref={ref} id="parent">
<div id="child">Child</div>
</div>
);
};
const { container: componentContainer } = render(<TestComponent />, { container });
const childElement = componentContainer.querySelector("#child")!;
// Simulate mousedown and click on child element
const mousedownEvent = new MouseEvent("mousedown", { bubbles: true });
Object.defineProperty(mousedownEvent, "target", { value: childElement, configurable: true });
document.dispatchEvent(mousedownEvent);
const clickEvent = new MouseEvent("click", { bubbles: true });
Object.defineProperty(clickEvent, "target", { value: childElement, configurable: true });
document.dispatchEvent(clickEvent);
expect(handler).not.toHaveBeenCalled();
});
test("should clean up event listeners on unmount", () => {
const handler = vi.fn();
const removeEventListenerSpy = vi.spyOn(document, "removeEventListener");
const TestComponent = () => {
const ref = useRef<HTMLDivElement>(null);
useClickOutside(ref, handler);
return (
<div ref={ref} id="inside">
Inside
</div>
);
};
const { unmount } = render(<TestComponent />, { container });
unmount();
expect(removeEventListenerSpy).toHaveBeenCalledWith("mousedown", expect.any(Function));
expect(removeEventListenerSpy).toHaveBeenCalledWith("touchstart", expect.any(Function));
expect(removeEventListenerSpy).toHaveBeenCalledWith("click", expect.any(Function));
removeEventListenerSpy.mockRestore();
});
test("should not call handler when ref.current is null during click", () => {
const handler = vi.fn();
const TestComponent = () => {
const ref = useRef<HTMLDivElement>(null);
useClickOutside(ref, handler);
return <div id="inside">Inside (no ref)</div>;
};
render(<TestComponent />, { container });
// Simulate mousedown and click outside
const mousedownEvent = new MouseEvent("mousedown", { bubbles: true });
Object.defineProperty(mousedownEvent, "target", { value: outsideElement, configurable: true });
document.dispatchEvent(mousedownEvent);
const clickEvent = new MouseEvent("click", { bubbles: true });
Object.defineProperty(clickEvent, "target", { value: outsideElement, configurable: true });
document.dispatchEvent(clickEvent);
// Handler should not be called because ref.current is null
expect(handler).not.toHaveBeenCalled();
});
test("should handle case when event.target is not a Node", () => {
const handler = vi.fn();
const TestComponent = () => {
const ref = useRef<HTMLDivElement>(null);
useClickOutside(ref, handler);
return (
<div ref={ref} id="inside">
Inside
</div>
);
};
render(<TestComponent />, { container });
// Simulate mousedown with valid target
const mousedownEvent = new MouseEvent("mousedown", { bubbles: true });
Object.defineProperty(mousedownEvent, "target", { value: outsideElement, configurable: true });
document.dispatchEvent(mousedownEvent);
// Simulate click with null target (edge case)
const clickEvent = new MouseEvent("click", { bubbles: true });
Object.defineProperty(clickEvent, "target", { value: null, configurable: true });
document.dispatchEvent(clickEvent);
// Handler should be called because ref.current is valid DOM element
// and event.target (null) is not contained in it
expect(handler).toHaveBeenCalledTimes(1);
});
});

View File

@@ -1,4 +1,5 @@
import { MutableRef, useEffect } from "preact/hooks";
import { isDOMElement } from "@/lib/utils";
// Improved version of https://usehooks.com/useOnClickOutside/
export const useClickOutside = (
@@ -13,14 +14,14 @@ export const useClickOutside = (
// Do nothing if `mousedown` or `touchstart` started inside ref element
if (startedInside || !startedWhenMounted) return;
// Do nothing if clicking ref's element or descendent elements
if (!ref.current || ref.current.contains(event.target as Node)) return;
if (!isDOMElement(ref.current) || ref.current.contains(event.target as Node)) return;
handler(event);
};
const validateEventStart = (event: MouseEvent | TouchEvent) => {
startedWhenMounted = ref.current !== null;
startedInside = ref.current !== null && ref.current.contains(event.target as Node);
startedWhenMounted = isDOMElement(ref.current);
startedInside = isDOMElement(ref.current) && ref.current.contains(event.target as Node);
};
document.addEventListener("mousedown", validateEventStart);

View File

@@ -1,4 +1,3 @@
import { ApiResponse, ApiSuccessResponse } from "@/types/api";
import { type Result, err, ok, wrapThrowsAsync } from "@formbricks/types/error-handlers";
import { type ApiErrorResponse } from "@formbricks/types/errors";
import { type TJsEnvironmentStateSurvey } from "@formbricks/types/js";
@@ -10,6 +9,7 @@ import {
type TSurveyQuestion,
type TSurveyQuestionChoice,
} from "@formbricks/types/surveys/types";
import { ApiResponse, ApiSuccessResponse } from "@/types/api";
export const cn = (...classes: string[]) => {
return classes.filter(Boolean).join(" ");
@@ -197,3 +197,8 @@ export const checkIfSurveyIsRTL = (survey: TJsEnvironmentStateSurvey, languageCo
return false;
};
// Helper function to check if a value is a DOM element with contains method
export const isDOMElement = (element: unknown): element is HTMLElement => {
return element instanceof HTMLElement;
};

View File

@@ -4,6 +4,8 @@ export const ZBoolean = z.boolean();
export const ZString = z.string();
export const ZUrl = z.string().url();
export const ZNumber = z.number();
export const ZOptionalNumber = z.number().optional();
@@ -178,3 +180,5 @@ export const safeUrlRefinement = (url: string, ctx: z.RefinementCtx): void => {
});
}
};
export const ZEmail = z.string().email();