diff --git a/.github/workflows/code-analysis.yml b/.github/workflows/code-analysis.yml index 46a6d8976..279a43ac1 100644 --- a/.github/workflows/code-analysis.yml +++ b/.github/workflows/code-analysis.yml @@ -101,11 +101,11 @@ jobs: - name: Use desired version of NodeJS uses: actions/setup-node@v6 with: - node-version: '18.15.0' + node-version: '24.16.0' cache: 'npm' - name: Install npm dependencies - run: npm ci --legacy-peer-deps + run: npm ci - name: Lint JS run: npm run lint-js diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index ebf7af3d0..ccbe3447d 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -30,10 +30,10 @@ jobs: - name: Checkout uses: actions/checkout@v6 - - name: Setup Node 20 + - name: Setup Node 24 uses: actions/setup-node@v6 with: - node-version: '20.20.1' + node-version: '24.16.0' - name: Restore node_modules cache id: npm-cache @@ -60,7 +60,7 @@ jobs: - name: Install dependencies if: steps.npm-cache.outputs.cache-hit != 'true' - run: npm ci --legacy-peer-deps + run: npm ci - name: Build plugin assets if: steps.build-cache.outputs.cache-hit != 'true' @@ -143,10 +143,10 @@ jobs: - name: Checkout uses: actions/checkout@v6 - - name: Setup Node 20 + - name: Setup Node 24 uses: actions/setup-node@v6 with: - node-version: '20.20.1' + node-version: '24.16.0' - name: Restore node_modules cache id: npm-cache @@ -157,7 +157,7 @@ jobs: - name: Install dependencies if: steps.npm-cache.outputs.cache-hit != 'true' - run: npm ci --legacy-peer-deps + run: npm ci - name: Download blob reports from all shards uses: actions/download-artifact@v8 diff --git a/.nvmrc b/.nvmrc index 1e24c0215..1ec89699e 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -18.15.0 \ No newline at end of file +24.16.0 \ No newline at end of file diff --git a/README.md b/README.md index 4d24eb801..afb1383ac 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,14 @@ -# SureForms - Drag & Drop Contact Form, Payment Form, Survey, Quiz, Calculator & Custom Form Builder # +# SureForms - Drag & Drop Contact Form & Form Builder, Payment Form, Survey, Quiz & Calculator # **Contributors:** [brainstormforce](https://profiles.wordpress.org/brainstormforce/) **Tags:** forms, contact form, form builder, survey, payment form **Requires at least:** 6.4 **Tested up to:** 7.0 **Requires PHP:** 7.4 -**Stable tag:** 2.11.0 +**Stable tag:** 2.11.1 **License:** GPLv2 or later **License URI:** http://www.gnu.org/licenses/gpl-2.0.html -The AI-powered WordPress form builder. Build contact, payment, quiz, survey & multi-step forms in minutes, no code needed. +AI WordPress form builder. Create contact forms, payment forms, surveys, quizzes & multi-step forms โ€” drag & drop, no code. ## Description ## @@ -26,23 +26,13 @@ Trusted by **500,000+ websites**, SureForms is the modern alternative to traditi ### CREATE BEAUTIFUL RESPONSIVE FORMS USING WORDPRESS BLOCK EDITOR (GUTENBERG EDITOR) WITHOUT CODING โšก -Our mission at SureForms is to empower you to build **beautiful WordPress forms without any code**. +Our mission at SureForms is to empower you to build **beautiful contact forms and custom WordPress forms without any code**. We're taking a fresh approach with Gutenberg, WordPress's native drag-and-drop builder, to make creating contact forms and custom forms seamless and intuitive โ€” with no new interface to learn. SureForms is a beginner-friendly WordPress form plugin that makes building contact forms and other high-converting custom forms fast and simple, with advanced features like multi-step forms, conversational forms, payment forms, conditional logic, calculations, native integrations, and more. -Good design and user experience are crucial for forms. Yet many website owners struggle to make their forms blend seamlessly with their site's look and feel, often leading to lower response rates. - -In this regard, SureForms addresses several pain points commonly experienced by WordPress users: - -- Complex Process of Form Building -- Design Limitations -- Lack of Mobile-friendliness and Accessibility -- Limited Engagement in Their Forms -- Spam and Security Issues - -SureForms is packed with features to address these pain points of WordPress users. +Good design and user experience are crucial for contact forms. Yet many website owners struggle to make their contact forms blend seamlessly with their site's look and feel, often leading to lower response rates. ### POWERFUL FEATURES OF SUREFORMS ๐Ÿ’ช @@ -95,7 +85,7 @@ With SureForms' own Instant Form feature, you can publish forms with a unique sh #### Mobile-Friendly Responsive Forms -SureForms recognizes the importance of mobile-friendly forms. Every form created with SureForms is designed with a mobile-first approach, ensuring it looks and functions flawlessly on phones, tablets, and desktops alike. +SureForms recognizes the importance of mobile-friendly contact forms. Every form created with SureForms is designed with a mobile-first approach, ensuring it looks and functions flawlessly on phones, tablets, and desktops alike. #### Multi-Column Form Layouts @@ -221,7 +211,7 @@ Let users save their progress and come back to complete the form later. Capture in-progress form submissions automatically โ€” recover abandoned forms and follow up with users who dropped off before completing. **Form Restrictions:** -Restrict form visibility and submissions by IP address, country, keywords, user login status, or password. Set submission limits per day, week, month, year, or lifetime. +Restrict form visibility and submissions by IP address, country, keywords, user login status, or password โ€” with regex support for advanced validation. Set submission limits per day, week, month, year, or lifetime. [**Custom Registration & Login Forms**](https://sureforms.com/features/login-and-registration/?utm_source=wordpress.org&utm_medium=registration_login): Fully functional, branded Registration and Login forms for your WordPress site using just a block. @@ -229,9 +219,6 @@ Fully functional, branded Registration and Login forms for your WordPress site u [**Custom Post Type Creation**](https://sureforms.com/features/post-creation/?utm_source=wordpress.org&utm_medium=post_creation): Create WordPress posts or custom post types directly from form submissions. -**Field Restrictions:** -Restrict form submissions by IP, country, keywords, user login, or password โ€” with regex support for advanced validation. - **Conditional Emails & Confirmations:** Send different email notifications and show different confirmation messages based on form field values. @@ -246,34 +233,7 @@ Customize form appearance with advanced styling options when embedding forms via [**Advanced Native Integrations**](https://sureforms.com/integrations/?utm_source=wordpress.org&utm_medium=integrations): Connect your forms natively with top apps and services to automate workflows and save time โ€” no third-party add-ons or plugins required. -SureForms connects natively with: -- Google Sheets -- Mailchimp -- FluentCRM -- Telegram -- HubSpot -- MailerLite -- Brevo (Sendinblue) -- ActiveCampaign -- Kit -- GetResponse -- Airtable -- MailJet -- Campaign Monitor -- Drip -- Salesflare -- Breeze -- Latepoint -- Hostinger Reach -- AgileCRM -- WPFusion -- Klaviyo -- Keap -- Notion -- MailPoet -- MailerPress -- Zoho CRM -- SureContact +SureForms connects natively with Google Sheets, Mailchimp, FluentCRM, HubSpot, Brevo, ActiveCampaign, Zoho CRM, Klaviyo, Airtable, Notion, Telegram, MailerLite, GetResponse, Campaign Monitor, Drip, MailPoet, Kit, Keap, and 25+ more. **Zapier Integration:** Connect your forms with 5,000+ apps through Zapier for limitless automation. @@ -291,11 +251,9 @@ Customize form appearance directly within your favorite page builder: - Bricks Builder โ€” styling options in the Bricks panel - Elementor โ€” styling controls in the Elementor widget -With SureForms, we are here to fix the real issues users face with WordPress forms. That's why **500,000+ websites** have embraced SureForms for all their form-related needs. - ### HOW IT WORKS โ“ -From installation to creating your first form, SureForms is designed to be simple and intuitive. Here is how it works: +From installation to creating your first contact form, SureForms is designed to be simple and intuitive. Here is how it works: #### Step 1: Install the SureForms WordPress Plugin ๐Ÿ”Œ @@ -313,53 +271,18 @@ Once your form is ready, easily embed it on any page or post using the provided SureForms is built for anyone who needs contact forms, custom forms, or advanced user-friendly forms on WordPress. -- **Website Owners:** For any GDPR-compliant forms without coding. +- **Website Owners:** For any GDPR-compliant contact form without coding. - **Designers:** For forms that match site aesthetics with custom styling options. - **Developers:** Ability to extend with clean APIs, hooks, and custom CSS. - **No-Code Professionals:** Use advanced features like Conditional Logic, Multi-step, and Conversational Forms with ease. - **Agencies:** To save time with easy integration for scalable workflows. - **E-commerce Stores:** To power up Checkouts, Registrations, and Customer Forms. - **Educators & Communities:** To build student Registration or Login Forms, Feedback Forms, or Membership Forms quickly. - -Don't think this is just it. There is no limit to the types of businesses and organizations that can benefit from using SureForms. - ### WORDPRESS THEMES & PLUGINS THAT SUREFORMS SUPPORTS ๐Ÿ”— -#### SureForms works with any theme, including: - -- Astra -- Spectra One -- Blocksy -- Bricks Builder -- Flatsome -- GeneratePress -- Hestia -- Kadence -- Neve - -#### SureForms is compatible with all plugins, including: - -- Spectra -- Easy Digital Downloads -- FluentCRM -- GiveWP -- LearnDash -- LifterLMS -- MemberPress -- PrestoPlayer -- Restrict Content Pro -- SureCart -- SureMembers -- OttoKit -- The Events Calendar -- TutorLMS -- Wishlist Member -- WooCommerce -- CartFlows -- Elementor Pro -- Beaver Builder -- Divi Builder -- And many more +SureForms works with any theme, including Astra, Spectra One, Blocksy, Bricks, Flatsome, GeneratePress, Hestia, Kadence, and Neve. + +It is compatible with popular plugins including WooCommerce, Easy Digital Downloads, GiveWP, LearnDash, LifterLMS, MemberPress, Restrict Content Pro, SureCart, SureMembers, OttoKit, The Events Calendar, TutorLMS, Wishlist Member, CartFlows, Elementor Pro, Beaver Builder, Divi, and many more. ### CONNECT WITH OUR TEAM AND COMMUNITY @@ -535,6 +458,10 @@ Yes. SureForms Business includes fully functional user registration forms and lo You can report security issues through our [Bug Bounty Program](https://brainstormforce.com/bug-bounty-program/). We collaborate with Patchstack to provide opportunities for researchers to report vulnerabilities. The Patchstack team will help validate, triage, and handle any reported security issues. ## Changelog ## +### 2.11.1 - 16th June 2026 ### +* Fix: Phone field auto country detection always resolved to the United States. +* Fix: Corrected the Cloudflare Turnstile "Get Keys" link. +* Fix: This update addressed a security bug. Props to Yaswanth Reddy Sunkara for reporting it responsibly to our team. ### 2.11.0 - 10th June 2026 ### * New: Added a Form Migrator to import forms from Contact Form 7, WPForms, Gravity Forms, and Ninja Forms in a single click. * New: Added native WPML support to translate each form individually using String Packages. @@ -542,12 +469,6 @@ You can report security issues through our [Bug Bounty Program](https://brainsto * Improvement: Improved compatibility with older Block API versions so the SureForms editor loads reliably across WordPress environments. * Fix: Resolved an issue where the Textarea character counter was misaligned. * Fix: Resolved an issue where the {entry_id} smart tag failed to resolve in email notifications. -### 2.10.0 - 27th May 2026 ### -* New: Added a live character counter to Textarea fields. -* New: Added a one-click converter that turns raw HTML forms into native SureForms in gutenberg editor. -* Improvement: Added dynamic default value support for multi-select Dropdown and Multi-Choice fields. -* Improvement: Entry URL now records actual submission page. -* Fix: CSV export was stripping line breaks from Textarea submissions. The full changelog is available [here](https://sureforms.com/whats-new/?utm_source=wordpress.org&utm_medium=whats_new). ## Upgrade Notice ## diff --git a/assets/js/unminified/blocks/phone.js b/assets/js/unminified/blocks/phone.js index 7f4715283..9356075a3 100644 --- a/assets/js/unminified/blocks/phone.js +++ b/assets/js/unminified/blocks/phone.js @@ -1,3 +1,6 @@ +// A valid ISO 3166-1 alpha-2 code, lowercase. +const isIso2 = ( c ) => typeof c === 'string' && /^[a-z]{2}$/.test( c ); + /** * Validates and returns a country code based on filter settings. * If the country is not valid for current filters, returns the first valid country. @@ -16,31 +19,220 @@ function validateCountryWithFilters( includeCountries, excludeCountries ) { + const countryLower = + typeof country === 'string' ? country.toLowerCase() : ''; + if ( enableCountryFilter !== 'true' ) { - return country; + return isIso2( countryLower ) ? countryLower : ''; } - const countryLower = country.toLowerCase(); + // Handle include filter. The list is JSON.parsed from a data attribute, so + // normalize to lowercase and drop anything that isn't a valid ISO2 code. + if ( + countryFilterType === 'include' && + Array.isArray( includeCountries ) && + includeCountries.length > 0 + ) { + const include = includeCountries + .map( ( c ) => String( c ).toLowerCase() ) + .filter( isIso2 ); + if ( countryLower && include.includes( countryLower ) ) { + return countryLower; + } + // Country not in include list โ€” use the first valid included country. + return include[ 0 ] || ''; + } - // Handle include filter - if ( countryFilterType === 'include' && includeCountries.length > 0 ) { - if ( ! includeCountries.includes( countryLower ) ) { - // Country not in include list, use first country from the list - return includeCountries[ 0 ]; + // Handle exclude filter. + if ( + countryFilterType === 'exclude' && + Array.isArray( excludeCountries ) && + excludeCountries.length > 0 + ) { + const exclude = excludeCountries + .map( ( c ) => String( c ).toLowerCase() ) + .filter( isIso2 ); + if ( countryLower && ! exclude.includes( countryLower ) ) { + return countryLower; } - return countryLower; + // Country is excluded โ€” pick the first sensible fallback that is NOT + // itself excluded (never a hardcoded gb/us that the site may exclude). + const candidates = [ 'us', 'gb', 'ca', 'au', 'de', 'fr', 'in', 'jp' ]; + return candidates.find( ( c ) => ! exclude.includes( c ) ) || ''; } - // Handle exclude filter - if ( countryFilterType === 'exclude' && excludeCountries.length > 0 ) { - if ( excludeCountries.includes( countryLower ) ) { - // Country is excluded, use 'us' or another fallback - return excludeCountries.includes( 'us' ) ? 'gb' : 'us'; + return isIso2( countryLower ) ? countryLower : ''; +} + +/** + * IANA timezone โ†’ ISO 3166-1 alpha-2 country (lowercase). + * + * The device timezone reflects the visitor's physical location far better than + * their browser language, so it is the primary on-device signal. Covers the + * common canonical zones; anything unlisted falls back to the locale region. + */ +const TIMEZONE_TO_COUNTRY = { + // North America. + 'America/New_York': 'us', 'America/Detroit': 'us', 'America/Chicago': 'us', 'America/Denver': 'us', 'America/Phoenix': 'us', 'America/Los_Angeles': 'us', 'America/Anchorage': 'us', 'America/Adak': 'us', 'America/Boise': 'us', 'America/Indiana/Indianapolis': 'us', 'Pacific/Honolulu': 'us', + 'America/Toronto': 'ca', 'America/Vancouver': 'ca', 'America/Edmonton': 'ca', 'America/Winnipeg': 'ca', 'America/Halifax': 'ca', 'America/St_Johns': 'ca', 'America/Regina': 'ca', + 'America/Mexico_City': 'mx', 'America/Tijuana': 'mx', 'America/Monterrey': 'mx', 'America/Cancun': 'mx', + // Central & South America. + 'America/Bogota': 'co', 'America/Lima': 'pe', 'America/Caracas': 've', 'America/Santiago': 'cl', 'America/Argentina/Buenos_Aires': 'ar', 'America/Sao_Paulo': 'br', 'America/Bahia': 'br', 'America/Fortaleza': 'br', 'America/Manaus': 'br', 'America/Montevideo': 'uy', 'America/Asuncion': 'py', 'America/La_Paz': 'bo', 'America/Guayaquil': 'ec', 'America/Panama': 'pa', 'America/Costa_Rica': 'cr', 'America/Guatemala': 'gt', 'America/El_Salvador': 'sv', 'America/Tegucigalpa': 'hn', 'America/Managua': 'ni', 'America/Santo_Domingo': 'do', 'America/Havana': 'cu', 'America/Jamaica': 'jm', 'America/Puerto_Rico': 'pr', 'America/Port_of_Spain': 'tt', + // Europe. + 'Europe/London': 'gb', 'Europe/Dublin': 'ie', 'Europe/Lisbon': 'pt', 'Atlantic/Canary': 'es', 'Europe/Madrid': 'es', 'Europe/Paris': 'fr', 'Europe/Brussels': 'be', 'Europe/Amsterdam': 'nl', 'Europe/Luxembourg': 'lu', 'Europe/Berlin': 'de', 'Europe/Zurich': 'ch', 'Europe/Vienna': 'at', 'Europe/Rome': 'it', 'Europe/Malta': 'mt', 'Europe/Copenhagen': 'dk', 'Europe/Oslo': 'no', 'Europe/Stockholm': 'se', 'Europe/Helsinki': 'fi', 'Europe/Reykjavik': 'is', 'Europe/Warsaw': 'pl', 'Europe/Prague': 'cz', 'Europe/Bratislava': 'sk', 'Europe/Budapest': 'hu', 'Europe/Vilnius': 'lt', 'Europe/Riga': 'lv', 'Europe/Tallinn': 'ee', 'Europe/Athens': 'gr', 'Europe/Bucharest': 'ro', 'Europe/Sofia': 'bg', 'Europe/Belgrade': 'rs', 'Europe/Zagreb': 'hr', 'Europe/Ljubljana': 'si', 'Europe/Sarajevo': 'ba', 'Europe/Skopje': 'mk', 'Europe/Tirane': 'al', 'Europe/Chisinau': 'md', 'Europe/Kyiv': 'ua', 'Europe/Kiev': 'ua', 'Europe/Minsk': 'by', 'Europe/Moscow': 'ru', 'Europe/Istanbul': 'tr', + // Middle East. + 'Asia/Jerusalem': 'il', 'Asia/Beirut': 'lb', 'Asia/Amman': 'jo', 'Asia/Damascus': 'sy', 'Asia/Baghdad': 'iq', 'Asia/Riyadh': 'sa', 'Asia/Kuwait': 'kw', 'Asia/Qatar': 'qa', 'Asia/Dubai': 'ae', 'Asia/Muscat': 'om', 'Asia/Bahrain': 'bh', 'Asia/Tehran': 'ir', + // South & Central Asia. + 'Asia/Kabul': 'af', 'Asia/Karachi': 'pk', 'Asia/Kolkata': 'in', 'Asia/Calcutta': 'in', 'Asia/Colombo': 'lk', 'Asia/Kathmandu': 'np', 'Asia/Dhaka': 'bd', 'Asia/Thimphu': 'bt', 'Asia/Almaty': 'kz', 'Asia/Tashkent': 'uz', 'Asia/Baku': 'az', 'Asia/Yerevan': 'am', 'Asia/Tbilisi': 'ge', + // East & Southeast Asia. + 'Asia/Yangon': 'mm', 'Asia/Bangkok': 'th', 'Asia/Ho_Chi_Minh': 'vn', 'Asia/Phnom_Penh': 'kh', 'Asia/Vientiane': 'la', 'Asia/Jakarta': 'id', 'Asia/Makassar': 'id', 'Asia/Kuala_Lumpur': 'my', 'Asia/Singapore': 'sg', 'Asia/Manila': 'ph', 'Asia/Hong_Kong': 'hk', 'Asia/Macau': 'mo', 'Asia/Taipei': 'tw', 'Asia/Shanghai': 'cn', 'Asia/Urumqi': 'cn', 'Asia/Tokyo': 'jp', 'Asia/Seoul': 'kr', 'Asia/Ulaanbaatar': 'mn', + // Africa. + 'Africa/Abidjan': 'ci', 'Africa/Accra': 'gh', 'Africa/Addis_Ababa': 'et', 'Africa/Algiers': 'dz', 'Africa/Cairo': 'eg', 'Africa/Casablanca': 'ma', 'Africa/Johannesburg': 'za', 'Africa/Lagos': 'ng', 'Africa/Nairobi': 'ke', 'Africa/Tripoli': 'ly', 'Africa/Tunis': 'tn', 'Africa/Khartoum': 'sd', 'Africa/Dar_es_Salaam': 'tz', 'Africa/Kampala': 'ug', 'Africa/Kinshasa': 'cd', 'Africa/Maputo': 'mz', 'Africa/Windhoek': 'na', 'Africa/Harare': 'zw', 'Africa/Lusaka': 'zm', 'Africa/Dakar': 'sn', + // Oceania. + 'Australia/Sydney': 'au', 'Australia/Melbourne': 'au', 'Australia/Brisbane': 'au', 'Australia/Perth': 'au', 'Australia/Adelaide': 'au', 'Australia/Darwin': 'au', 'Australia/Hobart': 'au', 'Pacific/Auckland': 'nz', 'Pacific/Fiji': 'fj', 'Pacific/Guam': 'gu', 'Pacific/Port_Moresby': 'pg', +}; + +/** + * Detect a likely country for the visitor using only on-device browser data. + * + * Primary signal is the device timezone (physical location); the browser locale + * region (language) is a weaker secondary fallback. Both are read locally via + * Intl โ€” no network request, no IP, no third-party call โ€” so detection works + * offline, on localhost and on full-page-cached pages, and never raises the + * CORS / rate-limit / privacy concerns of a browser geo-IP request. + * + * @return {string} Lowercase 2-letter country code, or '' when undeterminable. + */ +function detectCountryFromBrowser() { + // 1. Timezone โ†’ country (reflects physical location). + try { + const tz = Intl.DateTimeFormat().resolvedOptions().timeZone; + if ( tz && TIMEZONE_TO_COUNTRY[ tz ] ) { + return TIMEZONE_TO_COUNTRY[ tz ]; } - return countryLower; + } catch { + // Intl.DateTimeFormat unsupported โ€” fall through to locale. } - return country; + // 2. Locale region (language) โ€” weaker, but better than nothing. + try { + const locales = + Array.isArray( navigator.languages ) && navigator.languages.length + ? navigator.languages + : [ navigator.language ]; + for ( const locale of locales ) { + if ( ! locale ) { + continue; + } + const region = new Intl.Locale( locale ).region; + if ( region && /^[A-Z]{2}$/.test( region ) ) { + return region.toLowerCase(); + } + } + } catch { + // Intl.Locale unsupported or a malformed locale โ€” fall through. + } + return ''; +} + +/** + * Apply per-visitor auto country detection to an intl-tel-input instance. + * + * Resolution order, most-to-least authoritative: + * 1. A browser-local Intl guess applied immediately โ€” works offline, on + * localhost and on full-page-cached pages, with no flash and no network. + * 2. The same-origin geo-country REST endpoint, used to refine the guess only + * when the server *confidently* detected (CDN header or a successful IP + * lookup); cached in sessionStorage for the session. + * + * Respects the field's country filters and never overrides a value the visitor + * already started typing. + * + * @param {Object} iti The intl-tel-input instance. + * @param {HTMLElement} phoneNumber The phone input element. + * @param {Object} filters Country-filter settings for this field. + */ +function applyAutoCountry( iti, phoneNumber, filters ) { + // Track the last country WE applied, seeded from whatever the instance + // currently shows (the server-baked default). The async "refine" steps only + // apply if the selected country still equals this โ€” i.e. the visitor hasn't + // changed it meanwhile (by typing OR by picking from the dropdown). + let lastAutoApplied = iti.getSelectedCountryData()?.iso2 || null; + + const setCountry = ( country, { isRefine = false } = {} ) => { + if ( ! country || typeof country !== 'string' ) { + return; + } + const countryLower = country.toLowerCase(); + // Guard the (possibly external) value before it reaches setCountry(). + if ( ! isIso2( countryLower ) ) { + return; + } + // Don't override a value the visitor already started entering. + if ( phoneNumber.value && phoneNumber.value.trim() !== '' ) { + return; + } + // Don't override an explicit country the visitor chose (e.g. from the + // dropdown, without typing) before this async refine resolved. + if ( isRefine && lastAutoApplied !== null ) { + const current = iti.getSelectedCountryData()?.iso2; + if ( current && current !== lastAutoApplied ) { + return; + } + } + const validated = validateCountryWithFilters( + countryLower, + filters.enableCountryFilter, + filters.countryFilterType, + filters.includeCountries, + filters.excludeCountries + ); + if ( validated ) { + iti.setCountry( validated ); + lastAutoApplied = validated; + } + }; + + // 1. Immediate, network-free local guess so the flag is sensible even on + // localhost, offline, or before any request resolves. + setCountry( detectCountryFromBrowser() ); + + const endpoint = + window.srfm_phone_data && window.srfm_phone_data.geo_endpoint; + if ( ! endpoint ) { + return; + } + + // 2. Prefer a confident server detection. Reuse a cached one for the session. + let cached = null; + try { + cached = window.sessionStorage?.getItem( 'srfm_geo_country_detected' ); + } catch { + cached = null; + } + if ( cached ) { + setCountry( cached, { isRefine: true } ); + return; + } + + fetch( endpoint, { headers: { Accept: 'application/json' } } ) + .then( ( res ) => ( res.ok ? res.json() : null ) ) + .then( ( data ) => { + // Only override the local guess when the server is confident. + if ( ! data || ! data.detected || ! data.country ) { + return; + } + const country = String( data.country ); + try { + window.sessionStorage?.setItem( 'srfm_geo_country_detected', country ); + } catch { + // sessionStorage may be unavailable (e.g. private mode) โ€” ignore. + } + setCountry( country, { isRefine: true } ); + } ) + .catch( () => { + // Network error โ€” keep the local guess. + } ); } function initializePhoneField() { @@ -146,6 +338,20 @@ function initializePhoneField() { // Dropdown selection goes through _selectListItem -> _setCountry directly, so it still works. iti._updateCountryFromNumber = () => false; + // Per-visitor auto country detection. The server bakes an initial + // `default-country`, but on full-page-cached sites that value is the first + // visitor's. When auto-country is enabled, fetch the current visitor's + // country from the same-origin REST endpoint (not part of the cached page + // HTML) and apply it โ€” correct per visitor. + if ( phoneNumber.getAttribute( 'data-auto-country' ) === 'true' ) { + applyAutoCountry( iti, phoneNumber, { + enableCountryFilter, + countryFilterType, + includeCountries, + excludeCountries, + } ); + } + const countriesData = iti?.countryList.querySelectorAll( '.iti__country' ); diff --git a/docs/01-getting-started/GETTING-STARTED.md b/docs/01-getting-started/GETTING-STARTED.md deleted file mode 100644 index a9c0b0c34..000000000 --- a/docs/01-getting-started/GETTING-STARTED.md +++ /dev/null @@ -1,647 +0,0 @@ -# Getting Started with SureForms Development - -> **Goal:** Get productive in less than 30 minutes -> **Audience:** New developers, contractors, open-source contributors -> **Prerequisites:** Basic WordPress, PHP, and React knowledge - -## Prerequisites - -Before you begin, ensure you have: - -- **PHP 7.4+** with extensions: mysqli, mbstring, curl, json -- **Composer 2.3+** for PHP dependencies -- **Node.js 18.15+** (check with `node --version`, use nvm: `nvm use`) -- **npm** (comes with Node.js) -- **Git** for version control -- **Code editor** (VS Code recommended with extensions: PHP Intelephense, ESLint, Prettier) -- **Docker** (optional, for wp-env local environment) - ---- - -## Quick Start (5 Minutes) - -### 1. Clone Repository -```bash -git clone https://github.com/brainstormforce/sureforms.git -cd sureforms -``` - -### 2. Install Dependencies -```bash -# PHP dependencies -composer install - -# JavaScript dependencies -npm install -``` - -This installs: -- **PHP:** Action Scheduler, NPS Survey, Analytics libraries -- **JavaScript:** React 18, WordPress scripts, TailwindCSS, Webpack, testing tools - -### 3. Build Assets -```bash -npm run build -``` - -This compiles: -- JavaScript bundles (Webpack โ†’ assets/build/) -- CSS from SASS (sass/ โ†’ assets/css/) -- Minified production files - -**Time:** ~2-3 minutes - -### 4. Start Local Environment - -**Option A: Using wp-env (Recommended)** -```bash -npm run play:up -``` - -This creates a Docker-based WordPress installation: -- **URL:** http://localhost:8888 -- **Admin:** http://localhost:8888/wp-admin -- **Username:** admin -- **Password:** password - -**Option B: Manual WordPress Setup** -1. Install WordPress locally (MAMP, Local by Flywheel, or XAMPP) -2. Symlink or copy plugin to `wp-content/plugins/sureforms` -3. Activate plugin in WordPress admin - -### 5. Activate Plugin - -Visit http://localhost:8888/wp-admin/plugins.php and activate "SureForms". - -**You're now ready to develop!** ๐ŸŽ‰ - ---- - -## Project Structure Overview - -``` -sureforms/ -โ”œโ”€โ”€ sureforms.php # Main plugin file (entry point) -โ”œโ”€โ”€ plugin-loader.php # Bootstrap and autoloader -โ”‚ -โ”œโ”€โ”€ inc/ # PHP backend logic (176+ files) -โ”‚ โ”œโ”€โ”€ form-submit.php # Form submission handler -โ”‚ โ”œโ”€โ”€ post-types.php # Custom post type registration -โ”‚ โ”œโ”€โ”€ rest-api.php # REST API endpoints -โ”‚ โ”œโ”€โ”€ helper.php # Utility functions -โ”‚ โ”œโ”€โ”€ blocks/ # Gutenberg block PHP classes -โ”‚ โ”‚ โ”œโ”€โ”€ base.php # Abstract base for blocks -โ”‚ โ”‚ โ”œโ”€โ”€ register.php # Block registration -โ”‚ โ”‚ โ”œโ”€โ”€ input/ # Text input block -โ”‚ โ”‚ โ””โ”€โ”€ [14+ more blocks] -โ”‚ โ”œโ”€โ”€ database/ # Custom database layer -โ”‚ โ”‚ โ”œโ”€โ”€ base.php # Abstract CRUD operations -โ”‚ โ”‚ โ”œโ”€โ”€ register.php # Table initialization -โ”‚ โ”‚ โ””โ”€โ”€ tables/ -โ”‚ โ”‚ โ”œโ”€โ”€ entries.php # Form submissions table -โ”‚ โ”‚ โ””โ”€โ”€ payments.php # Payment transactions table -โ”‚ โ””โ”€โ”€ [many more directories] -โ”‚ -โ”œโ”€โ”€ src/ # JavaScript/React source -โ”‚ โ”œโ”€โ”€ blocks/ # Gutenberg block components -โ”‚ โ”‚ โ”œโ”€โ”€ blocks.js # Block registration entry -โ”‚ โ”‚ โ”œโ”€โ”€ input/ # Input block React component -โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ edit.js # Editor interface -โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ save.js # Frontend save (usually null) -โ”‚ โ”‚ โ”‚ โ””โ”€โ”€ block.json # Block metadata -โ”‚ โ”‚ โ””โ”€โ”€ [14+ more blocks] -โ”‚ โ”œโ”€โ”€ admin/ # Admin dashboard React apps -โ”‚ โ”‚ โ”œโ”€โ”€ dashboard/ # Forms listing -โ”‚ โ”‚ โ”œโ”€โ”€ settings/ # Settings page -โ”‚ โ”‚ โ”œโ”€โ”€ entries/ # Entry management -โ”‚ โ”‚ โ””โ”€โ”€ single-form-settings/ # Form editor -โ”‚ โ”œโ”€โ”€ components/ # Reusable React components -โ”‚ โ”œโ”€โ”€ store/ # WordPress Data Store (Redux) -โ”‚ โ””โ”€โ”€ utils/ # Helper functions -โ”‚ -โ”œโ”€โ”€ assets/ # Compiled build output -โ”‚ โ”œโ”€โ”€ build/ # Webpack bundles -โ”‚ โ”œโ”€โ”€ css/ # Compiled CSS -โ”‚ โ””โ”€โ”€ js/ # Compiled JavaScript -โ”‚ -โ”œโ”€โ”€ sass/ # SCSS source files -โ”œโ”€โ”€ tests/ # PHPUnit and Playwright tests -โ”œโ”€โ”€ webpack.config.js # Build configuration -โ”œโ”€โ”€ package.json # npm dependencies and scripts -โ””โ”€โ”€ composer.json # PHP dependencies -``` - -### Key Entry Points - -**PHP Initialization:** -``` -sureforms.php (defines constants) - โ†’ plugin-loader.php (Plugin_Loader class) - โ†’ Autoloader registration - โ†’ WordPress hooks: plugins_loaded, init, admin_init -``` - -**JavaScript Entry:** -- **Blocks:** [src/blocks/index.js](../../src/blocks/index.js) -- **Admin Pages:** [src/admin/{page}/index.js](../../src/admin/) - ---- - -## Development Workflow - -### Daily Development - -**1. Start Development Server** -```bash -npm start -``` - -This starts Webpack in watch mode: -- Automatically rebuilds on file changes -- Hot reload for React components -- Source maps for debugging - -**2. Make Changes** -- Edit PHP files in `inc/` or `admin/` -- Edit React components in `src/` -- Edit styles in `sass/` - -**3. See Changes** -- **Admin:** Refresh browser (Cmd/Ctrl + R) -- **Frontend:** Hard refresh (Cmd/Ctrl + Shift + R) to clear cache - -### Before Committing - -**CRITICAL: Always run these commands before committing** - -```bash -# 1. Fix JavaScript linting issues -npm run lint-js:fix - -# 2. Fix CSS linting issues -npm run lint-css:fix - -# 3. Production build (REQUIRED) -npm run build - -# 4. Check PHP coding standards -composer phpcs - -# 5. Run static analysis -composer phpstan - -# 6. Run tests (optional but recommended) -composer test -npm run test:e2e -``` - -**If all pass, commit:** -```bash -git add . -git commit -m "feat: your change description" -git push -``` - -### Commit Message Format - -Follow [Conventional Commits](https://www.conventionalcommits.org/): - -``` -feat: add date picker field block -fix: resolve form submission nonce error -docs: update API endpoint documentation -style: format code with PHPCS -refactor: simplify validation logic -test: add unit tests for Helper class -chore: update dependencies -``` - ---- - -## Common Development Tasks - -### Task 1: Create a Test Form - -**Time:** 5 minutes - -1. Navigate to **SureForms โ†’ Add New** in WordPress admin -2. Block editor opens with empty form -3. Add fields by clicking "+" button: - - Add "Input" block โ†’ Configure as "Name" - - Add "Email" block โ†’ Configure as "Email Address" - - Add "Textarea" block โ†’ Configure as "Message" -4. Click "Publish" -5. View form on frontend or use shortcode `[sureforms id="{ID}"]` - -### Task 2: Submit a Test Form - -**Time:** 2 minutes - -1. Visit form on frontend -2. Fill out fields -3. Click "Submit" -4. Check **SureForms โ†’ Entries** to see submission - -### Task 3: Add a New Setting to Existing Block - -**Time:** 30-45 minutes -**Difficulty:** Easy -**Files Modified:** 2 - -**Example: Add "Max Length" setting to Input block** - -**Step 1:** Update [src/blocks/input/edit.js](../../src/blocks/input/edit.js) - -Find the `` section and add: -```javascript -import { TextControl } from '@wordpress/components'; - -// Inside InspectorControls > PanelBody - setAttributes({ maxLength: parseInt(value) })} - help={__('Maximum number of characters allowed', 'sureforms')} -/> -``` - -**Step 2:** Update [src/blocks/input/block.json](../../src/blocks/input/block.json) - -Add to `attributes` object: -```json -"maxLength": { - "type": "number", - "default": 0 -} -``` - -**Step 3:** Build and test -```bash -npm run build -# Refresh block editor -# Test setting in Inspector panel -``` - -**Step 4:** Update PHP rendering (if needed) - -Edit [inc/blocks/input/class-input.php](../../inc/blocks/input/class-input.php) to use the attribute: -```php -$max_length = $attributes['maxLength'] ?? 0; - -// In HTML output - 0): ?> - maxlength="" - -/> -``` - -### Task 4: Debug a Form Submission Issue - -**Time:** 10-20 minutes - -**Symptoms:** Form submission fails silently, no error message - -**Debug Steps:** - -1. **Check Browser Console** (F12 โ†’ Console tab) - - Look for JavaScript errors - - Check Network tab for failed AJAX requests - - Look for 403 (nonce error) or 500 (server error) - -2. **Check PHP Error Logs** -```bash -# If using wp-env -npm run play:logs - -# Or tail WordPress debug log -tail -f wp-content/debug.log -``` - -3. **Enable WordPress Debug Mode** (wp-config.php) -```php -define('WP_DEBUG', true); -define('WP_DEBUG_LOG', true); -define('WP_DEBUG_DISPLAY', false); -define('SCRIPT_DEBUG', true); -``` - -4. **Test REST API Directly** -```bash -# Get nonce from browser (inspect form, look for data-nonce attribute) -curl -X POST "http://localhost:8888/wp-json/sureforms/v1/submit-form" \ - -H "X-WP-Nonce: YOUR_NONCE_HERE" \ - -H "Content-Type: application/json" \ - -d '{"form_id":123,"field_data":{"email":{"value":"test@example.com"}}}' -``` - -5. **Common Fixes:** - - **Nonce expired:** Refresh page - - **Spam protection:** Disable reCAPTCHA temporarily - - **PHP error:** Check debug.log for syntax errors - - **REST API disabled:** Check .htaccess or security plugins - ---- - -## Testing Your Changes - -### Unit Tests (PHP) - -```bash -# Run all PHPUnit tests -composer test - -# Run specific test file -./vendor/bin/phpunit tests/unit/test-helper.php - -# Generate coverage report -composer test:coverage -``` - -### E2E Tests (Playwright) - -```bash -# Run all E2E tests -npm run test:e2e - -# Run specific test -npx playwright test tests/play/specs/basic-form-test-submit-text-field.spec.js - -# Run in headed mode (see browser) -npx playwright test --headed - -# Debug mode -npx playwright test --debug -``` - -### Manual Testing Checklist - -After making changes, test: -- [ ] Form appears in block editor -- [ ] Settings panel works -- [ ] Form renders on frontend -- [ ] Form submission works -- [ ] Entry appears in admin -- [ ] Email notification sent (if configured) -- [ ] No console errors -- [ ] No PHP errors in debug.log - ---- - -## Debugging Tips - -### Enable Debugging - -**WordPress Debug Mode** (wp-config.php): -```php -define('WP_DEBUG', true); // Enable debug mode -define('WP_DEBUG_LOG', true); // Log to wp-content/debug.log -define('WP_DEBUG_DISPLAY', false); // Don't display errors on page -define('SCRIPT_DEBUG', true); // Load unminified JS/CSS -define('SAVEQUERIES', true); // Log database queries -``` - -**Plugin Debug Mode** (wp-config.php): -```php -define('SRFM_DEBUG', true); // Load unminified assets -``` - -### View Logs - -**PHP Errors:** -```bash -tail -f wp-content/debug.log -``` - -**JavaScript Console:** -- Open browser DevTools (F12) -- Console tab shows errors and logs -- Network tab shows AJAX requests - -### Common Issues - -#### Issue: "Class not found" Error -**Cause:** Namespace doesn't match file path -**Fix:** Ensure `SRFM\Inc\Blocks\Input` maps to `inc/blocks/input/class-input.php` - -#### Issue: Blocks Don't Appear in Editor -**Cause:** JavaScript not rebuilt -**Fix:** -```bash -npm run build -# Hard refresh browser (Cmd/Ctrl + Shift + R) -``` - -#### Issue: Form Submission Fails -**Cause:** Nonce expired or invalid -**Fix:** Refresh page to get new nonce - -#### Issue: Styling Not Applied -**Cause:** CSS not compiled or cached -**Fix:** -```bash -npm run build:sass -# Hard refresh browser -``` - -#### Issue: PHP Syntax Error After Edit -**Cause:** Syntax mistake in PHP file -**Fix:** Check debug.log, fix syntax, refresh - ---- - -## Next Steps - -Now that you're set up, here's how to continue learning: - -### 1. Read Core Documentation (2-3 hours) - -**Essential:** -- [CLAUDE.md](../../CLAUDE.md) - AI agent guide with constraints and patterns -- [ARCHITECTURE.md](../02-architecture/ARCHITECTURE.md) - System design overview - -**Important:** -- [CODING-STANDARDS.md](../03-development/CODING-STANDARDS.md) - Code style rules -- [DATABASE-SCHEMA.md](../04-backend/DATABASE-SCHEMA.md) - Data model -- [FRONTEND-GUIDE.md](../05-frontend/FRONTEND-GUIDE.md) - React/Gutenberg patterns - -### 2. Explore the Codebase (2-3 hours) - -**Follow the Request Flow:** - -**Admin Page Load:** -``` -1. WordPress loads: admin.php?page=sureforms_forms -2. admin/admin.php โ†’ render_forms_page() -3. Outputs:
-4. React app mounts from assets/build/forms.js -5. Fetches data from REST API -``` - -**Form Submission:** -``` -1. User fills form โ†’ formSubmit.js validates -2. AJAX POST โ†’ /wp-json/sureforms/v1/submit-form -3. inc/form-submit.php โ†’ handle_form_submission() -4. Validates โ†’ Saves to wp_srfm_entries table -5. Sends email notifications -6. Returns success response -``` - -### 3. Study Example Implementations - -**Reference Block:** [inc/blocks/input/](../../inc/blocks/input/) -- See complete block implementation -- PHP class extends Base -- React component structure -- Attribute schema in block.json - -**Reference React App:** [src/admin/dashboard/](../../src/admin/dashboard/) -- React Query for data fetching -- React Router for navigation -- Component structure - -### 4. Make Your First Contribution - -**Choose from "Good First Issue" labels:** -- Add documentation -- Fix typos -- Add unit tests -- Improve error messages -- Add new field setting - -**Contribution Process:** -1. Fork repository -2. Create feature branch: `git checkout -b feat/your-feature` -3. Make changes -4. Run tests and linters -5. Commit with conventional commit message -6. Push and create pull request -7. Address review feedback - ---- - -## Getting Help - -### Documentation -- [CLAUDE.md](../../CLAUDE.md) - AI agent guide -- [docs/](../) - Full documentation -- [README.md](../../README.md) - Plugin overview - -### Community -- **GitHub Issues:** https://github.com/brainstormforce/sureforms/issues -- **Pull Requests:** https://github.com/brainstormforce/sureforms/pulls - -### Code Questions - -**When asking for help, include:** -1. What you're trying to do -2. What you've tried -3. Error messages (browser console + PHP debug.log) -4. Code snippets -5. Environment (WordPress version, PHP version, plugin version) - ---- - -## Development Tools - -### Recommended VS Code Extensions - -- **PHP Intelephense** - PHP intelligence and autocomplete -- **ESLint** - JavaScript linting -- **Prettier** - Code formatting -- **EditorConfig** - Consistent editor config -- **WordPress Snippets** - WordPress function snippets -- **GitLens** - Git integration -- **Auto Rename Tag** - HTML tag renaming -- **Path Intellisense** - File path autocomplete - -### Browser Extensions - -- **React Developer Tools** - Inspect React components -- **Redux DevTools** - Inspect WordPress Data Store state - -### Command Line Tools - -```bash -# Install WP-CLI globally (optional but helpful) -curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar -chmod +x wp-cli.phar -sudo mv wp-cli.phar /usr/local/bin/wp - -# Useful WP-CLI commands -wp plugin list -wp post list --post_type=sureforms_form -wp cache flush -``` - ---- - -## Keyboard Shortcuts (Block Editor) - -| Action | Mac | Windows | -|--------|-----|---------| -| Save | Cmd + S | Ctrl + S | -| Add block | / | / | -| Duplicate block | Cmd + Shift + D | Ctrl + Shift + D | -| Delete block | Shift + Alt + Z | Shift + Alt + Z | -| Block settings | Cmd + Shift + , | Ctrl + Shift + , | -| Undo | Cmd + Z | Ctrl + Z | -| Redo | Cmd + Shift + Z | Ctrl + Shift + Z | - ---- - -## Quick Reference - -### Important npm Scripts - -```bash -npm start # Watch mode with hot reload -npm run build # Production build -npm run build:script # JavaScript only -npm run build:sass # CSS only -npm run lint-js # Check JavaScript -npm run lint-js:fix # Fix JavaScript -npm run lint-css # Check CSS -npm run lint-css:fix # Fix CSS -npm test:unit # JavaScript unit tests -npm run test:e2e # Playwright E2E tests -npm run play:up # Start wp-env -npm run play:stop # Stop wp-env -npm run play:down # Destroy wp-env -npm run makepot # Generate translation template -``` - -### Important Composer Scripts - -```bash -composer install # Install dependencies -composer test # Run PHPUnit tests -composer test:coverage # Generate coverage report -composer phpcs # Check coding standards -composer phpcbf # Fix coding standards -composer phpstan # Static analysis -composer phpinsights # Code quality metrics -``` - -### Important File Paths - -| Purpose | Path | -|---------|------| -| Main plugin file | sureforms.php | -| Plugin loader | plugin-loader.php | -| Form submission | inc/form-submit.php | -| REST API | inc/rest-api.php | -| Helper functions | inc/helper.php | -| Block base class | inc/blocks/base.php | -| Database entries | inc/database/tables/entries.php | -| Webpack config | webpack.config.js | -| TailwindCSS config | tailwind.config.js | - ---- - -**Congratulations!** You're now ready to contribute to SureForms. Happy coding! ๐Ÿš€ - -**Questions?** Check [CLAUDE.md](../../CLAUDE.md) or create an issue on GitHub. diff --git a/docs/04-backend/DATABASE-SCHEMA.md b/docs/04-backend/DATABASE-SCHEMA.md deleted file mode 100644 index 68f5de98f..000000000 --- a/docs/04-backend/DATABASE-SCHEMA.md +++ /dev/null @@ -1,962 +0,0 @@ -# SureForms Database Schema - -> **Purpose:** Document custom database tables, WordPress post types, and data migration strategies -> **Audience:** Backend developers, database administrators -> **Last Updated:** 2026-02-06 -> **Plugin Version:** 2.5.0 - -## Overview - -SureForms uses a **hybrid data storage approach** combining WordPress native tables with custom optimized tables: - -1. **WordPress Custom Post Type (`sureforms_form`)** - Form configurations and structure -2. **Custom Table (`wp_srfm_entries`)** - Form submission data (performance-optimized) -3. **Custom Table (`wp_srfm_payments`)** - Payment transaction tracking - -**Why Custom Tables?** -- **Performance:** Separate from WordPress posts/postmeta tables (millions of rows) -- **Query Optimization:** Custom indexes for form-specific queries -- **Data Integrity:** Structured schema with foreign keys -- **Scalability:** Handle large volumes of form submissions efficiently - ---- - -## Custom Tables - -### Table: `wp_srfm_entries` - -**Purpose:** Store form submission data separate from WordPress posts for optimized query performance. - -**Schema Definition:** [inc/database/tables/entries.php](../../inc/database/tables/entries.php) -**Table Version:** 1 -**Character Set:** utf8mb4_unicode_ci - -#### SQL Schema - -```sql -CREATE TABLE wp_srfm_entries ( - ID BIGINT(20) UNSIGNED AUTO_INCREMENT PRIMARY KEY, - form_id BIGINT(20) UNSIGNED, - user_id BIGINT(20) UNSIGNED NOT NULL DEFAULT 0, - form_data LONGTEXT, - logs LONGTEXT, - notes LONGTEXT, - submission_info LONGTEXT, - status VARCHAR(10), - type VARCHAR(20), - extras LONGTEXT, - created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - - INDEX idx_form_id (form_id), - INDEX idx_user_id (user_id), - INDEX idx_form_id_created_at_status (form_id, created_at, status) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -``` - -#### Column Descriptions - -| Column | Type | Nullable | Default | Description | -|--------|------|----------|---------|-------------| -| `ID` | BIGINT(20) UNSIGNED | No | AUTO_INCREMENT | Primary key, unique entry identifier | -| `form_id` | BIGINT(20) UNSIGNED | No | - | Foreign key to wp_posts.ID (sureforms_form post type) | -| `user_id` | BIGINT(20) UNSIGNED | No | 0 | Foreign key to wp_users.ID (0 for guest submissions) | -| `form_data` | LONGTEXT | Yes | NULL | JSON-encoded submission data (field values) | -| `logs` | LONGTEXT | Yes | NULL | JSON-encoded activity logs array | -| `notes` | LONGTEXT | Yes | NULL | JSON-encoded admin notes array | -| `submission_info` | LONGTEXT | Yes | NULL | JSON-encoded metadata (IP, browser, device, referrer) | -| `status` | VARCHAR(10) | Yes | 'unread' | Entry status: 'unread', 'read', 'trash' | -| `type` | VARCHAR(20) | Yes | NULL | Form type: 'quiz', 'standard', NULL (standard default) | -| `extras` | LONGTEXT | Yes | NULL | JSON-encoded additional data | -| `created_at` | TIMESTAMP | No | CURRENT_TIMESTAMP | Entry creation timestamp | -| `updated_at` | TIMESTAMP | No | CURRENT_TIMESTAMP ON UPDATE | Last modification timestamp | - -#### Indexes - -**Purpose:** Optimize query performance for common access patterns - -| Index Name | Columns | Type | Purpose | -|------------|---------|------|---------| -| PRIMARY | ID | PRIMARY KEY | Unique entry lookup | -| idx_form_id | form_id | INDEX | Filter entries by form | -| idx_user_id | user_id | INDEX | Filter entries by user | -| idx_form_id_created_at_status | form_id, created_at, status | COMPOSITE INDEX | Optimize form dashboard queries with date/status filters | - -**Index Usage Examples:** -```sql --- Uses idx_form_id index -SELECT * FROM wp_srfm_entries WHERE form_id = 123; - --- Uses idx_form_id_created_at_status composite index -SELECT * FROM wp_srfm_entries -WHERE form_id = 123 - AND status = 'unread' - AND created_at > '2026-01-01' -ORDER BY created_at DESC; -``` - -#### JSON Column Structures - -**form_data** (LONGTEXT, JSON): -```json -{ - "field_slug": { - "value": "user input", - "label": "Field Label", - "type": "text" - }, - "email": { - "value": "user@example.com", - "label": "Email Address", - "type": "email" - }, - "phone": { - "value": "+1234567890", - "label": "Phone Number", - "type": "phone" - } -} -``` - -**submission_info** (LONGTEXT, JSON): -```json -{ - "ip_address": "192.168.1.1", - "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)...", - "browser": "Chrome", - "browser_version": "120.0.0.0", - "device": "Desktop", - "os": "Mac OS X", - "referrer": "https://example.com/landing-page", - "timestamp": 1706800000 -} -``` - -**logs** (LONGTEXT, JSON): -```json -[ - { - "title": "Entry Created", - "messages": ["Entry submitted successfully"], - "timestamp": "2026-02-06 10:30:00" - }, - { - "title": "Email Sent", - "messages": [ - "Notification sent to admin@example.com", - "User confirmation sent to user@example.com" - ], - "timestamp": "2026-02-06 10:30:05" - }, - { - "title": "Integration Triggered", - "messages": ["Data sent to MailChimp", "Subscriber added successfully"], - "timestamp": "2026-02-06 10:30:10" - } -] -``` - -**notes** (LONGTEXT, JSON): -```json -[ - { - "note": "Follow up required", - "author": "admin", - "timestamp": "2026-02-06 12:00:00" - } -] -``` - -**extras** (LONGTEXT, JSON): -```json -{ - "quiz_score": 85, - "quiz_result": "passed", - "conversational_form": true, - "utm_source": "google", - "utm_campaign": "summer_2026" -} -``` - -#### Status Values - -| Status | Description | -|--------|-------------| -| `unread` | New submission, not yet viewed by admin (default) | -| `read` | Admin has viewed the submission | -| `trash` | Soft-deleted, can be restored or permanently deleted | - -#### Type Values - -| Type | Description | -|------|-------------| -| NULL or `standard` | Regular form submission (default) | -| `quiz` | Quiz form submission with score/results | -| Other custom types | Extensible for future form types | - -#### Migration History - -**Version 1:** -- **Renamed Column:** `user_data` โ†’ `form_data` (v0.0.13) - - Reason: More descriptive name - - Migration: ALTER TABLE RENAME COLUMN - - Backward compatibility: Old queries updated - -- **Added Columns:** - - `type` VARCHAR(20) (v0.0.13) - - `extras` LONGTEXT (v0.0.13) - - `user_id` BIGINT(20) (v0.0.13) - ---- - -### Table: `wp_srfm_payments` - -**Purpose:** Store payment transaction records for Stripe integration and payment tracking. - -**Schema Definition:** [inc/database/tables/payments.php](../../inc/database/tables/payments.php) -**Table Version:** 1 -**Character Set:** utf8mb4_unicode_ci - -#### SQL Schema - -```sql -CREATE TABLE wp_srfm_payments ( - id BIGINT(20) UNSIGNED AUTO_INCREMENT PRIMARY KEY, - form_id BIGINT(20) UNSIGNED, - block_id VARCHAR(255) NOT NULL, - status VARCHAR(50) NOT NULL, - total_amount DECIMAL(26,8) NOT NULL, - refunded_amount DECIMAL(26,8) NOT NULL, - currency VARCHAR(10) NOT NULL, - entry_id BIGINT(20) UNSIGNED NOT NULL, - gateway VARCHAR(20) NOT NULL, - type VARCHAR(30) NOT NULL, - mode VARCHAR(20) NOT NULL, - transaction_id VARCHAR(50) NOT NULL, - customer_id VARCHAR(50) NOT NULL, - subscription_id VARCHAR(50) NOT NULL, - subscription_status VARCHAR(20) NOT NULL, - parent_subscription_id BIGINT(20) UNSIGNED NOT NULL DEFAULT 0, - payment_data LONGTEXT, - extra LONGTEXT, - log LONGTEXT, - created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - srfm_txn_id VARCHAR(100) NOT NULL, - customer_email VARCHAR(255) NOT NULL, - customer_name VARCHAR(255) NOT NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -``` - -#### Column Descriptions - -| Column | Type | Nullable | Default | Description | -|--------|------|----------|---------|-------------| -| `id` | BIGINT(20) UNSIGNED | No | AUTO_INCREMENT | Primary key, unique payment identifier | -| `form_id` | BIGINT(20) UNSIGNED | No | - | Foreign key to wp_posts.ID (form) | -| `block_id` | VARCHAR(255) | No | '' | Block client ID (unique identifier for payment field) | -| `status` | VARCHAR(50) | No | 'pending' | Payment status (Stripe-specific) | -| `total_amount` | DECIMAL(26,8) | No | 0.00000000 | Total amount after discount (8 decimal precision) | -| `refunded_amount` | DECIMAL(26,8) | No | 0.00000000 | Total refunded amount | -| `currency` | VARCHAR(10) | No | '' | ISO 4217 currency code (USD, EUR, GBP, etc.) | -| `entry_id` | BIGINT(20) UNSIGNED | No | 0 | Foreign key to wp_srfm_entries.ID | -| `gateway` | VARCHAR(20) | No | '' | Payment gateway ('stripe') | -| `type` | VARCHAR(30) | No | '' | Payment type: 'payment', 'subscription', 'renewal' | -| `mode` | VARCHAR(20) | No | '' | Payment mode: 'test' or 'live' | -| `transaction_id` | VARCHAR(50) | No | '' | Gateway transaction ID (e.g., Stripe pi_xxx) | -| `customer_id` | VARCHAR(50) | No | '' | Gateway customer ID (e.g., Stripe cus_xxx) | -| `subscription_id` | VARCHAR(50) | No | '' | Gateway subscription ID (e.g., Stripe sub_xxx) | -| `subscription_status` | VARCHAR(20) | No | '' | Subscription status ('active', 'canceled', etc.) | -| `parent_subscription_id` | BIGINT(20) UNSIGNED | No | 0 | Parent subscription payment ID (for renewal payments) | -| `payment_data` | LONGTEXT | Yes | NULL | JSON-encoded gateway-specific data | -| `extra` | LONGTEXT | Yes | NULL | JSON-encoded additional metadata | -| `log` | LONGTEXT | Yes | NULL | JSON-encoded payment activity logs | -| `created_at` | TIMESTAMP | No | CURRENT_TIMESTAMP | Payment creation timestamp | -| `updated_at` | TIMESTAMP | No | CURRENT_TIMESTAMP ON UPDATE | Last update timestamp | -| `srfm_txn_id` | VARCHAR(100) | No | '' | SureForms transaction ID (custom format) | -| `customer_email` | VARCHAR(255) | No | '' | Customer email address | -| `customer_name` | VARCHAR(255) | No | '' | Customer full name | - -#### Valid Enum Values - -**Payment Status** (Stripe-specific): -- `pending` - Payment initiated but not completed -- `succeeded` - Payment completed successfully -- `failed` - Payment failed -- `canceled` - Payment canceled by user or admin -- `requires_action` - Requires additional authentication (3D Secure) -- `requires_payment_method` - Payment method needs to be provided -- `processing` - Payment is being processed -- `refunded` - Full refund processed -- `partially_refunded` - Partial refund processed - -**Currency Codes** (ISO 4217): -``` -USD, EUR, GBP, JPY, CAD, AUD, CHF, CNY, SEK, NZD, -MXN, SGD, HKD, NOK, TRY, RUB, INR, BRL, ZAR, KRW -``` - -**Payment Gateway:** -- `stripe` (currently only Stripe supported) - -**Payment Mode:** -- `test` - Test/sandbox mode -- `live` - Production mode - -**Subscription Status** (Stripe-specific): -- `active` - Subscription is active -- `canceled` - Subscription canceled -- `past_due` - Payment failed, retrying -- `unpaid` - Payment failed, no retry -- `trialing` - In trial period -- `incomplete` - Initial payment not completed -- `incomplete_expired` - Initial payment window expired -- `paused` - Subscription paused - -#### JSON Column Structures - -**payment_data** (LONGTEXT, JSON): -```json -{ - "stripe_payment_intent": { - "id": "pi_1234567890", - "amount": 4999, - "currency": "usd", - "status": "succeeded", - "created": 1706800000 - }, - "refunds": { - "re_1234567890": { - "refund_id": "re_1234567890", - "amount": 1000, - "status": "succeeded", - "created": 1706900000, - "reason": "requested_by_customer" - } - } -} -``` - -**extra** (LONGTEXT, JSON): -```json -{ - "discount_code": "SUMMER2026", - "discount_amount": 10.00, - "original_amount": 59.99, - "tax_amount": 5.00, - "metadata": { - "utm_source": "google", - "utm_campaign": "summer_sale" - } -} -``` - -**log** (LONGTEXT, JSON): -```json -[ - { - "title": "Payment Initiated", - "message": "Stripe Payment Intent created", - "timestamp": "2026-02-06 10:30:00" - }, - { - "title": "Payment Succeeded", - "message": "Payment completed successfully", - "timestamp": "2026-02-06 10:30:15" - } -] -``` - ---- - -## WordPress Custom Post Type - -### Post Type: `sureforms_form` - -**Purpose:** Store form configurations and structure using WordPress's content management system. - -**Registration:** [inc/post-types.php](../../inc/post-types.php) -**Supports:** title, editor, custom-fields -**Public:** false (admin-only) -**Has Archive:** false -**Rewrite:** false - -#### Post Fields - -| Field | Type | Description | -|-------|------|-------------| -| `post_title` | VARCHAR(200) | Form name (user-editable) | -| `post_content` | LONGTEXT | Serialized Gutenberg blocks (form structure) | -| `post_status` | VARCHAR(20) | 'draft', 'publish', 'trash' | -| `post_type` | VARCHAR(20) | 'sureforms_form' (constant) | -| `post_author` | BIGINT(20) | WordPress user ID who created the form | -| `post_date` | DATETIME | Form creation date | -| `post_modified` | DATETIME | Last modification date | - -#### Post Meta Keys - -Form-specific settings stored in `wp_postmeta`: - -| Meta Key | Description | Data Type | Example | -|----------|-------------|-----------|---------| -| `_srfm_form_settings` | General form settings | Serialized array | [complex settings object] | -| `_srfm_email_notifications` | Email notification rules | Serialized array | Multiple notification configs | -| `_srfm_confirmation_settings` | Post-submission behavior | Serialized array | Message or redirect URL | -| `_srfm_spam_protection` | Anti-spam settings | Serialized array | reCAPTCHA, honeypot config | -| `_srfm_gdpr_settings` | GDPR compliance options | Serialized array | Consent, auto-delete rules | -| `_srfm_styling_settings` | Form visual customization | Serialized array | Colors, fonts, spacing | -| `_srfm_conditional_logic` | Conditional field display | Serialized array | Field visibility rules | -| `_srfm_integrations_webhooks` | Third-party integrations | Serialized array | MailChimp, webhooks | -| `_srfm_instant_form_settings` | Instant form configuration | Serialized array | AI-generated form data | -| `_srfm_conversational_form` | Conversational mode settings | Serialized array | Step-by-step form config | -| `_srfm_premium_common` | Pro features settings | Serialized array | Pro-only configurations | -| `_srfm_user_registration_settings` | User registration integration | Serialized array | Create user on submission | - -#### Block Structure (post_content) - -Forms stored as serialized Gutenberg blocks (HTML comments): - -```html - - - - - - - - - -``` - ---- - -## Database Schema Migrations - -### Version Control System - -**Implementation:** Each table class maintains a `$table_version` property. - -**Version Storage:** WordPress options table -``` -Option Name: srfm_entries_version -Option Value: 1 (integer) - -Option Name: srfm_payments_version -Option Value: 1 (integer) -``` - -### Migration Flow - -``` -1. Plugin loads โ†’ Database\Register::init() -2. For each table: - a. Get stored version from wp_options - b. Compare with code version ($table_version) - c. If mismatch: run upgrade() method - d. Execute schema changes - e. Update version in wp_options -``` - -### Migration Methods - -**Base Class Methods** ([inc/database/base.php](../../inc/database/base.php)): - -| Method | Purpose | -|--------|---------| -| `maybe_create_table()` | Create table if not exists | -| `maybe_add_new_columns()` | Add new columns to existing table | -| `maybe_rename_columns()` | Rename columns (e.g., user_data โ†’ form_data) | -| `upgrade($old_version)` | Custom migration logic per version | - -### Adding a New Column (Example) - -**Step 1:** Increment table version in table class -```php -// In inc/database/tables/entries.php -protected $table_version = 2; // Increment from 1 to 2 -``` - -**Step 2:** Add column to schema -```php -public function get_schema() { - return [ - // ... existing columns - 'new_column' => [ - 'type' => 'string', - 'default' => '', - ], - ]; -} -``` - -**Step 3:** Add column definition -```php -public function get_new_columns_definition() { - return [ - 'new_column VARCHAR(255) DEFAULT "" AFTER status', - ]; -} -``` - -**Step 4:** Implement upgrade logic (if needed) -```php -public function upgrade($old_version) { - global $wpdb; - - if ($old_version < 2) { - // Additional migration logic beyond column addition - $wpdb->query("UPDATE {$this->table_name} SET new_column = 'default_value'"); - } -} -``` - -### Migration Best Practices - -1. **Never Delete Columns** - Mark as deprecated instead - ```php - // DON'T: ALTER TABLE DROP COLUMN old_column - // DO: Leave column, document as deprecated - ``` - -2. **Always Provide Defaults** - Avoid NULL for new columns - ```php - 'new_column VARCHAR(255) DEFAULT ""' // Good - 'new_column VARCHAR(255)' // Bad (no default) - ``` - -3. **Test with Production Data** - Use staging environment first -4. **Log All Migrations** - Use error_log() for debugging -5. **Backwards Compatible** - Old code must work during migration -6. **Atomic Operations** - Use transactions where possible - ---- - -## Common Query Patterns - -### Get All Entries for a Form - -```php -use SRFM\Inc\Database\Tables\Entries; - -$entries = Entries::get_all([ - 'where' => [ - [ - ['key' => 'form_id', 'compare' => '=', 'value' => 123], - ['key' => 'status', 'compare' => '!=', 'value' => 'trash'], - ] - ], - 'orderby' => 'created_at', - 'order' => 'DESC', - 'limit' => 20, - 'offset' => 0 -]); -``` - -**Generated SQL:** -```sql -SELECT * FROM wp_srfm_entries -WHERE form_id = 123 - AND status != 'trash' -ORDER BY created_at DESC -LIMIT 0, 20 -``` - -### Get Entry Count by Status - -```php -$unread_count = Entries::get_total_entries_by_status('unread', $form_id); -$all_count = Entries::get_total_entries_by_status('all', $form_id); -``` - -**Generated SQL:** -```sql --- Unread count -SELECT COUNT(*) FROM wp_srfm_entries -WHERE status = 'unread' AND form_id = 123 - --- All count (excluding trash) -SELECT COUNT(*) FROM wp_srfm_entries -WHERE status != 'trash' AND form_id = 123 -``` - -### Get Entries with Payments - -```php -global $wpdb; - -$entries_with_payments = $wpdb->get_results($wpdb->prepare( - "SELECT e.*, p.total_amount, p.status as payment_status, p.currency - FROM {$wpdb->prefix}srfm_entries e - INNER JOIN {$wpdb->prefix}srfm_payments p ON e.ID = p.entry_id - WHERE e.form_id = %d - AND p.status = 'succeeded' - ORDER BY e.created_at DESC", - $form_id -)); -``` - -### Get Payments by Status - -```php -use SRFM\Inc\Database\Tables\Payments; - -$succeeded_payments = Payments::get_all([ - 'where' => [ - [ - ['key' => 'form_id', 'compare' => '=', 'value' => 123], - ['key' => 'status', 'compare' => '=', 'value' => 'succeeded'], - ] - ], - 'orderby' => 'created_at', - 'order' => 'DESC' -]); -``` - ---- - -## Performance Optimization - -### Indexing Strategy - -**Why Indexes Matter:** -- 10,000+ entries: ~50ms query time with indexes vs ~500ms without -- Composite indexes optimize multi-column WHERE clauses -- Index order matters: (form_id, created_at, status) โ‰  (status, form_id, created_at) - -**Index Usage Guidelines:** - -1. **Use Indexed Columns in WHERE Clauses** -```php -// GOOD - Uses idx_form_id index -$entries = Entries::get_all(['where' => [[['key' => 'form_id', 'compare' => '=', 'value' => 123]]]]); - -// BAD - No index on 'type' column (full table scan) -$entries = Entries::get_all(['where' => [[['key' => 'type', 'compare' => '=', 'value' => 'quiz']]]]); -``` - -2. **Leverage Composite Indexes** -```php -// GOOD - Uses idx_form_id_created_at_status composite index -$entries = Entries::get_all([ - 'where' => [ - [ - ['key' => 'form_id', 'compare' => '=', 'value' => 123], - ['key' => 'created_at', 'compare' => '>', 'value' => '2026-01-01'], - ['key' => 'status', 'compare' => '=', 'value' => 'unread'], - ] - ] -]); -``` - -3. **Avoid SELECT *** -```php -// GOOD - Specify columns -$entries = Entries::get_instance()->get_results( - ['form_id' => 123], - 'ID, form_data, created_at' -); - -// BAD - Selects all columns including large LONGTEXT -$entries = Entries::get_all(['where' => [[['key' => 'form_id', 'compare' => '=', 'value' => 123]]]]); -``` - -### Pagination Best Practices - -```php -// Paginate large result sets -$per_page = 20; -$page = 2; -$offset = ($page - 1) * $per_page; - -$entries = Entries::get_all([ - 'where' => [[['key' => 'form_id', 'compare' => '=', 'value' => 123]]], - 'limit' => $per_page, - 'offset' => $offset, - 'orderby' => 'created_at', - 'order' => 'DESC' -]); - -// Cache total count separately -$total = Entries::get_total_entries_by_status('all', 123); -$total_pages = ceil($total / $per_page); -``` - -### JSON Column Optimization - -**MySQL 5.7+ JSON Functions:** -```sql --- Extract specific field from form_data JSON -SELECT - ID, - JSON_EXTRACT(form_data, '$.email.value') as email -FROM wp_srfm_entries -WHERE form_id = 123; - --- Search within JSON -SELECT * FROM wp_srfm_entries -WHERE JSON_EXTRACT(form_data, '$.email.value') = 'user@example.com'; -``` - -**Performance Warning:** -- JSON queries are slower than indexed columns -- Avoid wildcard searches in JSON (`LIKE '%value%'`) -- Consider extracting frequently-queried JSON fields to dedicated columns - ---- - -## Data Retention & GDPR - -### Auto-Delete Configuration - -**Setting Location:** [inc/single-form-settings/compliance-settings.php](../../inc/single-form-settings/compliance-settings.php) - -**Per-Form Settings:** -```php -$retention_days = get_post_meta($form_id, '_srfm_entry_retention_days', true); -// Values: 0 (never delete), 7, 30, 60, 90, 365 (days) -``` - -**Implementation:** WordPress Cron (Action Scheduler) - -```php -// Scheduled task runs daily at 2 AM -add_action('srfm_daily_scheduled_action', 'srfm_auto_delete_entries'); - -function srfm_auto_delete_entries() { - global $wpdb; - - // Get forms with auto-delete enabled - $forms = $wpdb->get_results(" - SELECT post_id, meta_value as retention_days - FROM {$wpdb->postmeta} - WHERE meta_key = '_srfm_entry_retention_days' - AND meta_value > 0 - "); - - foreach ($forms as $form) { - $cutoff_date = date('Y-m-d H:i:s', strtotime("-{$form->retention_days} days")); - - // Delete entries older than cutoff - $wpdb->delete( - $wpdb->prefix . 'srfm_entries', - [ - 'form_id' => $form->post_id, - 'created_at < ' => $cutoff_date - ] - ); - } -} -``` - -### Manual Entry Management - -**Soft Delete (Trash):** -```php -Entries::update($entry_id, ['status' => 'trash']); -``` - -**Permanent Delete:** -```php -// Fires srfm_before_delete_entry hook -Entries::delete($entry_id); -``` - -**Restore from Trash:** -```php -Entries::update($entry_id, ['status' => 'unread']); -``` - ---- - -## Backup & Recovery - -### Backup Recommendations - -**1. Full Database Backup** (before plugin updates) -```bash -mysqldump -u username -p database_name > sureforms_backup.sql -``` - -**2. Table-Specific Dumps** -```bash -# Entries table -mysqldump -u username -p database_name wp_srfm_entries > entries_backup.sql - -# Payments table -mysqldump -u username -p database_name wp_srfm_payments > payments_backup.sql - -# Form configurations (WordPress tables) -mysqldump -u username -p database_name wp_posts wp_postmeta \ - --where="post_type='sureforms_form'" > forms_backup.sql -``` - -**3. Export Entries via Admin UI** -- Navigate to SureForms โ†’ Entries -- Select entries โ†’ Export CSV -- Includes all form data and metadata - -### Restore Process - -```bash -# Restore from backup -mysql -u username -p database_name < entries_backup.sql - -# Restore specific table -mysql -u username -p database_name < wp_srfm_entries.sql -``` - ---- - -## Troubleshooting - -### Issue: Missing Tables - -**Symptom:** "Table doesn't exist" errors in PHP logs -**Cause:** Tables not created during activation -**Fix:** -1. Deactivate plugin -2. Delete option: `srfm_entries_version`, `srfm_payments_version` -3. Reactivate plugin (triggers table creation) - -### Issue: Charset/Collation Errors - -**Symptom:** Garbled text in submissions (emoji, special characters) -**Cause:** Incorrect charset (not utf8mb4) -**Fix:** -```sql -ALTER TABLE wp_srfm_entries -CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; - -ALTER TABLE wp_srfm_payments -CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -``` - -### Issue: JSON Parsing Errors - -**Symptom:** "Invalid JSON" errors when retrieving form_data -**Cause:** Unescaped quotes in field values -**Fix:** -```php -// Always use wp_json_encode() for JSON storage -$form_data_json = wp_json_encode($form_data); - -// Always use json_decode() with error handling -$form_data = json_decode($form_data_json, true); -if (json_last_error() !== JSON_ERROR_NONE) { - error_log('JSON decode error: ' . json_last_error_msg()); -} -``` - -### Issue: Slow Queries - -**Symptom:** Dashboard loads slowly with many entries -**Cause:** Missing indexes or inefficient queries -**Debug:** -```sql --- Check query execution plan -EXPLAIN SELECT * FROM wp_srfm_entries -WHERE form_id = 123 - AND status = 'unread' -ORDER BY created_at DESC -LIMIT 20; - --- Should show "Using index" in Extra column -``` - -**Fix:** -1. Ensure indexes exist (check `SHOW INDEX FROM wp_srfm_entries`) -2. Use indexed columns in WHERE clauses -3. Add pagination (LIMIT/OFFSET) - ---- - -## Entity Relationship Diagram - -```mermaid -erDiagram - wp_posts ||--o{ wp_srfm_entries : "has many" - wp_posts ||--o{ wp_srfm_payments : "has many" - wp_srfm_entries ||--o| wp_srfm_payments : "may have" - wp_users ||--o{ wp_srfm_entries : "submits" - - wp_posts { - bigint ID PK - varchar post_type "sureforms_form" - longtext post_content "Gutenberg blocks" - varchar post_status "draft|publish|trash" - } - - wp_srfm_entries { - bigint ID PK - bigint form_id FK - bigint user_id FK - longtext form_data "JSON" - varchar status "unread|read|trash" - timestamp created_at - } - - wp_srfm_payments { - bigint id PK - bigint form_id FK - bigint entry_id FK - varchar status "pending|succeeded|failed" - decimal total_amount - varchar currency - varchar transaction_id - timestamp created_at - } - - wp_users { - bigint ID PK - varchar user_email - } -``` - ---- - -## Summary - -**Storage Strategy:** -- **Forms:** WordPress custom post type (native CMS benefits) -- **Entries:** Custom table (performance optimization) -- **Payments:** Custom table (financial data tracking) - -**Key Design Decisions:** -- Custom tables for scalability (handle millions of entries) -- JSON columns for flexible schema (form fields vary per form) -- Composite indexes for query optimization -- Version-controlled migrations for safe schema updates - -**Maintenance:** -- Regular backups before plugin updates -- Monitor table sizes (OPTIMIZE TABLE if needed) -- Review slow query logs -- Test migrations on staging first - ---- - -**Related Documentation:** -- [CLAUDE.md](../../CLAUDE.md) - AI agent guide -- [ARCHITECTURE.md](../02-architecture/ARCHITECTURE.md) - System design -- [CODING-STANDARDS.md](../03-development/CODING-STANDARDS.md) - Code style -- [SECURITY.md](../07-security/SECURITY.md) - Security practices diff --git a/docs/04-backend/HOOKS-REFERENCE.md b/docs/04-backend/HOOKS-REFERENCE.md deleted file mode 100644 index 35b5c4c12..000000000 --- a/docs/04-backend/HOOKS-REFERENCE.md +++ /dev/null @@ -1,1055 +0,0 @@ -# SureForms Hooks Reference - -> **Purpose:** Complete reference of all WordPress actions and filters for extending SureForms -> **Audience:** Plugin developers, theme developers, integrators -> **Last Updated:** 2026-02-06 -> **Plugin Version:** 2.5.0 - -## Overview - -SureForms provides **450+ hooks** (actions and filters) for extending functionality without modifying core files. This document catalogs the most commonly used hooks with usage examples. - -**Hook Naming Convention:** -- **Prefix:** All hooks start with `srfm_` -- **Format:** `srfm_{context}_{action}` or `srfm_{data_type}_{modification}` -- **Examples:** `srfm_before_submission`, `srfm_field_validation`, `srfm_email_content` - ---- - -## Table of Contents - -- [Plugin Lifecycle](#plugin-lifecycle) -- [Form Submission](#form-submission) -- [Field Validation](#field-validation) -- [Email Notifications](#email-notifications) -- [Form Rendering](#form-rendering) -- [Data Modification](#data-modification) -- [Database Operations](#database-operations) -- [Payment Processing](#payment-processing) -- [Block Registration](#block-registration) -- [Admin Operations](#admin-operations) -- [Integration Points](#integration-points) - ---- - -## Plugin Lifecycle - -### `srfm_core_loaded` - -Fires after the plugin core is fully loaded and initialized. - -**Location:** [plugin-loader.php](../../plugin-loader.php) -**Since:** 0.0.1 -**Parameters:** None - -**Usage:** -```php -add_action('srfm_core_loaded', function() { - // Plugin is ready, initialize custom extensions - error_log('SureForms plugin loaded'); - - // Register custom integrations - my_custom_sureforms_integration(); -}); -``` - -### `srfm_init` - -Fires during WordPress `init` hook after SureForms initialization. - -**Location:** [plugin-loader.php](../../plugin-loader.php) -**Since:** 0.0.1 -**Parameters:** None - -**Usage:** -```php -add_action('srfm_init', function() { - // Register custom post types, taxonomies, or other WordPress entities - register_post_type('custom_form_data', [ - 'public' => false, - 'supports' => ['title'] - ]); -}); -``` - ---- - -## Form Submission - -### `srfm_before_submission` - -Fires immediately before form data is processed and saved to database. Use to validate or modify data before processing. - -**Location:** [inc/form-submit.php:525](../../inc/form-submit.php) -**Since:** 0.0.1 -**Parameters:** -- `array $form_data` - Submitted form data including form_id, fields, and metadata - -**Usage:** -```php -add_action('srfm_before_submission', function($form_data) { - $form_id = $form_data['form_id'] ?? 0; - - // Log submission attempt - error_log(sprintf('Form %d submission started', $form_id)); - - // Perform custom validation - if ($form_id === 123) { - $email = $form_data['email']['value'] ?? ''; - if (strpos($email, '@company.com') === false) { - // Throw exception to halt submission - throw new Exception('Only company emails allowed'); - } - } -}, 10, 1); -``` - -### `srfm_after_submission_process` - -Fires after form entry is saved to database but before email notifications are sent. - -**Location:** [inc/form-submit.php:556](../../inc/form-submit.php) -**Since:** 0.0.1 -**Parameters:** -- `array $form_data` - Complete form data including entry_id - -**Usage:** -```php -add_action('srfm_after_submission_process', function($form_data) { - $entry_id = $form_data['entry_id'] ?? 0; - $form_id = $form_data['form_id'] ?? 0; - - // Trigger third-party integration - if ($form_id === 123) { - $email = $form_data['email']['value'] ?? ''; - $name = $form_data['name']['value'] ?? ''; - - // Add to MailChimp - mailchimp_add_subscriber($email, $name); - - // Send to CRM - crm_create_lead([ - 'email' => $email, - 'name' => $name, - 'source' => 'sureforms' - ]); - } -}, 10, 1); -``` - -### `srfm_form_submit` - -Fires after complete form submission process (entry saved, emails sent). - -**Location:** [inc/form-submit.php:548,644](../../inc/form-submit.php) -**Since:** 0.0.1 -**Parameters:** -- `array $response` - Submission response with entry_id, success status, message - -**Usage:** -```php -add_action('srfm_form_submit', function($response) { - if ($response['success']) { - $entry_id = $response['entry_id']; - - // Custom logging - error_log(sprintf('Form submission %d completed', $entry_id)); - - // Update custom database - global $wpdb; - $wpdb->insert('wp_custom_leads', [ - 'sureforms_entry_id' => $entry_id, - 'created_at' => current_time('mysql') - ]); - } -}, 10, 1); -``` - ---- - -## Field Validation - -### `srfm_field_validation` - -Filters field validation result. Return `WP_Error` to fail validation. - -**Location:** [inc/field-validation.php](../../inc/field-validation.php) -**Since:** 0.0.1 -**Parameters:** -- `bool|WP_Error $is_valid` - Current validation status -- `mixed $field_value` - Field value to validate -- `array $field_data` - Field metadata (type, label, required, etc.) -- `int $form_id` - Form post ID - -**Return:** `bool|WP_Error` - True if valid, WP_Error if invalid - -**Usage:** -```php -add_filter('srfm_field_validation', function($is_valid, $field_value, $field_data, $form_id) { - // Custom validation for specific field type - if ($field_data['type'] === 'text' && $field_data['slug'] === 'phone') { - // Validate phone format - if (!preg_match('/^\+?[1-9]\d{1,14}$/', $field_value)) { - return new WP_Error( - 'invalid_phone', - __('Please enter a valid phone number', 'your-plugin') - ); - } - } - - // Custom validation for specific form - if ($form_id === 123 && $field_data['slug'] === 'age') { - if (intval($field_value) < 18) { - return new WP_Error( - 'age_restriction', - __('You must be 18 or older', 'your-plugin') - ); - } - } - - return $is_valid; -}, 10, 4); -``` - -### `srfm_validate_{field_type}` - -Filters validation for specific field type. - -**Location:** [inc/field-validation.php](../../inc/field-validation.php) -**Since:** Various -**Available Types:** `email`, `phone`, `url`, `number`, `text`, etc. - -**Usage:** -```php -// Custom email validation -add_filter('srfm_validate_email', function($is_valid, $value, $field_data) { - // Block disposable email domains - $disposable_domains = ['tempmail.com', 'throwaway.email']; - $domain = substr(strrchr($value, '@'), 1); - - if (in_array($domain, $disposable_domains)) { - return new WP_Error( - 'disposable_email', - __('Disposable email addresses are not allowed', 'your-plugin') - ); - } - - return $is_valid; -}, 10, 3); -``` - ---- - -## Email Notifications - -### `srfm_email_notification_should_send` - -Filters whether email notification should be sent. - -**Location:** [inc/form-submit.php:796](../../inc/form-submit.php) -**Since:** Various -**Parameters:** -- `array $email_notification` - Email configuration -- `array $submission_data` - Submitted form data -- `array $form_data` - Complete form metadata - -**Return:** `array|false` - Email config to send, false to skip - -**Usage:** -```php -add_filter('srfm_email_notification_should_send', function($email_notification, $submission_data, $form_data) { - $form_id = $form_data['form_id'] ?? 0; - - // Only send email for specific form if user opted in - if ($form_id === 123) { - $opted_in = $submission_data['email_optin']['value'] ?? false; - if (!$opted_in) { - return false; // Skip email - } - } - - return $email_notification; -}, 10, 3); -``` - -### `srfm_email_notification` - -Filters parsed email data before sending. - -**Location:** [inc/form-submit.php:809](../../inc/form-submit.php) -**Since:** Various -**Parameters:** -- `array $parsed` - Parsed email data (to, subject, message, headers) -- `array $submission_data` - Submitted form data -- `array $item` - Email notification configuration -- `array $form_data` - Form metadata - -**Return:** `array` - Modified email data - -**Usage:** -```php -add_filter('srfm_email_notification', function($parsed, $submission_data, $item, $form_data) { - // Add custom header - $parsed['headers'][] = 'X-Form-ID: ' . ($form_data['form_id'] ?? 0); - - // Modify subject based on submission data - if (isset($submission_data['priority']['value']) && $submission_data['priority']['value'] === 'high') { - $parsed['subject'] = '[URGENT] ' . $parsed['subject']; - } - - // Add custom footer to message - $parsed['message'] .= "\n\n---\nSubmitted via SureForms"; - - return $parsed; -}, 10, 4); -``` - -### `srfm_before_email_send` - -Action fired immediately before email is sent via `wp_mail()`. - -**Location:** [inc/form-submit.php:812](../../inc/form-submit.php) -**Since:** Various -**Parameters:** -- `array $parsed` - Email data (to, subject, message, headers) -- `array $submission_data` - Submitted form data -- `array $item` - Email notification configuration -- `array $form_data` - Form metadata - -**Usage:** -```php -add_action('srfm_before_email_send', function($parsed, $submission_data, $item, $form_data) { - // Log email send attempt - error_log(sprintf( - 'Sending email to %s for form %d', - $parsed['to'], - $form_data['form_id'] ?? 0 - )); - - // Save email to custom table for tracking - global $wpdb; - $wpdb->insert('wp_email_log', [ - 'recipient' => $parsed['to'], - 'subject' => $parsed['subject'], - 'sent_at' => current_time('mysql') - ]); -}, 10, 4); -``` - -### `srfm_after_email_send` - -Action fired after email is sent. - -**Location:** [inc/form-submit.php:904-905](../../inc/form-submit.php) -**Since:** Various -**Parameters:** -- `array $parsed` - Email data -- `array $submission_data` - Form data -- `array $item` - Email config -- `array $form_data` - Form metadata -- `bool $sent` - Whether email was sent successfully - -**Usage:** -```php -add_action('srfm_after_email_send', function($parsed, $submission_data, $item, $form_data, $sent) { - if (!$sent) { - // Email failed to send - error_log(sprintf( - 'Email failed for form %d to %s', - $form_data['form_id'] ?? 0, - $parsed['to'] - )); - - // Send alert to admin - wp_mail( - get_option('admin_email'), - 'Form email notification failed', - sprintf('Failed to send notification for form %d', $form_data['form_id']) - ); - } -}, 10, 5); -``` - ---- - -## Data Modification - -### `srfm_form_submit_data` - -Filters complete form submission data before processing. - -**Location:** [inc/form-submit.php:474](../../inc/form-submit.php) -**Since:** 0.0.1 -**Parameters:** -- `array $form_data` - Complete form data - -**Return:** `array` - Modified form data - -**Usage:** -```php -add_filter('srfm_form_submit_data', function($form_data) { - // Add custom calculated field - if (isset($form_data['price'], $form_data['quantity'])) { - $form_data['total'] = [ - 'value' => $form_data['price']['value'] * $form_data['quantity']['value'], - 'label' => 'Total Amount', - 'type' => 'calculated' - ]; - } - - // Add timestamp - $form_data['submitted_timestamp'] = [ - 'value' => current_time('mysql'), - 'label' => 'Submission Time', - 'type' => 'hidden' - ]; - - return $form_data; -}, 10, 1); -``` - -### `srfm_before_entry_data` - -Filters entry data before saving to database. - -**Location:** [inc/form-submit.php:605-606](../../inc/form-submit.php) -**Since:** 0.0.1 -**Parameters:** -- `array $entries_data` - Entry data to be saved -- `int $form_id` - Form post ID - -**Return:** `array` - Modified entry data - -**Usage:** -```php -add_filter('srfm_before_entry_data', function($entries_data, $form_id) { - // Add custom extras data - $entries_data['extras'] = [ - 'ip_country' => get_user_ip_country(), - 'utm_source' => $_GET['utm_source'] ?? '', - 'utm_campaign' => $_GET['utm_campaign'] ?? '', - 'referrer' => wp_get_referer() - ]; - - // Modify status based on conditions - if ($form_id === 123) { - $entries_data['status'] = 'pending_review'; // Custom status - } - - return $entries_data; -}, 10, 2); -``` - -### `srfm_form_submission_response` - -Filters final submission response sent to frontend. - -**Location:** [inc/form-submit.php:660](../../inc/form-submit.php) -**Since:** 2.4.0 -**Parameters:** -- `array $response` - Response data (success, message, entry_id) -- `array $form_data` - Form data -- `array $submission_data` - Submission data - -**Return:** `array` - Modified response - -**Usage:** -```php -add_filter('srfm_form_submission_response', function($response, $form_data, $submission_data) { - // Add custom data to response - if ($response['success']) { - $response['custom_redirect_url'] = 'https://example.com/thank-you'; - $response['tracking_code'] = 'FB-' . $response['entry_id']; - - // Add custom message - $response['custom_message'] = sprintf( - 'Thank you! Your reference number is %d', - $response['entry_id'] - ); - } - - return $response; -}, 10, 3); -``` - -### `srfm_process_field_value` - -Filters individual field value during processing. - -**Location:** [inc/form-submit.php:1211-1212](../../inc/form-submit.php) -**Since:** 0.0.1 -**Parameters:** -- `mixed $value` - Field value -- `array $field` - Field data -- `array $form_data` - Complete form data - -**Return:** `mixed` - Modified field value - -**Usage:** -```php -add_filter('srfm_process_field_value', function($value, $field, $form_data) { - // Normalize phone numbers - if ($field['type'] === 'phone') { - $value = preg_replace('/[^0-9+]/', '', $value); - } - - // Convert text to uppercase for specific field - if ($field['slug'] === 'reference_code') { - $value = strtoupper($value); - } - - // Encrypt sensitive data - if ($field['slug'] === 'ssn') { - $value = encrypt_data($value); - } - - return $value; -}, 10, 3); -``` - ---- - -## Form Rendering - -### `srfm_form_markup` - -Filters complete form HTML before rendering. - -**Location:** [inc/generate-form-markup.php](../../inc/generate-form-markup.php) -**Since:** 0.0.1 -**Parameters:** -- `string $markup` - Generated HTML -- `int $form_id` - Form post ID -- `array $blocks` - Gutenberg blocks array - -**Return:** `string` - Modified HTML - -**Usage:** -```php -add_filter('srfm_form_markup', function($markup, $form_id, $blocks) { - // Add custom wrapper - $markup = '
' . $markup . '
'; - - // Add custom analytics tracking - $markup .= sprintf( - '', - $form_id - ); - - return $markup; -}, 10, 3); -``` - -### `srfm_field_markup` - -Filters individual field HTML. - -**Location:** [inc/fields/base.php](../../inc/fields/base.php) -**Since:** 0.0.1 -**Parameters:** -- `string $markup` - Field HTML -- `array $attributes` - Block attributes -- `string $field_type` - Field type (input, email, etc.) - -**Return:** `string` - Modified HTML - -**Usage:** -```php -add_filter('srfm_field_markup', function($markup, $attributes, $field_type) { - // Add custom class to all email fields - if ($field_type === 'email') { - $markup = str_replace( - 'class="srfm-field', - 'class="srfm-field custom-email-field', - $markup - ); - } - - // Add tooltips - if (!empty($attributes['help_text'])) { - $markup .= sprintf( - '%s', - esc_html($attributes['help_text']) - ); - } - - return $markup; -}, 10, 3); -``` - -### `srfm_form_class` - -Filters CSS classes applied to form element. - -**Location:** [inc/generate-form-markup.php](../../inc/generate-form-markup.php) -**Since:** 0.0.1 -**Parameters:** -- `array $classes` - CSS class array -- `int $form_id` - Form post ID - -**Return:** `array` - Modified classes - -**Usage:** -```php -add_filter('srfm_form_class', function($classes, $form_id) { - // Add custom class - $classes[] = 'custom-form'; - - // Add class based on form ID - $classes[] = 'form-' . $form_id; - - // Add class based on form type - $form_type = get_post_meta($form_id, '_srfm_form_type', true); - if ($form_type === 'contact') { - $classes[] = 'contact-form'; - } - - return $classes; -}, 10, 2); -``` - ---- - -## Database Operations - -### `srfm_before_delete_entry` - -Action fired before entry is permanently deleted from database. - -**Location:** [inc/database/tables/entries.php:297](../../inc/database/tables/entries.php) -**Since:** 0.0.13 -**Parameters:** -- `int $entry_id` - Entry ID being deleted - -**Usage:** -```php -add_action('srfm_before_delete_entry', function($entry_id) { - // Log deletion - error_log(sprintf('Deleting entry %d', $entry_id)); - - // Clean up related data - global $wpdb; - $wpdb->delete('wp_custom_entry_meta', ['entry_id' => $entry_id]); - - // Archive entry before deletion - $entry = SRFM\Inc\Database\Tables\Entries::get($entry_id); - if ($entry) { - $wpdb->insert('wp_deleted_entries_archive', [ - 'entry_id' => $entry_id, - 'form_data' => wp_json_encode($entry), - 'deleted_at' => current_time('mysql') - ]); - } -}, 10, 1); -``` - ---- - -## Payment Processing - -### `srfm_before_payment_process` - -Action fired before payment processing starts. - -**Location:** [inc/payments/front-end.php](../../inc/payments/front-end.php) -**Since:** 2.0.0 -**Parameters:** -- `array $payment_data` - Payment data -- `int $form_id` - Form post ID - -**Usage:** -```php -add_action('srfm_before_payment_process', function($payment_data, $form_id) { - // Log payment attempt - error_log(sprintf( - 'Processing payment of %s %s for form %d', - $payment_data['amount'], - $payment_data['currency'], - $form_id - )); - - // Verify inventory before charging - if ($form_id === 123) { - $product_id = $payment_data['product_id'] ?? 0; - if (!check_inventory($product_id)) { - throw new Exception('Product out of stock'); - } - } -}, 10, 2); -``` - -### `srfm_after_payment_success` - -Action fired after successful payment. - -**Location:** [inc/payments/front-end.php](../../inc/payments/front-end.php) -**Since:** 2.0.0 -**Parameters:** -- `int $payment_id` - Payment record ID -- `array $payment_data` - Payment data -- `int $entry_id` - Entry ID - -**Usage:** -```php -add_action('srfm_after_payment_success', function($payment_id, $payment_data, $entry_id) { - // Send receipt - $customer_email = $payment_data['customer_email']; - wp_mail( - $customer_email, - 'Payment Receipt', - sprintf('Payment of %s received', $payment_data['total_amount']) - ); - - // Update inventory - update_inventory($payment_data['product_id'], -1); - - // Trigger fulfillment - trigger_order_fulfillment($payment_id); -}, 10, 3); -``` - ---- - -## Block Registration - -### `srfm_block_registration_args` - -Filters block registration arguments. - -**Location:** [inc/blocks/register.php](../../inc/blocks/register.php) -**Since:** 0.0.1 -**Parameters:** -- `array $args` - Block registration args -- `string $block_name` - Block name (sureforms/input, etc.) - -**Return:** `array` - Modified args - -**Usage:** -```php -add_filter('srfm_block_registration_args', function($args, $block_name) { - // Modify render callback - if ($block_name === 'sureforms/input') { - $original_callback = $args['render_callback']; - $args['render_callback'] = function($attributes, $content) use ($original_callback) { - // Wrap output in custom div - $output = call_user_func($original_callback, $attributes, $content); - return '
' . $output . '
'; - }; - } - - return $args; -}, 10, 2); -``` - ---- - -## Admin Operations - -### `srfm_after_form_created` - -Action fired after new form is created. - -**Location:** [inc/create-new-form.php](../../inc/create-new-form.php) -**Since:** 0.0.1 -**Parameters:** -- `int $form_id` - Created form post ID - -**Usage:** -```php -add_action('srfm_after_form_created', function($form_id) { - // Set default form settings - update_post_meta($form_id, '_srfm_custom_setting', 'default_value'); - - // Log form creation - error_log(sprintf('New form created: %d', $form_id)); - - // Notify admin - wp_mail( - get_option('admin_email'), - 'New form created', - sprintf('Form ID %d was created', $form_id) - ); -}, 10, 1); -``` - ---- - -## Form Restrictions - -### `srfm_form_restriction_message` - -Filters restriction message shown to users. - -**Location:** [inc/form-submit.php:267](../../inc/form-submit.php) -**Since:** Various -**Parameters:** -- `string $message` - Default restriction message -- `int $form_id` - Form post ID -- `array $form_restriction` - Restriction settings - -**Return:** `string` - Modified message - -**Usage:** -```php -add_filter('srfm_form_restriction_message', function($message, $form_id, $form_restriction) { - // Custom message based on restriction type - if ($form_restriction['type'] === 'schedule' && $form_restriction['state'] === 'not_started') { - $message = sprintf( - 'This form will open on %s', - date('F j, Y', strtotime($form_restriction['start_date'])) - ); - } - - return $message; -}, 10, 3); -``` - -### `srfm_additional_restriction_check` - -Filters whether form has additional restrictions beyond scheduling. - -**Location:** [inc/form-submit.php:276](../../inc/form-submit.php) -**Since:** Various -**Parameters:** -- `bool $is_restricted` - Whether form is restricted -- `int $form_id` - Form post ID -- `array $form_data` - Form data - -**Return:** `bool` - True to restrict, false to allow - -**Usage:** -```php -add_filter('srfm_additional_restriction_check', function($is_restricted, $form_id, $form_data) { - // Restrict based on user role - if ($form_id === 123 && !current_user_can('subscriber')) { - return true; // Restrict - } - - // Restrict based on IP - $user_ip = $_SERVER['REMOTE_ADDR']; - if (is_ip_blocked($user_ip)) { - return true; - } - - // Restrict based on previous submissions - $user_email = $form_data['email']['value'] ?? ''; - if ($user_email && has_recent_submission($form_id, $user_email)) { - return true; // Already submitted recently - } - - return $is_restricted; -}, 10, 3); -``` - ---- - -## Integration Points - -### Third-Party Service Integration Example - -```php -/** - * Complete integration example: Send form data to CRM after submission - */ -class SureForms_CRM_Integration { - public function __construct() { - add_action('srfm_after_submission_process', [$this, 'send_to_crm'], 10, 1); - add_action('srfm_before_delete_entry', [$this, 'delete_from_crm'], 10, 1); - } - - public function send_to_crm($form_data) { - // Only for contact forms - if ($form_data['form_id'] !== 123) { - return; - } - - $crm_data = [ - 'email' => $form_data['email']['value'] ?? '', - 'name' => $form_data['name']['value'] ?? '', - 'phone' => $form_data['phone']['value'] ?? '', - 'company' => $form_data['company']['value'] ?? '', - 'source' => 'sureforms', - 'entry_id' => $form_data['entry_id'] ?? 0 - ]; - - $response = wp_remote_post('https://crm.example.com/api/leads', [ - 'body' => json_encode($crm_data), - 'headers' => [ - 'Content-Type' => 'application/json', - 'Authorization' => 'Bearer ' . get_option('crm_api_key') - ] - ]); - - if (is_wp_error($response)) { - error_log('CRM sync failed: ' . $response->get_error_message()); - } else { - $crm_id = json_decode(wp_remote_retrieve_body($response))->id; - // Store CRM ID with entry - update_post_meta($form_data['entry_id'], '_crm_lead_id', $crm_id); - } - } - - public function delete_from_crm($entry_id) { - $crm_id = get_post_meta($entry_id, '_crm_lead_id', true); - if ($crm_id) { - wp_remote_request('https://crm.example.com/api/leads/' . $crm_id, [ - 'method' => 'DELETE', - 'headers' => [ - 'Authorization' => 'Bearer ' . get_option('crm_api_key') - ] - ]); - } - } -} - -new SureForms_CRM_Integration(); -``` - ---- - -## Hook Priority Guidelines - -**Priority Values:** -- **5:** Execute before default behavior -- **10:** Default priority (most hooks) -- **15:** Execute after default behavior -- **20+:** Late execution -- **100+:** Very late (cleanup, logging) - -**Example:** -```php -// Execute before SureForms processes submission -add_action('srfm_before_submission', 'my_function', 5); - -// Execute at default time -add_action('srfm_before_submission', 'my_function', 10); - -// Execute after SureForms processes submission -add_action('srfm_before_submission', 'my_function', 15); -``` - ---- - -## Debugging Hooks - -### Enable Hook Debugging - -```php -// Add to wp-config.php -define('SRFM_DEBUG_HOOKS', true); - -// Log all SureForms hooks -add_action('all', function($hook) { - if (strpos($hook, 'srfm_') === 0) { - error_log('Hook fired: ' . $hook); - } -}); -``` - -### View Hook Execution Order - -```php -// Log hook priority and callback -add_action('all', function($hook) { - if (strpos($hook, 'srfm_') === 0) { - global $wp_filter; - if (isset($wp_filter[$hook])) { - foreach ($wp_filter[$hook]->callbacks as $priority => $callbacks) { - foreach ($callbacks as $callback) { - error_log(sprintf( - 'Hook: %s, Priority: %d, Callback: %s', - $hook, - $priority, - is_array($callback['function']) ? - get_class($callback['function'][0]) . '::' . $callback['function'][1] : - $callback['function'] - )); - } - } - } - } -}); -``` - ---- - -## Best Practices - -### 1. Always Check Hook Existence - -```php -if (function_exists('add_action')) { - add_action('srfm_after_submission_process', 'my_function'); -} -``` - -### 2. Use Proper Nonces for Custom Forms - -```php -add_filter('srfm_before_entry_data', function($data, $form_id) { - // Verify custom nonce if adding custom fields - if (isset($_POST['custom_nonce'])) { - if (!wp_verify_nonce($_POST['custom_nonce'], 'custom_action')) { - return new WP_Error('nonce_failed', 'Security check failed'); - } - } - return $data; -}, 10, 2); -``` - -### 3. Return Correct Data Types - -```php -// Filter must return array -add_filter('srfm_form_submit_data', function($data) { - // โœ… GOOD - returns array - return array_merge($data, ['custom' => 'value']); - - // โŒ BAD - returns nothing - // (void return breaks functionality) -}, 10, 1); -``` - -### 4. Handle Errors Gracefully - -```php -add_action('srfm_after_submission_process', function($form_data) { - try { - // Risky operation - send_to_external_api($form_data); - } catch (Exception $e) { - error_log('External API failed: ' . $e->getMessage()); - // Don't throw - allow submission to continue - } -}, 10, 1); -``` - ---- - -## Summary - -**Hook Categories:** -- **Lifecycle:** 2 hooks (core_loaded, init) -- **Submission:** 10+ hooks (before, during, after) -- **Validation:** 5+ hooks (field-specific and general) -- **Email:** 5+ hooks (before, during, after send) -- **Rendering:** 10+ hooks (markup, classes, attributes) -- **Data:** 8+ hooks (modify, filter, transform) -- **Database:** 3+ hooks (before/after operations) -- **Payment:** 6+ hooks (process, success, failure) -- **Admin:** 5+ hooks (form creation, updates) - -**Total:** 450+ hooks across the plugin - -**Auto-Generation Note:** This document contains the most commonly used hooks. For a complete list, run the hook extraction script: -```bash -php scripts/extract-hooks.php > docs/COMPLETE-HOOKS-LIST.md -``` - ---- - -**Related Documentation:** -- [CLAUDE.md](../../CLAUDE.md) - AI agent guide -- [ARCHITECTURE.md](../02-architecture/ARCHITECTURE.md) - System design -- [REST-API.md](REST-API.md) - REST API endpoints -- [DATABASE-SCHEMA.md](DATABASE-SCHEMA.md) - Database tables diff --git a/docs/05-frontend/FRONTEND-GUIDE.md b/docs/05-frontend/FRONTEND-GUIDE.md deleted file mode 100644 index d26f09ee8..000000000 --- a/docs/05-frontend/FRONTEND-GUIDE.md +++ /dev/null @@ -1,1197 +0,0 @@ -# SureForms Frontend Development Guide - -> **Purpose:** Comprehensive guide for React/Gutenberg block development -> **Audience:** Frontend developers working with React, Gutenberg, and WordPress -> **Last Updated:** 2026-02-06 -> **Plugin Version:** 2.5.0 - -## Overview - -SureForms frontend is built with modern JavaScript technologies integrated deeply with WordPress's Gutenberg block editor: - -- **React 18.2:** UI components and interactive features -- **Gutenberg Blocks:** WordPress block editor integration for form building -- **TailwindCSS 3.4:** Utility-first CSS framework -- **React Query 5.x:** Server state management and caching -- **@wordpress/scripts 26.2:** Build tooling (Webpack 5 wrapper) - ---- - -## Table of Contents - -- [Architecture Overview](#architecture-overview) -- [Directory Structure](#directory-structure) -- [Creating Gutenberg Blocks](#creating-gutenberg-blocks) -- [State Management](#state-management) -- [Component Patterns](#component-patterns) -- [Styling](#styling) -- [Form Validation](#form-validation) -- [Internationalization](#internationalization) -- [Performance Optimization](#performance-optimization) -- [Testing](#testing) - ---- - -## Architecture Overview - -### Technology Stack - -``` -โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” -โ”‚ Admin UI (React Apps) โ”‚ -โ”‚ Dashboard, Settings, Entries, Editor โ”‚ -โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ - โ”‚ - โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” - โ”‚ โ”‚ -โ”Œโ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ” -โ”‚ Gutenberg โ”‚ โ”‚ Admin โ”‚ -โ”‚ Blocks โ”‚ โ”‚ Pages โ”‚ -โ”‚ (Editor) โ”‚ โ”‚ (Router) โ”‚ -โ””โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”˜ - โ”‚ โ”‚ - โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ - โ”‚ - โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” - โ”‚ State Management โ”‚ - โ”‚ Data Store + Hooks โ”‚ - โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ - โ”‚ - โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” - โ”‚ REST API โ”‚ - โ”‚ /sureforms/v1/* โ”‚ - โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ -``` - -### Component Layers - -1. **Gutenberg Block Layer** - Form builder blocks (src/blocks/) -2. **Admin UI Layer** - React SPA pages (src/admin/) -3. **Shared Components** - Reusable UI (src/components/) -4. **State Layer** - Data stores (src/store/) -5. **API Layer** - WordPress REST API - ---- - -## Directory Structure - -``` -src/ -โ”œโ”€โ”€ blocks/ # Gutenberg block components -โ”‚ โ”œโ”€โ”€ blocks.js # Block registration entry -โ”‚ โ”œโ”€โ”€ register-block.js # Block utilities -โ”‚ โ”‚ -โ”‚ โ”œโ”€โ”€ sform/ # Form container block -โ”‚ โ”‚ โ”œโ”€โ”€ index.js # Block registration -โ”‚ โ”‚ โ”œโ”€โ”€ edit.js # Editor component -โ”‚ โ”‚ โ”œโ”€โ”€ save.js # Frontend save (returns null) -โ”‚ โ”‚ โ”œโ”€โ”€ block.json # Block metadata -โ”‚ โ”‚ โ”œโ”€โ”€ components/ # Block-specific components -โ”‚ โ”‚ โ””โ”€โ”€ style.scss # Block styles -โ”‚ โ”‚ -โ”‚ โ”œโ”€โ”€ input/ # Text input field block -โ”‚ โ”‚ โ”œโ”€โ”€ edit.js # Editor with InspectorControls -โ”‚ โ”‚ โ”œโ”€โ”€ save.js # Server-side rendering -โ”‚ โ”‚ โ””โ”€โ”€ block.json # Attributes schema -โ”‚ โ”‚ -โ”‚ โ””โ”€โ”€ [14+ more blocks] # Email, textarea, checkbox, etc. -โ”‚ -โ”œโ”€โ”€ admin/ # Admin dashboard React apps -โ”‚ โ”œโ”€โ”€ dashboard/ # Forms listing page -โ”‚ โ”‚ โ”œโ”€โ”€ index.js # Entry point -โ”‚ โ”‚ โ”œโ”€โ”€ FormsTable.js # Table component -โ”‚ โ”‚ โ”œโ”€โ”€ Analytics.js # Analytics widgets -โ”‚ โ”‚ โ””โ”€โ”€ styles.scss -โ”‚ โ”‚ -โ”‚ โ”œโ”€โ”€ single-form-settings/ # Form editor -โ”‚ โ”‚ โ”œโ”€โ”€ Editor.js # Main editor wrapper -โ”‚ โ”‚ โ”œโ”€โ”€ InstantForm.js # Live preview -โ”‚ โ”‚ โ”œโ”€โ”€ tabs/ # Settings tabs -โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ GeneralSettings.js -โ”‚ โ”‚ โ”‚ โ””โ”€โ”€ StyleSettings.js -โ”‚ โ”‚ โ””โ”€โ”€ components/ # Editor components -โ”‚ โ”‚ -โ”‚ โ”œโ”€โ”€ entries/ # Entry management -โ”‚ โ”œโ”€โ”€ settings/ # Global settings -โ”‚ โ”œโ”€โ”€ payment/ # Payment settings -โ”‚ โ””โ”€โ”€ onboarding/ # Setup wizard -โ”‚ -โ”œโ”€โ”€ components/ # Shared React components -โ”‚ โ”œโ”€โ”€ ui/ # UI primitives -โ”‚ โ”‚ โ”œโ”€โ”€ Button/ -โ”‚ โ”‚ โ”œโ”€โ”€ Input/ -โ”‚ โ”‚ โ”œโ”€โ”€ Modal/ -โ”‚ โ”‚ โ””โ”€โ”€ Tooltip/ -โ”‚ โ”‚ -โ”‚ โ”œโ”€โ”€ form/ # Form-specific -โ”‚ โ”‚ โ”œโ”€โ”€ FieldWrapper/ -โ”‚ โ”‚ โ”œโ”€โ”€ ValidationMessage/ -โ”‚ โ”‚ โ””โ”€โ”€ FormContainer/ -โ”‚ โ”‚ -โ”‚ โ”œโ”€โ”€ inspector-tabs/ # Block editor tabs -โ”‚ โ”œโ”€โ”€ color-switch-control/ # Color picker -โ”‚ โ”œโ”€โ”€ spacing-control/ # Responsive spacing -โ”‚ โ””โ”€โ”€ [40+ component dirs] -โ”‚ -โ”œโ”€โ”€ srfm-controls/ # Gutenberg block controls -โ”‚ โ”œโ”€โ”€ index.js # Control registry -โ”‚ โ”œโ”€โ”€ getPreviewType.js # Responsive preview -โ”‚ โ””โ”€โ”€ [18+ control definitions] -โ”‚ -โ”œโ”€โ”€ store/ # WordPress Data Store (Redux) -โ”‚ โ”œโ”€โ”€ store.js # Store creation -โ”‚ โ”œโ”€โ”€ actions.js # Action creators -โ”‚ โ”œโ”€โ”€ reducer.js # Reducer function -โ”‚ โ”œโ”€โ”€ selectors.js # Selectors -โ”‚ โ””โ”€โ”€ constants.js # Action types -โ”‚ -โ”œโ”€โ”€ utils/ # Utility functions -โ”‚ โ”œโ”€โ”€ Helpers.js # Common helpers -โ”‚ โ”œโ”€โ”€ datePickerHelper.js -โ”‚ โ””โ”€โ”€ addressFieldHelper.js -โ”‚ -โ””โ”€โ”€ styles/ # Global styles - โ”œโ”€โ”€ typography/ - โ””โ”€โ”€ breakpoints/ -``` - -**Build Output:** -``` -assets/build/ -โ”œโ”€โ”€ formEditor.js # Form editor bundle (~1.9MB) -โ”œโ”€โ”€ blocks.js # Gutenberg blocks (~1.3MB) -โ”œโ”€โ”€ dashboard.js # Dashboard page (~1.3MB) -โ”œโ”€โ”€ entries.js # Entries page (~728KB) -โ”œโ”€โ”€ forms.js # Forms listing (~727KB) -โ”œโ”€โ”€ settings.js # Settings page (~1.1MB) -โ”œโ”€โ”€ formSubmit.js # Frontend submission (~60KB) -โ””โ”€โ”€ *.asset.php # Webpack dependency manifests -``` - ---- - -## Creating Gutenberg Blocks - -### Block Anatomy - -Every form field block consists of: -1. **block.json** - Metadata and attributes schema -2. **edit.js** - Editor component (React) -3. **save.js** - Frontend rendering (usually null, PHP renders) -4. **style.scss** - Block-specific styles -5. **PHP class** - Server-side registration and rendering - -### Step-by-Step: Create a New Block - -#### Step 1: Create Block Directory - -```bash -mkdir -p src/blocks/custom-field -cd src/blocks/custom-field -``` - -#### Step 2: Create block.json - -**File:** [src/blocks/custom-field/block.json](../../src/blocks/custom-field/block.json) - -```json -{ - "$schema": "https://schemas.wp.org/trunk/block.json", - "apiVersion": 2, - "name": "sureforms/custom-field", - "title": "Custom Field", - "category": "sureforms", - "icon": "text", - "description": "A custom form field", - "keywords": ["form", "custom", "field"], - "supports": { - "html": false, - "anchor": false, - "customClassName": false - }, - "attributes": { - "label": { - "type": "string", - "default": "Custom Field" - }, - "slug": { - "type": "string", - "default": "custom_field" - }, - "placeholder": { - "type": "string", - "default": "" - }, - "required": { - "type": "boolean", - "default": false - }, - "helpText": { - "type": "string", - "default": "" - } - }, - "editorScript": "file:./index.js", - "editorStyle": "file:./editor.scss", - "style": "file:./style.scss" -} -``` - -#### Step 3: Create edit.js (Editor Component) - -**File:** [src/blocks/custom-field/edit.js](../../src/blocks/custom-field/edit.js) - -```javascript -import { __ } from '@wordpress/i18n'; -import { InspectorControls, useBlockProps } from '@wordpress/block-editor'; -import { PanelBody, TextControl, ToggleControl, TextareaControl } from '@wordpress/components'; - -export default function Edit({ attributes, setAttributes, clientId }) { - const { label, slug, placeholder, required, helpText } = attributes; - - const blockProps = useBlockProps({ - className: 'srfm-block srfm-custom-field-block', - }); - - return ( - <> - {/* Inspector Panel (Right Sidebar) */} - - - setAttributes({ label: value })} - help={__('Field label shown to users', 'sureforms')} - /> - - setAttributes({ slug: value })} - help={__('Unique identifier for this field', 'sureforms')} - /> - - setAttributes({ placeholder: value })} - /> - - setAttributes({ required: value })} - /> - - setAttributes({ helpText: value })} - help={__('Additional instructions for users', 'sureforms')} - /> - - - - {/* Block Preview in Editor */} -
-
- - - - - {helpText && ( - - {helpText} - - )} -
-
- - ); -} -``` - -#### Step 4: Create save.js - -**File:** [src/blocks/custom-field/save.js](../../src/blocks/custom-field/save.js) - -```javascript -/** - * Save function - return null for dynamic blocks (rendered server-side). - * - * SureForms blocks are rendered server-side via PHP for: - * - Better security (no client-side data exposure) - * - Consistent rendering across contexts - * - Easier form submission handling - */ -export default function save() { - return null; -} -``` - -#### Step 5: Create index.js (Registration) - -**File:** [src/blocks/custom-field/index.js](../../src/blocks/custom-field/index.js) - -```javascript -import { registerBlockType } from '@wordpress/blocks'; -import Edit from './edit'; -import save from './save'; -import metadata from './block.json'; - -// Register block -registerBlockType(metadata.name, { - ...metadata, - edit: Edit, - save, -}); -``` - -#### Step 6: Add to blocks.js - -**File:** [src/blocks/blocks.js](../../src/blocks/blocks.js) - -```javascript -// ... other imports -import './custom-field'; -``` - -#### Step 7: Create PHP Server-Side Rendering - -**File:** [inc/blocks/custom-field/class-custom-field.php](../../inc/blocks/custom-field/class-custom-field.php) - -```php - -
- - - - - /> - - - - - - -
- { - setValue(e.target.value); - - // Validate - if (e.target.value.length < 3) { - setError('Minimum 3 characters'); - } else { - setError(''); - } - }; - - return ( -
- - {error && {error}} -
- ); -} -``` - -### 2. WordPress Data Store (Redux-based) - -For block editor state and form metadata. - -**Define Store** ([src/store/store.js](../../src/store/store.js)): - -```javascript -import { createReduxStore, register } from '@wordpress/data'; -import apiFetch from '@wordpress/api-fetch'; - -const DEFAULT_STATE = { - formSettings: {}, - blockAttributes: {}, - isLoading: false, -}; - -const actions = { - setFormSettings(settings) { - return { - type: 'SET_FORM_SETTINGS', - settings, - }; - }, - - updateBlockAttribute(blockId, attribute, value) { - return { - type: 'UPDATE_BLOCK_ATTRIBUTE', - blockId, - attribute, - value, - }; - }, - - *fetchFormSettings(formId) { - yield { type: 'SET_LOADING', isLoading: true }; - - try { - const settings = yield apiFetch({ - path: `/sureforms/v1/forms/${formId}/settings`, - }); - - return actions.setFormSettings(settings); - } catch (error) { - console.error('Failed to fetch settings:', error); - return { type: 'FETCH_ERROR', error }; - } - }, -}; - -const selectors = { - getFormSettings(state) { - return state.formSettings; - }, - - getBlockAttribute(state, blockId, attribute) { - return state.blockAttributes[blockId]?.[attribute]; - }, - - isLoading(state) { - return state.isLoading; - }, -}; - -const reducer = (state = DEFAULT_STATE, action) => { - switch (action.type) { - case 'SET_FORM_SETTINGS': - return { - ...state, - formSettings: action.settings, - isLoading: false, - }; - - case 'UPDATE_BLOCK_ATTRIBUTE': - return { - ...state, - blockAttributes: { - ...state.blockAttributes, - [action.blockId]: { - ...state.blockAttributes[action.blockId], - [action.attribute]: action.value, - }, - }, - }; - - case 'SET_LOADING': - return { - ...state, - isLoading: action.isLoading, - }; - - default: - return state; - } -}; - -export const store = createReduxStore('srfm/forms', { - reducer, - actions, - selectors, -}); - -register(store); -``` - -**Use Store in Components:** - -```javascript -import { useSelect, useDispatch } from '@wordpress/data'; - -function FormEditor({ formId }) { - // Select data from store - const { formSettings, isLoading } = useSelect((select) => ({ - formSettings: select('srfm/forms').getFormSettings(), - isLoading: select('srfm/forms').isLoading(), - })); - - // Dispatch actions to store - const { fetchFormSettings, setFormSettings } = useDispatch('srfm/forms'); - - useEffect(() => { - fetchFormSettings(formId); - }, [formId]); - - if (isLoading) { - return ; - } - - return ( -
-

{formSettings.title}

- {/* Editor UI */} -
- ); -} -``` - -### 3. React Query (Server State) - -For API responses and caching. - -**Setup Query Client** ([src/admin/dashboard/index.js](../../src/admin/dashboard/index.js)): - -```javascript -import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; - -const queryClient = new QueryClient({ - defaultOptions: { - queries: { - staleTime: 5 * 60 * 1000, // 5 minutes - retry: 1, - }, - }, -}); - -function App() { - return ( - - - - ); -} -``` - -**Create Custom Hooks** ([src/hooks/useFormData.js](../../src/hooks/)): - -```javascript -import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; -import apiFetch from '@wordpress/api-fetch'; - -// Fetch form data -export function useFormData(formId) { - return useQuery({ - queryKey: ['form', formId], - queryFn: async () => { - const response = await apiFetch({ - path: `/sureforms/v1/forms/${formId}`, - }); - return response; - }, - enabled: !!formId, - }); -} - -// Update form data -export function useUpdateForm() { - const queryClient = useQueryClient(); - - return useMutation({ - mutationFn: async ({ formId, data }) => { - return await apiFetch({ - path: `/sureforms/v1/forms/${formId}`, - method: 'PUT', - data, - }); - }, - onSuccess: (data, variables) => { - // Invalidate and refetch - queryClient.invalidateQueries(['form', variables.formId]); - }, - }); -} - -// Fetch entries -export function useEntries(formId, page = 1) { - return useQuery({ - queryKey: ['entries', formId, page], - queryFn: async () => { - return await apiFetch({ - path: `/sureforms/v1/forms/${formId}/entries?page=${page}`, - }); - }, - keepPreviousData: true, // For pagination - }); -} -``` - -**Use in Components:** - -```javascript -function FormEditor({ formId }) { - const { data: form, isLoading, error } = useFormData(formId); - const updateForm = useUpdateForm(); - - const handleSave = async () => { - try { - await updateForm.mutateAsync({ - formId, - data: { title: 'Updated Title' }, - }); - // Success toast - toast.success('Form saved!'); - } catch (error) { - // Error toast - toast.error('Failed to save form'); - } - }; - - if (isLoading) return ; - if (error) return
Error: {error.message}
; - - return ( -
-

{form.title}

- -
- ); -} -``` - ---- - -## Component Patterns - -### Functional Components with Hooks - -**Always use functional components** (not class components): - -```javascript -// โœ… GOOD - Functional component -function MyComponent({ prop1, prop2 }) { - const [state, setState] = useState(null); - - useEffect(() => { - // Side effects - }, []); - - return
{/* JSX */}
; -} - -// โŒ BAD - Class component (deprecated pattern) -class MyComponent extends React.Component { - // Don't use class components in SureForms -} -``` - -### Props Destructuring - -```javascript -// โœ… GOOD - Destructure in signature -function Button({ label, onClick, disabled = false, variant = 'primary' }) { - return ( - - ); -} - -// โŒ BAD - Access via props object -function Button(props) { - return ; -} -``` - -### Conditional Rendering - -```javascript -function FormField({ label, required, error }) { - return ( -
- - - {/* Ternary for if/else */} - {error ? ( - {error} - ) : ( - Optional - )} - - {/* Conditional with && */} - {!error && Valid} -
- ); -} -``` - -### Event Handlers - -```javascript -function FormContainer() { - // useCallback for stable reference - const handleSubmit = useCallback((event) => { - event.preventDefault(); - // Handle submit - }, []); - - // Arrow function for inline with parameters - const handleFieldChange = useCallback((fieldId, value) => { - setFormData((prev) => ({ - ...prev, - [fieldId]: value, - })); - }, []); - - return ( -
- handleFieldChange('name', e.target.value)} - /> -
- ); -} -``` - ---- - -## Styling - -### TailwindCSS (Preferred) - -Use Tailwind utility classes for rapid development: - -```javascript -function Card({ title, children }) { - return ( -
-

- {title} -

-
- {children} -
-
- ); -} -``` - -**Responsive Design:** - -```javascript -
- {/* Full width mobile, half on tablet, third on desktop */} -
- -
- {/* Responsive text size */} -
-``` - -### Custom SCSS (When Needed) - -**Use BEM methodology** with `.srfm-` prefix: - -```scss -// style.scss -.srfm-custom-field { - // Block - &__label { - // Element - @apply block text-sm font-medium text-gray-700 mb-2; - - .required { - // Nested element - @apply text-red-500 ml-1; - } - } - - &__input { - // Element - @apply w-full px-4 py-2 border border-gray-300 rounded-md; - @apply focus:outline-none focus:ring-2 focus:ring-blue-500; - - &:disabled { - // Modifier via pseudo-class - @apply bg-gray-100 cursor-not-allowed; - } - } - - &--error { - // Block modifier - .srfm-custom-field__input { - @apply border-red-500; - } - } -} -``` - -### Conditional Classes (classnames) - -```javascript -import classnames from 'classnames'; - -function Button({ variant, size, disabled, className }) { - const classes = classnames( - 'srfm-button', - `srfm-button--${variant}`, - `srfm-button--${size}`, - { - 'srfm-button--disabled': disabled, - }, - className // Allow override - ); - - return ; -} -``` - ---- - -## Form Validation - -### Client-Side Validation (Frontend) - -**Inline validation:** - -```javascript -import { useState } from 'react'; - -function EmailField({ value, onChange, required }) { - const [error, setError] = useState(''); - - const validateEmail = (email) => { - const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; - return regex.test(email); - }; - - const handleBlur = () => { - if (required && !value) { - setError(__('Email is required', 'sureforms')); - } else if (value && !validateEmail(value)) { - setError(__('Please enter a valid email', 'sureforms')); - } else { - setError(''); - } - }; - - return ( -
- - {error && {error}} -
- ); -} -``` - -**Form-level validation:** - -```javascript -function FormContainer() { - const [formData, setFormData] = useState({}); - const [errors, setErrors] = useState({}); - - const validate = () => { - const newErrors = {}; - - if (!formData.name) { - newErrors.name = 'Name is required'; - } - - if (!formData.email || !isValidEmail(formData.email)) { - newErrors.email = 'Valid email is required'; - } - - if (formData.age && formData.age < 18) { - newErrors.age = 'Must be 18 or older'; - } - - setErrors(newErrors); - return Object.keys(newErrors).length === 0; - }; - - const handleSubmit = async (e) => { - e.preventDefault(); - - if (!validate()) { - return; - } - - // Submit form - try { - await submitForm(formData); - toast.success('Form submitted!'); - } catch (error) { - toast.error('Submission failed'); - } - }; - - return ( -
- {/* Form fields */} - -
- ); -} -``` - ---- - -## Internationalization (i18n) - -### Translation Functions - -```javascript -import { __, _n, sprintf } from '@wordpress/i18n'; - -// Simple translation -const label = __('Submit Form', 'sureforms'); - -// Plural forms -const message = _n( - 'One field is required', - '%d fields are required', - count, - 'sureforms' -); - -// String interpolation -const greeting = sprintf( - __('Hello, %s!', 'sureforms'), - userName -); -``` - -### Best Practices - -**โœ… DO:** -```javascript -// Use sprintf for variables -const msg = sprintf(__('Form %s saved', 'sureforms'), formName); - -// Separate strings for different contexts -const saveButton = __('Save', 'sureforms'); -const saveForm = __('Save Form', 'sureforms'); -``` - -**โŒ DON'T:** -```javascript -// Never use template literals in translations -const msg = __(`Form ${formName} saved`, 'sureforms'); // โŒ WRONG - -// Never concatenate -const msg = __('Form ', 'sureforms') + formName + __(' saved', 'sureforms'); // โŒ WRONG -``` - ---- - -## Performance Optimization - -### Code Splitting - -```javascript -import { lazy, Suspense } from 'react'; - -const HeavyComponent = lazy(() => import('./HeavyComponent')); - -function App() { - return ( - }> - - - ); -} -``` - -### Memoization - -```javascript -import { useMemo, useCallback } from 'react'; - -function DataTable({ data, onRowClick }) { - // Memoize expensive calculations - const sortedData = useMemo(() => { - console.log('Sorting data...'); - return data.sort((a, b) => a.name.localeCompare(b.name)); - }, [data]); // Only recompute when data changes - - // Memoize callbacks - const handleRowClick = useCallback( - (row) => { - onRowClick(row); - }, - [onRowClick] - ); - - return {/* Render sortedData */}
; -} -``` - -### React.memo - -```javascript -import { memo } from 'react'; - -// Prevent re-renders if props haven't changed -const ExpensiveComponent = memo(function ExpensiveComponent({ data }) { - console.log('Rendering...'); - return
{/* Complex rendering */}
; -}); -``` - ---- - -## Testing - -### Component Testing (Jest + React Testing Library) - -```javascript -import { render, screen, fireEvent } from '@testing-library/react'; -import '@testing-library/jest-dom'; -import FormField from '../FormField'; - -describe('FormField', () => { - it('renders with label', () => { - render(); - expect(screen.getByText('Name')).toBeInTheDocument(); - }); - - it('shows required indicator', () => { - render(); - expect(screen.getByText('*')).toBeInTheDocument(); - }); - - it('calls onChange when value changes', () => { - const handleChange = jest.fn(); - render(); - - const input = screen.getByRole('textbox'); - fireEvent.change(input, { target: { value: 'test' } }); - - expect(handleChange).toHaveBeenCalledWith('test'); - }); - - it('displays error message', () => { - render(); - expect(screen.getByText('This field is required')).toBeInTheDocument(); - }); -}); -``` - ---- - -## Summary - -**Key Takeaways:** - -1. **Use React 18 functional components** with hooks -2. **Gutenberg blocks** are registered in JavaScript, rendered in PHP -3. **State management** uses three layers: local, WordPress Data Store, React Query -4. **Styling** prefers TailwindCSS utilities, custom SCSS for complex needs -5. **Validation** happens client-side (UX) and server-side (security) -6. **i18n** uses `@wordpress/i18n` functions, no template literals -7. **Performance** optimized with memoization, code splitting, virtualization - ---- - -**Related Documentation:** -- [CLAUDE.md](../../CLAUDE.md) - AI agent guide -- [GETTING-STARTED.md](../01-getting-started/GETTING-STARTED.md) - Setup -- [CODING-STANDARDS.md](../03-development/CODING-STANDARDS.md) - Code style -- [TESTING.md](../08-testing/TESTING.md) - Testing guide diff --git a/docs/wiki/AI-Form-Builder.md b/docs/wiki/AI-Form-Builder.md deleted file mode 100644 index a35a46a4e..000000000 --- a/docs/wiki/AI-Form-Builder.md +++ /dev/null @@ -1,103 +0,0 @@ -# AI Form Builder - -SureForms includes an AI-powered form generator that creates complete forms from natural language descriptions. - -## Architecture - -``` -inc/ai-form-builder/ -|-- ai-form-builder.php # Main AI builder class -|-- ai-auth.php # Authentication and billing -|-- ai-helper.php # AI utility functions -|-- field-mapping.php # Maps AI response to Gutenberg blocks -``` - -## Authentication Flow - -The `AI_Auth` class handles authentication with the SureForms middleware API: - -1. User initiates authentication from admin settings -2. `GET /initiate-auth` REST endpoint generates an auth URL -3. User is redirected to the billing portal (`SRFM_BILLING_PORTAL`) -4. After authentication, an encrypted access key is returned -5. `POST /handle-access-key` decrypts and stores the key in WordPress options -6. Subsequent AI requests use this key for authorization - -### Constants - -| Constant | URL | Purpose | -|----------|-----|---------| -| `SRFM_AI_MIDDLEWARE` | `https://credits.startertemplates.com/sureforms/` | AI credits API | -| `SRFM_MIDDLEWARE_BASE_URL` | `https://api.sureforms.com/` | API middleware | -| `SRFM_BILLING_PORTAL` | `https://billing.sureforms.com/` | Billing portal | - -## Form Generation Process - -### Step 1: User Input - -The user provides a natural language description of the form they want (e.g., "Create a contact form with name, email, phone, and message fields"). - -### Step 2: AI Generation - -`POST /generate-form` sends the description to the AI middleware: - -``` -User prompt -> REST API -> AI_Form_Builder::generate_ai_form() - -> External AI middleware API call - -> AI generates form structure as JSON - -> Returns field definitions -``` - -### Step 3: Field Mapping - -`POST /map-fields` converts the AI response to SureForms Gutenberg blocks: - -``` -AI JSON response -> Field_Mapping::generate_gutenberg_fields_from_questions() - -> Maps each AI field to a SureForms block type - -> Generates block attributes - -> Creates Gutenberg block markup - -> Returns blocks ready for the editor -``` - -### Field Type Mapping - -The `Field_Mapping` class maps AI-suggested field types to SureForms blocks: - -| AI Field Type | SureForms Block | -|---------------|----------------| -| text / name | `srfm/input` | -| email | `srfm/email` | -| phone / tel | `srfm/phone` | -| textarea / message | `srfm/textarea` | -| number | `srfm/number` | -| url / website | `srfm/url` | -| select / dropdown | `srfm/dropdown` | -| checkbox | `srfm/checkbox` | -| radio / multiple choice | `srfm/multichoice` | -| address | `srfm/address` | - -## REST API Endpoints - -| Method | Endpoint | Handler | Description | -|--------|----------|---------|-------------| -| POST | `/generate-form` | `AI_Form_Builder::generate_ai_form` | Send prompt to AI, get form structure | -| POST | `/map-fields` | `Field_Mapping::generate_gutenberg_fields_from_questions` | Convert AI fields to blocks | -| GET | `/initiate-auth` | `AI_Auth::get_auth_url` | Get billing portal auth URL | -| POST | `/handle-access-key` | `AI_Auth::handle_access_key` | Save decrypted access key | - -All endpoints require `manage_options` capability. - -## AI Helper - -The `AI_Helper` class provides utility functions for: -- API key management -- Credit balance checking -- Request formatting -- Error handling for AI middleware responses - -## Related Pages - -- [REST API Reference](REST-API-Reference) -- All API endpoints -- [Gutenberg Blocks](Gutenberg-Blocks) -- Block types the AI maps to -- [Architecture Overview](Architecture-Overview) -- AI classes in bootstrap flow diff --git a/docs/wiki/Admin-Dashboard.md b/docs/wiki/Admin-Dashboard.md deleted file mode 100644 index 9c16aea85..000000000 --- a/docs/wiki/Admin-Dashboard.md +++ /dev/null @@ -1,121 +0,0 @@ -# Admin Dashboard - -The SureForms admin dashboard is a React single-page application (SPA) integrated into the WordPress admin area. - -## Architecture - -### Entry Point - -The admin React app is bootstrapped in `src/admin/editor-scripts.js`, which serves as the Webpack entry point. It mounts the React app to a DOM container registered by the PHP `Admin` class. - -### Tech Stack - -| Technology | Purpose | -|------------|---------| -| React 18 | UI rendering | -| react-router-dom 6 | Client-side routing | -| @tanstack/react-query 5 | Server state management and data fetching | -| @wordpress/api-fetch | REST API client with nonce handling | -| @wordpress/data | WordPress data store integration | -| @bsf/force-ui | BSF component library (buttons, modals, inputs, etc.) | -| Tailwind CSS 3 | Utility-first styling | -| react-hot-toast | Toast notifications | - -### Admin Pages - -The React app includes the following pages/routes: - -| Route | Component | Description | -|-------|-----------|-------------| -| Dashboard | `src/admin/dashboard/` | Overview with charts and stats | -| Forms | `src/admin/forms/` | Forms listing with search, filter, bulk actions | -| Entries | `src/admin/entries/` | Entry listing and management | -| Settings | `src/admin/settings/` | Global plugin settings | -| Payments | `src/admin/payment/` | Payment transactions listing | -| Single Form Settings | `src/admin/single-form-settings/` | Per-form configuration | - -### Shared Components - -Common admin components are in `src/admin/components/`: - -- `PageHeader` -- Consistent page header with title and actions -- `TemplatePicker` -- Form template selection UI -- Loading skeletons (via `react-loading-skeleton`) -- Modal dialogs and confirmation prompts - -## WordPress Integration - -### Menu Registration - -The PHP `Admin` class (`admin/admin.php`) registers the WordPress admin menu: - -```php -add_menu_page( - 'SureForms', - 'SureForms', - 'manage_options', - 'sureforms_menu', - [ $this, 'render_admin_page' ], - 'dashicons-feedback', - 30 -); -``` - -### Asset Enqueuing - -Admin assets are enqueued only on SureForms admin pages: - -- React app bundle (from `assets/build/`) -- Tailwind CSS styles -- Localized data via `wp_localize_script()` providing: - - REST API URL and nonce - - Current user data - - Plugin settings - - Form data - -## Data Fetching - -### @tanstack/react-query - -Used for server state management with automatic caching, refetching, and invalidation: - -```javascript -const { data, isLoading } = useQuery({ - queryKey: ['entries', filters], - queryFn: () => apiFetch({ path: '/sureforms/v1/entries/list', ... }), -}); -``` - -### @wordpress/api-fetch - -WordPress API client with automatic nonce injection: - -```javascript -import apiFetch from '@wordpress/api-fetch'; - -apiFetch({ path: '/sureforms/v1/form-data' }) - .then(data => { /* handle response */ }); -``` - -## Force UI Component Library - -`@bsf/force-ui` is BSF's internal component library providing: - -- Buttons, inputs, selects, toggles -- Modals and dialogs -- Tables and data display -- Navigation components -- Consistent design system - -Components are imported directly: - -```javascript -import { Button, Modal, Input } from '@bsf/force-ui'; -``` - -## Related Pages - -- [State Management](State-Management) -- WordPress data store -- [Frontend Assets](Frontend-Assets) -- Asset loading pipeline -- [REST API Reference](REST-API-Reference) -- API endpoints used by dashboard -- [Environment Configuration](Environment-Configuration) -- Build setup diff --git a/docs/wiki/Architecture-Overview.md b/docs/wiki/Architecture-Overview.md deleted file mode 100644 index 523f18cc8..000000000 --- a/docs/wiki/Architecture-Overview.md +++ /dev/null @@ -1,294 +0,0 @@ -# Architecture Overview - -This page describes the high-level architecture of the SureForms WordPress plugin (v2.5.1), covering the bootstrap flow, namespace conventions, directory layout, design patterns, and data flow. - -## High-Level Architecture Diagram - -``` -+------------------------------------------------------+ -| WordPress Core | -| (hooks: plugins_loaded, init, rest_api_init, etc.) | -+---------------------------+--------------------------+ - | - +--------v---------+ - | sureforms.php | - | (entry point, | - | constants) | - +--------+---------+ - | - +--------v---------+ - | plugin-loader.php| - | (Plugin_Loader) | - | - autoloader | - | - hook setup | - | - class init | - +--------+---------+ - | - +------------------+------------------+ - | | | - plugins_loaded(99) init admin_init - load_plugin() load_classes() activation_redirect() - | | - +------v------+ +------v------+ - | Core Classes| | Admin/Block | - | Post_Types | | Register | - | Form_Submit | | Admin | - | Rest_Api | | Payments | - | Helper | | Duplicate | - | ...20+ more | +-------------+ - +------+------+ - | - +------v------+ +-------------+ +-------------+ - | Database | | REST API | | Frontend | - | Register | | /sureforms/ | | Assets | - | Entries tbl | | v1/... | | Form Markup | - | Payments tbl| +-------------+ +-------------+ - +-------------+ -``` - -## Plugin Bootstrap Flow - -### 1. Entry Point: sureforms.php - -The main plugin file defines all global constants and then requires `plugin-loader.php`: - -```php -define( 'SRFM_FILE', __FILE__ ); -define( 'SRFM_DIR', plugin_dir_path( SRFM_FILE ) ); -define( 'SRFM_URL', plugins_url( '/', SRFM_FILE ) ); -define( 'SRFM_VER', '2.5.1' ); -define( 'SRFM_FORMS_POST_TYPE', 'sureforms_form' ); -define( 'SRFM_ENTRIES', 'sureforms_entries' ); -define( 'SRFM_PAYMENTS', 'sureforms_payments' ); -require_once 'plugin-loader.php'; -``` - -### 2. Plugin Loader: plugin-loader.php - -The `SRFM\Plugin_Loader` class is the central bootstrap orchestrator: - -1. Loads the Action Scheduler library from `inc/lib/action-scheduler/action-scheduler.php` -2. Registers the PSR-4-style autoloader via `spl_autoload_register()` -3. Hooks into WordPress lifecycle events: - - `plugins_loaded` (default priority) -- `load_textdomain()` - - `plugins_loaded` (priority 99) -- `load_plugin()` (main class initialization) - - `init` -- `load_classes()` (block registration, admin, payments) - - `admin_init` -- `activation_redirect()` -4. Instantiates `Analytics` singleton immediately -5. Registers activation hook (`Activator::activate()`) -6. Registers deactivation hook (clears scheduled events) - -The `Plugin_Loader` fires the `srfm_core_loaded` action after first instantiation. - -### 3. Class Initialization Order - -**On `plugins_loaded` (priority 99) via `load_plugin()`:** - -| Order | Class | Responsibility | -|-------|-------|---------------| -| 1 | `Post_Types` | Registers `sureforms_form` CPT and all post meta | -| 2 | `Form_Submit` | Registers `/submit-form` and `/refresh-nonces` REST endpoints | -| 3 | `Gutenberg_Hooks` | Block editor integration hooks | -| 4 | `Frontend_Assets` | Frontend CSS/JS enqueue | -| 5 | `Helper` | Utility/helper functions | -| 6 | `Activator` | First-run setup and migrations | -| 7 | `Admin_Ajax` | WordPress AJAX handlers | -| 8 | `Forms_Data` | Form data queries and listing | -| 9 | `Export` | Import/export functionality | -| 10 | `Smart_Tags` | Template tag processing | -| 11 | `Generate_Form_Markup` | Form HTML rendering | -| 12 | `Create_New_Form` | New form creation flow with default meta | -| 13 | `Global_Settings` | Plugin-wide settings management | -| 14 | `Email_Summary` | Scheduled email digest reports | -| 15 | `Compliance_Settings` | GDPR/privacy per-form settings | -| 16 | `Events_Scheduler` | Cron-based scheduled events | -| 17 | `AI_Form_Builder` | AI-powered form generation | -| 18 | `Field_Mapping` | AI response to Gutenberg block mapping | -| 19 | `Background_Process` | Background task processing via Action Scheduler | -| 20 | `Page_Builders` | Third-party page builder integrations | -| 21 | `Rest_Api` | Admin REST endpoint registration (20+ routes) | -| 22 | `AI_Helper` | AI utility functions | -| 23 | `AI_Auth` | AI authentication and billing portal | -| 24 | `Updater` | Plugin update logic | -| 25 | `Onboarding` | First-run onboarding wizard | -| 26 | `DatabaseRegister` | Custom table creation/migration | -| 27 | `Form_Restriction` | Submission limits, scheduling, and entry caps | -| 28 | `Astra` | Astra theme compatibility layer | - -**On `init` via `load_classes()`:** - -| Class | Condition | Responsibility | -|-------|-----------|---------------| -| `Blocks\Register` | Always | Gutenberg block type registration | -| `Admin` | `is_admin()` only | Admin menu pages, assets, and screens | -| `Notice_Manager` | `is_admin()` only | Admin notice display and management | -| `Payments` | Always | Payment gateway setup (Stripe) | -| `Duplicate_Form` | Always | Form duplication handler | - -## Namespace and Autoloading - -### Namespace Structure - -The root namespace is `SRFM`. All classes follow `SRFM\{directory}\{ClassName}`: - -``` -SRFM\ -> plugin-loader.php -SRFM\Inc\Helper -> inc/helper.php -SRFM\Inc\Rest_Api -> inc/rest-api.php -SRFM\Inc\Form_Submit -> inc/form-submit.php -SRFM\Inc\Database\Base -> inc/database/base.php -SRFM\Inc\Database\Tables\Entries -> inc/database/tables/entries.php -SRFM\Inc\AI_Form_Builder\* -> inc/ai-form-builder/ -SRFM\Inc\Traits\Get_Instance -> inc/traits/get-instance.php -SRFM\Admin\Admin -> admin/admin.php -``` - -### Autoloader Logic - -The autoloader in `Plugin_Loader::autoload()`: - -1. Strips the root `SRFM\` namespace prefix -2. Converts `CamelCase` to `kebab-case` -3. Replaces underscores with hyphens -4. Replaces namespace separators with directory separators -5. Converts to lowercase, prepends `SRFM_DIR`, appends `.php` -6. Rejects any path containing `..` (directory traversal protection) - -## Directory Layout - -``` -sureforms/ -|-- sureforms.php # Plugin entry point, all SRFM_* constants -|-- plugin-loader.php # Autoloader, bootstrap, hook registration -|-- inc/ # Core PHP classes (SRFM\Inc namespace) -| |-- helper.php # Static utility methods -| |-- rest-api.php # REST API endpoint registration -| |-- form-submit.php # Public form submission handler -| |-- post-types.php # sureforms_form CPT and post meta -| |-- entries.php # Entry CRUD operations -| |-- blocks/ # Gutenberg block server-side rendering -| |-- database/ # Custom DB table management -| |-- fields/ # Form field type definitions and validation -| |-- payments/ # Payment gateway integrations (Stripe) -| |-- email/ # Email template rendering -| |-- ai-form-builder/ # AI-powered form generation -| |-- global-settings/ # Plugin-wide settings -| |-- single-form-settings/ # Per-form configuration -| |-- compatibility/ # Theme/plugin compatibility -| |-- page-builders/ # Page builder integrations -| |-- traits/ # Shared PHP traits (Get_Instance) -| |-- lib/ # Bundled third-party libraries (do not modify) -|-- src/ # JS/React source (compiled by wp-scripts) -| |-- admin/ # Admin dashboard React app -| |-- blocks/ # Gutenberg block editor components -| |-- components/ # Shared React components -| |-- store/ # WordPress @wordpress/data store -| |-- utils/ # JS utilities -|-- modules/ # Feature modules (Gutenberg, Quick Action Sidebar) -|-- admin/ # Admin PHP classes and assets -|-- sass/ # SASS source files (compiled to assets/css/) -|-- assets/ # Compiled and static assets -|-- templates/ # PHP templates (BladeOne engine) -|-- tests/ # PHPUnit, Playwright, and Docker setup -``` - -## Design Patterns - -### Singleton via Get_Instance Trait - -Nearly every class uses the `Get_Instance` trait from `inc/traits/get-instance.php`: - -```php -trait Get_Instance { - private static $instance = null; - public static function get_instance() { - if ( null === self::$instance ) { - self::$instance = new self(); - } - return self::$instance; - } -} -``` - -### Abstract Base Class (Database) - -The database layer uses `SRFM\Inc\Database\Base` providing: - -- Table creation via `dbDelta()` -- Schema versioning with integer versions stored in options -- Column migration (`maybe_add_new_columns()`, `maybe_rename_columns()`) -- CRUD wrappers (`use_insert()`, `use_update()`, `use_delete()`) -- Query builder with parameterized WHERE supporting `=`, `!=`, `>`, `<`, `LIKE`, `IN` -- In-memory result caching keyed by MD5 of SQL query -- Schema-driven JSON encoding/decoding for array columns - -### Hook-Based Initialization - -Classes register WordPress hooks in their constructors, invoked during singleton instantiation in `load_plugin()` or `load_classes()`. - -### Filter-Driven Extensibility - -| Filter | Purpose | -|--------|---------| -| `srfm_rest_api_endpoints` | Extend REST API routes | -| `srfm_register_post_meta` | Register additional form post meta | -| `srfm_form_submit_data` | Modify form data before processing | -| `srfm_entry_value` | Transform entry field values | -| `srfm_is_special_block` | Declare custom blocks as special | -| `srfm_handle_special_block` | Custom processing for special blocks | -| `srfm_form_confirmation_params` | Extend form confirmation settings | -| `srfm_normalize_csv_field_value` | Custom CSV export formatting | - -## Data Flow - -``` -1. FORM CREATION - Admin creates form in Gutenberg block editor - -> Saved as sureforms_form CPT (wp_posts) - -> Settings stored as post meta (_srfm_* keys) - -> Block content in post_content column - -2. FORM DISPLAY - Form embedded via shortcode, Gutenberg block, or Instant Form URL - -> Generate_Form_Markup::get_form_markup() renders HTML - -> Frontend_Assets enqueues CSS/JS - -> Submission nonce generated - -3. FORM SUBMISSION - User submits via JavaScript fetch() - -> POST /wp-json/sureforms/v1/submit-form - -> Nonce verification, field validation - -> CAPTCHA validation (reCAPTCHA, hCaptcha, Turnstile) - -> Honeypot spam check - -4. ENTRY STORAGE - -> JSON-encoded form data inserted into wp_srfm_entries - -> Email notifications sent - -> Payment processed if applicable (wp_srfm_payments) - -> Confirmation response returned - -5. POST-SUBMISSION - -> srfm_form_submit and srfm_after_submission_process actions fired -``` - -## Key Constants - -| Constant | Value | Purpose | -|----------|-------|---------| -| `SRFM_FILE` | `__FILE__` | Main plugin file path | -| `SRFM_DIR` | Plugin dir path | File system operations | -| `SRFM_URL` | Plugin URL | Asset URL generation | -| `SRFM_VER` | `2.5.1` | Version for cache busting | -| `SRFM_SLUG` | `srfm` | Short identifier slug | -| `SRFM_FORMS_POST_TYPE` | `sureforms_form` | Custom post type slug | -| `SRFM_ENTRIES` | `sureforms_entries` | Entries identifier | -| `SRFM_PAYMENTS` | `sureforms_payments` | Payments identifier | -| `SRFM_PRO_RECOMMENDED_VER` | `2.5.1` | Minimum Pro version | - -## Related Pages - -- [Database Schema](Database-Schema) -- Custom tables, post types, and meta keys -- [Environment Configuration](Environment-Configuration) -- Development setup, build tools, and linting -- [REST API Reference](REST-API-Reference) -- Full endpoint documentation -- [Form Submission Flow](Form-Submission-Flow) -- Detailed submission pipeline -- [WordPress Hooks Reference](WordPress-Hooks-Reference) -- All actions and filters diff --git a/docs/wiki/Block-Editor-Controls.md b/docs/wiki/Block-Editor-Controls.md deleted file mode 100644 index 7d5cd1e33..000000000 --- a/docs/wiki/Block-Editor-Controls.md +++ /dev/null @@ -1,109 +0,0 @@ -# Block Editor Controls - -SureForms provides custom inspector controls and utilities for the Gutenberg block editor experience. - -## Directory Structure - -``` -src/srfm-controls/ -|-- addCommonData.js # Inject common data into blocks -|-- generateCSS.js # Dynamic CSS generation for blocks -|-- block-icons.js # Block icon definitions -|-- fonts.js # Font management utilities -|-- maybeGetColorForVariable.js # CSS variable color resolution -|-- parseIcon.js # SVG icon parser -|-- renderIcon.js # Icon rendering component - -src/blocks-attributes/ -|-- getMetakeys.js # Form meta key retrieval -|-- getFormId.js # Get current form ID -|-- getBlocksDefaultAttributes.js # Block attribute defaults -``` - -## CSS Generation System - -`generateCSS.js` dynamically generates CSS for block styling: - -- Converts block attributes to CSS properties -- Supports responsive breakpoints (desktop, tablet, mobile) -- Generates inline styles injected into the page -- Handles CSS variable references - -This system allows each block instance to have unique styling without class conflicts. - -## Block Icons - -`block-icons.js` provides SVG icon components for all SureForms blocks, used in: - -- Block inserter panel -- Block toolbar -- Block settings sidebar - -Additional icon sets from Spectra are available via `spectra-icons-v*.php` files. - -Icon utilities: -- `parseIcon.js` -- Parses SVG string into React-renderable format -- `renderIcon.js` -- React component for rendering parsed icons - -## Common Data Injection - -`addCommonData.js` injects shared data into block components: - -- Form-level settings accessible to all child blocks -- Common attributes and defaults -- Shared configuration values - -## Meta Key Integration - -`getMetakeys.js` retrieves form post meta keys for use in block controls: - -- Provides meta key names for form settings -- Used by inspector controls to read/write form meta -- Integrates with `@wordpress/data` store - -## Block Attribute Defaults - -`getBlocksDefaultAttributes.js` provides default attribute values for all block types: - -- Ensures consistent defaults across block instances -- Used during block registration -- Prevents undefined attribute errors - -## Form ID Resolution - -`getFormId.js` resolves the current form's post ID: - -- Used by blocks to identify their parent form -- Required for meta key operations -- Supports nested block contexts - -## Field Preview - -`src/blocks/FieldsPreview.jsx` renders a preview of form fields in the block editor: - -- Shows a visual representation of the field in editor mode -- Responds to attribute changes in real-time -- Handles edit vs preview states - -## Font Management - -`fonts.js` manages font loading for form styling: - -- Font family selection in block settings -- Google Fonts integration -- Font weight and style options - -## Color Variable Resolution - -`maybeGetColorForVariable.js` resolves WordPress CSS custom properties: - -- Maps color slugs to CSS variable references -- Supports theme color palette integration -- Falls back to raw color values when variables are not available - -## Related Pages - -- [Gutenberg Blocks](Gutenberg-Blocks) -- Block types and registration -- [State Management](State-Management) -- WordPress data store -- [Frontend Assets](Frontend-Assets) -- Editor asset loading -- [Form Fields Architecture](Form-Fields-Architecture) -- Field types diff --git a/docs/wiki/Changelog.md b/docs/wiki/Changelog.md deleted file mode 100644 index 058c89f45..000000000 --- a/docs/wiki/Changelog.md +++ /dev/null @@ -1,39 +0,0 @@ -# Changelog - -Recent changes to SureForms. For the full changelog, see [sureforms.com/whats-new](https://sureforms.com/whats-new/). - -## 2.5.1 - 16th February 2026 - -- **New:** Added option to change currency position (e.g., $100, 100$, $ 100, 100 $) -- **Fix:** Fixed the payment block amount not updating correctly with conditional logic - -## 2.5.0 - 2nd February 2026 - -- **Improvement:** Added translation support for the country list in the phone number field -- **Fix:** Fixed dropdown placeholder and GDPR label translation on the frontend - -## 2.4.0 - 20th January 2026 - -- **New:** Added form scheduling restrictions with start and end date/time -- **New:** Added Previous/Next navigation for single entry page -- **Improvement:** Improved multi-choice block settings UI -- **Improvement:** Updated Syria flag in the Phone field -- **Fix:** Fixed HTML block content corruption when duplicating forms -- **Fix:** Fixed multi-choice options being translated in entries -- **Fix:** Fixed reCAPTCHA v3 validation triggering multiple times on the same page -- **Fix:** Fixed Spectra button styles being affected by SureForms CSS - -## Version Bumping - -When preparing a release, update the version in: - -1. `sureforms.php` -- Plugin header `Version:` and `SRFM_VER` constant -2. `readme.txt` -- `Stable tag:` and changelog section -3. `package.json` -- `version` field - -See [Deployment Guide](Deployment-Guide) for the full release process. - -## Related Pages - -- [Deployment Guide](Deployment-Guide) -- Release workflow and CI/CD -- [Contributing Guide](Contributing-Guide) -- Development workflow diff --git a/docs/wiki/Contributing-Guide.md b/docs/wiki/Contributing-Guide.md deleted file mode 100644 index 74c97ae07..000000000 --- a/docs/wiki/Contributing-Guide.md +++ /dev/null @@ -1,205 +0,0 @@ -# Contributing Guide - -Thank you for your interest in contributing to SureForms! This guide covers the development workflow, coding standards, and submission process. - -## Prerequisites - -- **PHP** 7.4+ -- **Node.js** 18.15.0 (managed via [Volta](https://volta.sh/)) -- **Composer** for PHP dependencies -- **Git** for version control -- **Docker** (optional, for wp-env test environment) - -## Getting Started - -1. Fork the repository on GitHub -2. Clone your fork: - ```bash - git clone https://github.com/YOUR_USERNAME/sureforms.git - cd sureforms - ``` -3. Install dependencies: - ```bash - composer install - npm install - ``` -4. Create a feature branch from `next-release`: - ```bash - git checkout next-release - git pull origin next-release - git checkout -b feature/your-feature-name - ``` - -## Git Workflow - -``` -feature/branch --> next-release --> master --> tag/release - (development) (production) -``` - -- **Feature branches** are created from `next-release` -- **Pull requests** target `next-release` -- **Hotfixes** may target `master` directly -- **Release merges** go from `next-release` into `master` - -## Development Workflow - -### Running the Dev Server - -```bash -npm start # Start wp-scripts dev server (hot reload) -``` - -### Building - -```bash -npm run build # Full production build (JS + SASS + minify) -npm run build:script # Build JS only -npm run build:sass # Build SASS only -``` - -### Linting - -Run linters before submitting a PR: - -```bash -# JavaScript -npm run lint-js # ESLint check -npm run lint-js:fix # Auto-fix JS issues - -# CSS -npm run lint-css # Stylelint check -npm run lint-css:fix # Auto-fix CSS issues - -# Formatting -npm run pretty # Prettier check -npm run pretty:fix # Auto-format - -# PHP -vendor/bin/phpcs # PHP CodeSniffer (WPCS) -vendor/bin/phpcbf # Auto-fix PHPCS issues -``` - -### Testing - -All tests should pass before submitting a PR: - -```bash -# PHP unit tests -vendor/bin/phpunit - -# JavaScript unit tests -npm run test:unit - -# E2E tests (requires wp-env) -npm run play:up # Start environment -npm run play:run # Run Playwright tests -``` - -See [Testing Guide](Testing-Guide) for detailed test setup. - -## Coding Standards - -### PHP Standards - -SureForms follows **WordPress Coding Standards (WPCS)** enforced via `phpcs.xml`: - -- **Escaping**: Use `esc_html()`, `esc_attr()`, `esc_url()`, `wp_kses_post()` for all output -- **Nonces**: Use `wp_nonce_field()` / `check_ajax_referer()` for form submissions and AJAX -- **Capabilities**: Always check `current_user_can()` before privileged operations -- **Sanitization**: Use `sanitize_text_field()`, `absint()`, `wp_kses()` for all input -- **Prefixes**: `SRFM_` for constants, `srfm_` for function names and handles -- **Text domain**: `sureforms` for all translatable strings -- **PHP compatibility**: 7.4+ (enforced via `PHPCompatibilityWP`) - -### JavaScript Standards - -- Follow `@wordpress/scripts` ESLint configuration -- Use `@wordpress/data` store for state management -- Use `@wordpress/api-fetch` for REST API calls -- Import WordPress dependencies from `@wordpress/*` packages -- Use Force UI (`@bsf/force-ui`) components in admin dashboard pages - -### CSS Standards - -- **Admin dashboard**: Tailwind CSS 3.x utility classes -- **Block frontend**: SASS files in `sass/` directory -- **Class prefix**: `srfm-` for all frontend CSS classes -- Do not edit generated CSS in `assets/css/` -- edit SASS source files instead - -## Pull Request Process - -### PR Checklist - -Before submitting your PR, verify: - -- [ ] Code follows the coding standards (PHP, JS, CSS) -- [ ] All linters pass without errors -- [ ] Tests pass (PHPUnit, Jest) -- [ ] New features include tests -- [ ] Translatable strings use the `sureforms` text domain -- [ ] No debug code, `console.log`, or `var_dump` statements -- [ ] No secrets or credentials committed -- [ ] Build completes without errors (`npm run build`) - -### PR Title Format - -PR titles are validated by CI. Use a clear, descriptive title that summarizes the change. - -### CI Checks - -Pull requests automatically run: - -1. **PHPUnit** -- PHP unit tests -2. **PHPStan** -- Static analysis -3. **PHP Insights** -- Code quality -4. **PR Title Validation** -- Title format check -5. **E2E Tests** -- When the PR is labeled with `e2e` - -All checks must pass before merge. - -### Code Review - -- PRs require at least one approving review -- Address all review comments -- Keep PRs focused on a single feature or fix -- Large changes should be discussed in an issue first - -## Directory Guide for Contributors - -| Directory | Purpose | Edit? | -|-----------|---------|-------| -| `src/` | JS/React source code | Yes | -| `sass/` | SASS stylesheets | Yes | -| `inc/` | PHP classes and logic | Yes | -| `tests/` | Test files | Yes | -| `build/` | Compiled JS output | No (generated) | -| `assets/css/` | Compiled CSS output | No (generated) | -| `assets/js/minified/` | Minified JS | No (generated) | -| `inc/lib/` | Bundled third-party libraries | No | -| `node_modules/` | NPM packages | No | -| `vendor/` | Composer packages | No | - -## Adding a New Gutenberg Block - -See [Gutenberg Blocks](Gutenberg-Blocks) for the full guide on adding blocks, including: - -- Block registration (server-side and client-side) -- `block.json` schema -- Editor and frontend rendering - -## Adding a New REST Endpoint - -See [REST API Reference](REST-API-Reference) for endpoint patterns and the registration system. - -## Reporting Issues - -- Use [GitHub Issues](https://github.com/brainstormforce/sureforms/issues) for bug reports and feature requests -- Security vulnerabilities should be reported through the [Bug Bounty Program](https://brainstormforce.com/bug-bounty-program/) - -## Related Pages - -- [Environment Configuration](Environment-Configuration) -- Development setup details -- [Architecture Overview](Architecture-Overview) -- Codebase structure -- [Testing Guide](Testing-Guide) -- Test framework details -- [Deployment Guide](Deployment-Guide) -- Release process diff --git a/docs/wiki/Data-Export-Import.md b/docs/wiki/Data-Export-Import.md deleted file mode 100644 index fc07271ae..000000000 --- a/docs/wiki/Data-Export-Import.md +++ /dev/null @@ -1,120 +0,0 @@ -# Data Export & Import - -SureForms supports exporting and importing forms and entries for backup, migration, and data analysis. - -## Form Export - -### REST Endpoint - -`POST /wp-json/sureforms/v1/forms/export` - -**Parameters:** -- `form_ids` (required) -- Array of form IDs to export - -**Response:** JSON file containing form data including: -- Form post data (title, content, status) -- All form post meta (`_srfm_*` keys) -- Block content (Gutenberg blocks) - -### Export Format - -Forms are exported as a JSON structure containing all data needed to recreate the form on another site. - -## Form Import - -### REST Endpoint - -`POST /wp-json/sureforms/v1/forms/import` - -**Parameters:** -- File upload containing exported JSON data - -**Process:** -1. Validates the uploaded JSON structure -2. Creates new `sureforms_form` posts -3. Restores all post meta keys -4. Assigns new post IDs (no ID conflicts) -5. Returns count of imported forms - -## Form Duplication - -### REST Endpoint - -`POST /wp-json/sureforms/v1/forms/duplicate` - -**Parameters:** -- `form_id` (required) -- ID of the form to duplicate - -**Process:** - -Handled by `Duplicate_Form` class (`inc/duplicate-form.php`): - -1. Reads the original form post and all meta -2. Creates a new post with "(Copy)" appended to the title -3. Copies all `_srfm_*` post meta to the new form -4. Returns the new form ID - -## Entry Export - -### REST Endpoint - -`POST /wp-json/sureforms/v1/entries/export` - -**Parameters:** -- `entry_ids` -- Specific entry IDs to export (optional) -- `form_id` -- Export all entries for a specific form -- `status` -- Filter by status (all, read, unread) -- `search` -- Search filter -- `date_from` / `date_to` -- Date range filter - -**Response:** CSV file (or ZIP for large exports) - -### Export Format - -The `Export` class (`inc/export.php`) generates CSV with: -- One row per entry -- Columns for each form field -- Submission metadata (date, status, IP) -- Field values normalized via `srfm_normalize_csv_field_value` filter - -### CSV Field Value Normalization - -The `srfm_normalize_csv_field_value` filter allows customizing how field values appear in CSV exports: - -```php -add_filter( 'srfm_normalize_csv_field_value', function( $value, $field ) { - // Custom formatting for specific field types - return $value; -}, 10, 2 ); -``` - -## Form Lifecycle Management - -### REST Endpoint - -`POST /wp-json/sureforms/v1/forms/manage` - -**Parameters:** -- `form_ids` (required) -- Array of form IDs -- `action` (required) -- `trash`, `restore`, or `delete` - -| Action | Behavior | -|--------|----------| -| `trash` | Move forms to trash (recoverable) | -| `restore` | Restore trashed forms | -| `delete` | Permanently delete forms | - -## Create New Form - -The `Create_New_Form` class (`inc/create-new-form.php`) handles new form creation with default meta values: - -- Sets default styling options -- Configures default submit button text -- Initializes email notification defaults -- Applies default form confirmation settings - -## Related Pages - -- [REST API Reference](REST-API-Reference) -- All export/import endpoints -- [Database Schema](Database-Schema) -- Entry and form data structure -- [Admin Dashboard](Admin-Dashboard) -- UI for export/import operations diff --git a/docs/wiki/Database-Schema.md b/docs/wiki/Database-Schema.md deleted file mode 100644 index c0a47044b..000000000 --- a/docs/wiki/Database-Schema.md +++ /dev/null @@ -1,173 +0,0 @@ -# Database Schema - -SureForms uses two custom database tables alongside the WordPress `sureforms_form` custom post type. All custom tables use the `wp_srfm_` prefix. - -## Table Relationships - -``` -+-------------------+ +-------------------+ -| wp_posts | | wp_srfm_entries | -| (sureforms_form) |<---------| form_id | -| ID (PK) | | | ID (PK) | -| post_content | | | user_id | -| post_meta (_srfm)| | | form_data (JSON) | -+-------------------+ | | status | - | +--------+-----------+ - | | - | +--------v-----------+ - | | wp_srfm_payments | - +----| form_id | - | id (PK) | - | entry_id (FK) | - | transaction_id | - | total_amount | - +--------------------+ -``` - -## Custom Tables - -### wp_srfm_entries - -Stores all form submissions. Table version: 1. - -| Column | Type | Default | Description | -|--------|------|---------|-------------| -| `ID` | BIGINT(20) UNSIGNED | AUTO_INCREMENT | Primary key | -| `form_id` | BIGINT(20) UNSIGNED | -- | Reference to sureforms_form post ID | -| `user_id` | BIGINT(20) UNSIGNED | 0 | WordPress user ID (0 = anonymous) | -| `status` | VARCHAR(10) | `unread` | Entry status: `unread`, `read`, `trash` | -| `type` | VARCHAR(20) | -- | Form type: `quiz`, `standard`, etc. | -| `form_data` | LONGTEXT | `[]` | JSON-encoded submitted field values | -| `submission_info` | LONGTEXT | `[]` | JSON-encoded browser/device/IP metadata | -| `notes` | LONGTEXT | `[]` | JSON-encoded admin notes | -| `logs` | LONGTEXT | `[]` | JSON-encoded activity log entries | -| `extras` | LONGTEXT | `[]` | JSON-encoded misc additional data | -| `created_at` | TIMESTAMP | CURRENT_TIMESTAMP | Submission timestamp | -| `updated_at` | TIMESTAMP | CURRENT_TIMESTAMP ON UPDATE | Last update timestamp | - -**Indexes:** -- `PRIMARY KEY (ID)` -- `INDEX idx_form_id (form_id)` -- `INDEX idx_user_id (user_id)` -- `INDEX idx_form_id_created_at_status (form_id, created_at, status)` -- composite index for list queries - -**Log Entry Structure:** -```json -{ - "title": "Form Submitted", - "messages": ["Email notification sent", "Entry stored"], - "timestamp": "2024-01-15 10:30:00" -} -``` - -### wp_srfm_payments - -Stores payment transaction records linked to form entries. Table version: 1. Added in v2.0.0. - -| Column | Type | Default | Description | -|--------|------|---------|-------------| -| `id` | BIGINT(20) UNSIGNED | AUTO_INCREMENT | Primary key | -| `form_id` | BIGINT(20) UNSIGNED | -- | Reference to sureforms_form post | -| `block_id` | VARCHAR(255) | `''` | Payment block identifier | -| `status` | VARCHAR(50) | `pending` | Payment status (see below) | -| `total_amount` | DECIMAL(26,8) | `0.00000000` | Total amount after discount | -| `refunded_amount` | DECIMAL(26,8) | `0.00000000` | Total refunded amount | -| `currency` | VARCHAR(10) | `''` | ISO 4217 currency code | -| `entry_id` | BIGINT(20) UNSIGNED | 0 | Reference to entries table | -| `gateway` | VARCHAR(20) | `''` | Payment gateway: `stripe` | -| `type` | VARCHAR(30) | `''` | Payment type: `payment`, `subscription`, `renewal` | -| `mode` | VARCHAR(20) | `''` | Mode: `test` or `live` | -| `transaction_id` | VARCHAR(50) | `''` | Gateway transaction ID | -| `customer_id` | VARCHAR(50) | `''` | Gateway customer ID | -| `subscription_id` | VARCHAR(50) | `''` | Subscription ID (if recurring) | -| `subscription_status` | VARCHAR(20) | `''` | Subscription status | -| `parent_subscription_id` | BIGINT(20) UNSIGNED | 0 | Parent subscription payment ID | -| `payment_data` | LONGTEXT | `[]` | JSON-encoded payment details (includes refunds) | -| `extra` | LONGTEXT | `[]` | JSON-encoded additional data | -| `log` | LONGTEXT | `[]` | JSON-encoded payment log | -| `created_at` | TIMESTAMP | CURRENT_TIMESTAMP | Creation timestamp | -| `updated_at` | TIMESTAMP | CURRENT_TIMESTAMP ON UPDATE | Last update timestamp | -| `srfm_txn_id` | VARCHAR(100) | `''` | Custom transaction ID format | -| `customer_email` | VARCHAR(255) | `''` | Customer email | -| `customer_name` | VARCHAR(255) | `''` | Customer name | - -**Valid Payment Statuses:** -`pending`, `succeeded`, `failed`, `canceled`, `requires_action`, `requires_payment_method`, `processing`, `refunded`, `partially_refunded` - -**Valid Subscription Statuses:** -`active`, `canceled`, `past_due`, `unpaid`, `trialing`, `incomplete`, `incomplete_expired`, `paused` - -**Supported Currencies:** -USD, EUR, GBP, JPY, CAD, AUD, CHF, CNY, SEK, NZD, MXN, SGD, HKD, NOK, TRY, RUB, INR, BRL, ZAR, KRW - -## WordPress Post Type: sureforms_form - -Forms are stored as a custom post type (`sureforms_form`) in the standard `wp_posts` table. Block content is in `post_content`, and form configuration is stored as post meta with `_srfm_` prefixed keys. - -### Key Post Meta Keys - -| Meta Key | Type | Description | -|----------|------|-------------| -| `_srfm_forms_styling` | string | Form styling mode | -| `_srfm_color` | string | Primary form color | -| `_srfm_bg_color` | string | Background color | -| `_srfm_fontsize` | string | Font size | -| `_srfm_label_color` | string | Label text color | -| `_srfm_input_color` | string | Input text color | -| `_srfm_submit_button_text` | string | Submit button text | -| `_srfm_submit_alignment` | string | Button alignment | -| `_srfm_submit_width` | string | Button width | -| `_srfm_submit_width_backend` | string | Backend button width | -| `_srfm_is_inline_button` | boolean | Inline button mode | -| `_srfm_email_notification` | array | Email notification settings | -| `_srfm_form_confirmation` | array | Confirmation settings (message/redirect) | -| `_srfm_captcha` | string | CAPTCHA type (recaptcha_v2, v3, hcaptcha, turnstile) | -| `_srfm_honeypot` | boolean | Honeypot spam protection | -| `_srfm_is_page_break` | boolean | Multi-step form enabled | -| `_srfm_single_page_form_title` | boolean | Show title on instant form | -| `_srfm_instant_form_settings` | array | Instant form configuration | -| `_srfm_page_form_logo` | string | Form logo URL | -| `_srfm_submit_type` | string | Submission type | - -Post meta is extensible via the `srfm_register_post_meta` filter. - -## Database Base Class - -All custom tables extend `SRFM\Inc\Database\Base`, which provides: - -### Schema Versioning -- Each table has a `$table_version` integer -- Versions stored in `srfm_database_table_versions` option -- On version mismatch, `start_db_upgrade()` runs migrations (new columns, renames) - -### Query Builder -```php -// Simple equality -$results = $instance->get_results(['form_id' => 123]); - -// Complex conditions with operators -$results = $instance->get_results([ - [ - ['key' => 'status', 'compare' => '!=', 'value' => 'trash'], - ['key' => 'created_at', 'compare' => '>', 'value' => '2024-01-01'], - ] -]); - -// IN operator -$results = $instance->get_results([ - [['key' => 'ID', 'compare' => 'IN', 'value' => [1, 2, 3]]] -]); -``` - -### Caching -Results are cached in-memory using MD5 of the SQL query as the cache key. Cache is reset on insert, update, or delete operations. - -### Data Encoding -Array-type columns (defined in `get_schema()`) are automatically JSON-encoded on write and decoded on read. Number types are cast to integers. - -## Related Pages - -- [Architecture Overview](Architecture-Overview) -- Plugin bootstrap and class initialization -- [Payment Integration](Payment-Integration) -- Stripe payment flow -- [Form Submission Flow](Form-Submission-Flow) -- Entry creation pipeline -- [REST API Reference](REST-API-Reference) -- API endpoints for entries and payments diff --git a/docs/wiki/Deployment-Guide.md b/docs/wiki/Deployment-Guide.md deleted file mode 100644 index 1511856ec..000000000 --- a/docs/wiki/Deployment-Guide.md +++ /dev/null @@ -1,109 +0,0 @@ -# Deployment Guide - -## Release Process Overview - -SureForms follows a branch-based release workflow with automated CI/CD via GitHub Actions. - -## Git Workflow - -``` -feature/branch --> next-release --> master --> tag/release - (development) (production) -``` - -1. Feature branches are created from `next-release` -2. PRs target `next-release` for review and merge -3. `next-release` is merged to `master` for releases -4. Tags trigger release artifacts - -## Build Steps - -### Production Build - -```bash -# Full production build (JS + SASS + minify) -npm run build - -# Individual steps: -npm run build:script # Build JS via wp-scripts -npm run build:sass # Compile SASS via Grunt -``` - -The build process: -1. Webpack bundles JS/React source from `src/` to `assets/build/` -2. Grunt compiles SASS from `sass/` to `assets/css/` -3. Grunt minifies CSS to `assets/css/minified/` -4. Grunt minifies JS to `assets/js/minified/` -5. PostCSS applies Autoprefixer - -### i18n - -```bash -npm run makepot # Generate .pot translation file -``` - -## CI/CD Pipelines - -### GitHub Actions Workflows - -| Workflow | Trigger | Purpose | -|----------|---------|---------| -| `phpunit.yml` | Pull requests | Run PHP unit tests | -| `playwright.yml` | PR labeled `e2e` | Run E2E browser tests | -| `code-analysis.yml` | Pull requests | PHPStan static analysis | -| `insights.yml` | Pull requests | PHP Insights code quality | -| `pr-title.yml` | Pull requests | Validate PR title format | -| `push-to-deploy.yml` | Push to master | Deploy to production | -| `push-asset-readme-update.yml` | Push to master | Update readme/assets | -| `release-tag-draft.yml` | Tag push | Create draft GitHub release | -| `release-pr-template.yml` | Release PRs | Apply release PR template | -| `claude-code-review.yml` | Pull requests | AI-powered code review | - -### Test Pipeline - -Pull requests automatically run: -1. PHPUnit tests (PHP 8.2, WordPress trunk) -2. PHPStan static analysis -3. PHP Insights code quality -4. PR title validation -5. E2E tests (when labeled `e2e`) - -### Deployment Pipeline - -On push to `master`: -1. `push-to-deploy.yml` triggers deployment -2. `push-asset-readme-update.yml` updates WordPress.org assets - -### Release Pipeline - -1. Merge `next-release` into `master` -2. Create a version tag (e.g., `v2.5.1`) -3. `release-tag-draft.yml` creates a draft GitHub release -4. Review and publish the release - -## Pre-Deployment Checklist - -- [ ] All tests pass (PHPUnit, Playwright, Jest) -- [ ] PHPStan analysis clean -- [ ] PHPCS standards pass -- [ ] Production build completes without errors -- [ ] Version bumped in `sureforms.php` and `readme.txt` -- [ ] `SRFM_VER` constant updated -- [ ] `SRFM_PRO_RECOMMENDED_VER` checked -- [ ] Changelog updated in `readme.txt` -- [ ] Translation .pot file regenerated -- [ ] No debug code or console.log statements -- [ ] Database migrations tested (if any) - -## Version Bumping - -Update version in these files: -1. `sureforms.php` -- Plugin header `Version:` and `SRFM_VER` constant -2. `readme.txt` -- `Stable tag:` and changelog section -3. `package.json` -- `version` field - -## Related Pages - -- [Testing Guide](Testing-Guide) -- Test setup and execution -- [Contributing Guide](Contributing-Guide) -- Development workflow -- [Environment Configuration](Environment-Configuration) -- Build tools diff --git a/docs/wiki/Email-Notifications.md b/docs/wiki/Email-Notifications.md deleted file mode 100644 index 642751bcb..000000000 --- a/docs/wiki/Email-Notifications.md +++ /dev/null @@ -1,86 +0,0 @@ -# Email Notifications - -SureForms sends email notifications on form submission and supports scheduled email summary digests. - -## Email System Overview - -``` -Form Submission - -> Form_Submit::handle_form_submission() - -> Email_Template (inc/email/email-template.php) - -> Smart_Tags resolution - -> wp_mail() dispatch -``` - -## Email Template - -The `Email_Template` class (`inc/email/email-template.php`) handles: - -- HTML email template rendering -- Dynamic content insertion via smart tags -- Multiple notification recipients -- Customizable subject lines and body content -- Reply-to address configuration - -### Per-Form Email Settings - -Email notifications are configured per-form via the `_srfm_email_notification` post meta key. Each form can have: - -- **To** -- Recipient email addresses (supports multiple, comma-separated) -- **Subject** -- Email subject line (supports smart tags) -- **Body** -- Email content (supports smart tags and HTML) -- **Reply-To** -- Reply-to email address -- **CC/BCC** -- Additional recipients - -## Smart Tags - -The `Smart_Tags` class (`inc/smart-tags.php`) provides template variables that are resolved at email send time: - -| Smart Tag | Description | -|-----------|-------------| -| `{admin_email}` | WordPress admin email | -| `{site_title}` | WordPress site title | -| `{site_url}` | WordPress site URL | -| `{form_title}` | Name of the submitted form | -| `{form_id}` | ID of the submitted form | -| `{entry_id}` | ID of the created entry | -| `{all_fields}` | All submitted field values formatted | -| `{field:field_name}` | Specific field value by field name | -| `{user_ip}` | Submitter's IP address | -| `{user_agent}` | Submitter's browser user agent | -| `{submission_date}` | Date of submission | - -Smart tags are processed by replacing the tag placeholders with actual values from the form submission data. - -## Email Summary - -The `Email_Summary` class (`inc/global-settings/email-summary.php`) provides scheduled digest reports: - -- Configurable frequency (daily, weekly, monthly) -- Summary of form submissions over the period -- Entry counts per form -- Sent to configured admin email addresses -- Uses WordPress cron (`Events_Scheduler`) for scheduling - -## Customization - -### Modifying Email Content - -Email content is filtered through smart tag processing, allowing dynamic content: - -```php -// In per-form settings, the email body supports: -// - Smart tags: {form_title}, {all_fields}, etc. -// - HTML formatting -// - Custom text -``` - -### Extending Smart Tags - -Smart tags can be extended by hooking into the tag resolution process to add custom replacements. - -## Related Pages - -- [Form Submission Flow](Form-Submission-Flow) -- When emails are triggered -- [WordPress Hooks Reference](WordPress-Hooks-Reference) -- Email-related hooks -- [Architecture Overview](Architecture-Overview) -- Email_Template initialization diff --git a/docs/wiki/Environment-Configuration.md b/docs/wiki/Environment-Configuration.md deleted file mode 100644 index 8c25069d3..000000000 --- a/docs/wiki/Environment-Configuration.md +++ /dev/null @@ -1,197 +0,0 @@ -# Environment Configuration - -## Prerequisites - -| Requirement | Version | Notes | -|-------------|---------|-------| -| PHP | 7.4+ | WordPress minimum requirement | -| WordPress | 6.4+ | Gutenberg block editor required | -| Node.js | 18.15.0 | Managed via Volta (see `package.json`) | -| Composer | 2.x | PHP dependency management | -| npm | 9.x+ | Comes with Node 18 | - -## Plugin Constants - -Defined in `sureforms.php`: - -| Constant | Value | Purpose | -|----------|-------|---------| -| `SRFM_FILE` | `__FILE__` | Absolute path to main plugin file | -| `SRFM_BASENAME` | `sureforms/sureforms.php` | Plugin basename for hooks | -| `SRFM_DIR` | Plugin directory path | File system path operations | -| `SRFM_URL` | Plugin URL | Asset URL generation | -| `SRFM_VER` | `2.5.1` | Version for cache busting | -| `SRFM_SLUG` | `srfm` | Short identifier slug | -| `SRFM_FORMS_POST_TYPE` | `sureforms_form` | Custom post type slug | -| `SRFM_ENTRIES` | `sureforms_entries` | Entries identifier | -| `SRFM_PAYMENTS` | `sureforms_payments` | Payments identifier | -| `SRFM_WEBSITE` | `https://sureforms.com/` | Official website | -| `SRFM_AI_MIDDLEWARE` | `https://credits.startertemplates.com/sureforms/` | AI credits API | -| `SRFM_MIDDLEWARE_BASE_URL` | `https://api.sureforms.com/` | API middleware | -| `SRFM_BILLING_PORTAL` | `https://billing.sureforms.com/` | Billing portal | -| `SRFM_PRO_RECOMMENDED_VER` | `2.5.1` | Minimum recommended Pro version | -| `SRFM_SURETRIGGERS_INTEGRATION_BASE_URL` | `https://app.ottokit.com/` | OttoKit integration | - -## Development Environment Setup - -### Option 1: wp-env (Docker) - -```bash -# Start the WordPress environment -npm run play:up - -# Stop the environment -npm run play:stop - -# Clean environment data -npm run env:clean -``` - -Configuration is in `.wp-env.json`. Requires Docker to be installed. - -### Option 2: Local by Flywheel / MAMP / XAMPP - -1. Set up a local WordPress installation -2. Clone the repo into `wp-content/plugins/sureforms` -3. Run `composer install` for PHP dependencies -4. Run `npm install` for JS dependencies -5. Run `npm start` for development with hot reload - -## Build Tools - -### wp-scripts (JavaScript) - -Primary build tool for JS/React compilation via Webpack: - -```bash -npm start # Dev server with hot reload -npm run build:script # Production JS build -``` - -Entry points are defined in `webpack.config.js` and output to `assets/build/`. - -### Grunt (SASS / Minification) - -```bash -npm run build:sass # Compile SASS to CSS -npm run build # Full build (JS + SASS + minify) -``` - -The `Gruntfile.js` handles: -- SASS compilation (`sass/` -> `assets/css/`) -- CSS minification -- JS minification -- PostCSS with Autoprefixer - -### Tailwind CSS - -Used for admin dashboard styles. Configuration in `tailwind.config.js`: -- Content scanning paths: `src/admin/**/*.{js,jsx}` -- Plugin: `@tailwindcss/forms` -- Custom theme extensions for Force UI integration - -### PostCSS - -Configuration in `postcss.config.js`: -- Autoprefixer for browser compatibility -- cssnano for production minification - -## NPM Scripts Reference - -| Script | Command | Description | -|--------|---------|-------------| -| `start` | `wp-scripts start` | Dev server with hot reload | -| `build` | Full pipeline | JS + SASS + minify | -| `build:script` | `wp-scripts build` | Build JS only | -| `build:sass` | Grunt sass tasks | Build SASS only | -| `lint-js` | `wp-scripts lint-js` | ESLint check | -| `lint-js:fix` | `wp-scripts lint-js --fix` | Auto-fix JS lint | -| `lint-css` | `wp-scripts lint-style` | Stylelint check | -| `lint-css:fix` | `wp-scripts lint-style --fix` | Auto-fix CSS lint | -| `pretty` | `prettier --check` | Prettier check | -| `pretty:fix` | `prettier --write` | Prettier format | -| `test:unit` | `wp-scripts test-unit-js` | Jest unit tests | -| `play:up` | `wp-env start` | Start Docker env | -| `play:stop` | `wp-env stop` | Stop Docker env | -| `play:run` | `playwright test` | Run E2E tests | -| `play:run:interactive` | `playwright test --headed` | E2E tests (headed) | -| `env:clean` | `wp-env clean` | Clean Docker data | -| `makepot` | `wp i18n make-pot` | Generate .pot file | - -## Composer Scripts - -| Script | Description | -|--------|-------------| -| `vendor/bin/phpunit` | Run PHPUnit tests | -| `vendor/bin/phpcs` | PHP CodeSniffer (WPCS) | -| `vendor/bin/phpcbf` | Auto-fix PHPCS issues | -| `vendor/bin/phpstan` | PHPStan static analysis | - -## Linting Configuration - -### PHP (PHPCS) - -Configured via `phpcs.xml`: -- Ruleset: WordPress Coding Standards (WPCS) -- PHPCompatibility for PHP 7.4+ -- Text domain: `sureforms` -- Prefixes: `srfm`, `SRFM_` - -### JavaScript (ESLint) - -Uses `@wordpress/scripts` ESLint configuration which extends WordPress defaults. - -### CSS (Stylelint) - -WordPress Stylelint configuration via `@wordpress/scripts`. - -### Prettier - -Code formatting for JS/CSS files. - -## Volta Configuration - -Node version is pinned in `package.json`: - -```json -{ - "volta": { - "node": "18.15.0" - } -} -``` - -Install Volta to automatically use the correct Node version when entering the project directory. - -## Key Dependencies - -### PHP (Composer) - -| Package | Purpose | -|---------|---------| -| `yoast/phpunit-polyfills` | PHPUnit compatibility | -| `squizlabs/php_codesniffer` | Code style checking | -| `wp-coding-standards/wpcs` | WordPress standards | -| `phpcompatibility/php-compatibility` | PHP version checks | -| `phpstan/phpstan` | Static type analysis | -| `nunomaduro/phpinsights` | Code quality insights | - -### JavaScript (npm) - -| Package | Purpose | -|---------|---------| -| `@bsf/force-ui` | BSF internal UI component library | -| `@wordpress/scripts` | Build tooling | -| `@wordpress/api-fetch` | REST API client | -| `@tanstack/react-query` | Data fetching/caching | -| `react-router-dom` | Client-side routing | -| `tailwindcss` | Utility-first CSS | -| `@playwright/test` | E2E testing | -| `@wordpress/env` | Docker test environment | - -## Related Pages - -- [Architecture Overview](Architecture-Overview) -- Plugin structure and bootstrap -- [Testing Guide](Testing-Guide) -- Test setup and execution -- [Contributing Guide](Contributing-Guide) -- Coding standards and workflow -- [Frontend Assets](Frontend-Assets) -- Asset pipeline details diff --git a/docs/wiki/Form-Fields-Architecture.md b/docs/wiki/Form-Fields-Architecture.md deleted file mode 100644 index 285f4793c..000000000 --- a/docs/wiki/Form-Fields-Architecture.md +++ /dev/null @@ -1,137 +0,0 @@ -# Form Fields Architecture - -SureForms uses a layered architecture for form fields: Gutenberg blocks define the editor experience, field markup classes generate the frontend HTML, and the validation system ensures data integrity on submission. - -## Field Type Hierarchy - -``` -Fields\Base (inc/fields/base.php) - |-- Input_Markup (text, hidden) - |-- Email_Markup (email with validation) - |-- Textarea_Markup (multi-line text) - |-- Number_Markup (numeric with min/max) - |-- Phone_Markup (with country selector) - |-- URL_Markup (URL with validation) - |-- Dropdown_Markup (select options) - |-- Checkbox_Markup (single/multiple) - |-- Multichoice_Markup (radio/checkbox groups) - |-- Address_Markup (composite address field) - |-- GDPR_Markup (consent checkbox) - |-- Payment_Markup (Stripe payment field) - |-- Inlinebutton_Markup (inline buttons) -``` - -## Base Field Class - -`inc/fields/base.php` provides the foundation: - -- Common HTML wrapper generation -- Label rendering with required indicator -- Help text / description output -- Error message container -- CSS class assembly with `srfm-` prefix -- Conditional logic attribute output -- Accessibility attributes (aria-label, aria-required) - -## Markup Generation Pattern - -Each field markup class follows a consistent pattern: - -1. Receive block attributes from the Gutenberg block -2. Process and sanitize attribute values -3. Generate field-specific HTML using WordPress escaping functions -4. Wrap in the standard field container with label and error placeholder -5. Return the complete HTML string - -## Available Field Types - -### Input (input-markup.php) -Standard text input supporting `text`, `hidden`, and other HTML5 input types. Supports placeholder, default value, min/max length. - -### Email (email-markup.php) -Email input with built-in email format validation. Supports confirmation email field option. - -### Textarea (textarea-markup.php) -Multi-line text area with configurable rows and max length. - -### Number (number-markup.php) -Numeric input with min/max value constraints, step size, and format validation. - -### Phone (phone-markup.php) -Phone number input integrated with `intl-tel-input` library for country code selection. Uses `countries.json` for country data. - -### URL (url-markup.php) -URL input with format validation. - -### Dropdown (dropdown-markup.php) -Select dropdown with configurable options. Supports default selection and placeholder text. - -### Checkbox (checkbox-markup.php) -Single or multiple checkbox inputs with label positioning options. - -### Multi Choice (multichoice-markup.php) -Radio button or checkbox groups for multiple choice questions. Supports image choices and custom layouts. - -### Address (address-markup.php) -Composite field with subfields: street address, city, state/province, zip/postal code, and country. Each subfield is independently configurable. - -### GDPR (gdpr-markup.php) -GDPR consent checkbox with customizable compliance text. Integrates with form-level compliance settings. - -### Payment (payment-markup.php) -Payment collection field for Stripe integration. Renders the payment form elements and connects to the payment processing flow. - -## Validation System - -### Server-Side Validation (field-validation.php) - -`inc/field-validation.php` handles validation during form submission: - -- **Required field check** -- Ensures required fields have values -- **Type validation** -- Validates data types (email format, URL format, number ranges) -- **Unique value check** -- Optional unique validation against existing entries -- **Custom validation** -- Extensible via filters - -Common error messages are defined in `Helper::get_common_err_msg()`: -- `required`: "This field is required." -- `unique`: "Value needs to be unique." - -### Client-Side Validation - -Frontend JavaScript provides instant validation feedback before submission, matching server-side rules. - -## Field Rendering Pipeline - -``` -1. Block Editor (Gutenberg) - -> Block attributes saved in post_content - -2. Frontend Request - -> Generate_Form_Markup::get_form_markup() - -> Parses post_content blocks - -> For each block, calls its render callback - -3. Block Render Callback - -> Block class (inc/blocks/{type}/block.php) - -> Instantiates field markup class - -> Passes block attributes - -4. Field Markup Generation - -> Field markup class (inc/fields/{type}-markup.php) - -> Base class wraps with container, label, error placeholder - -> Field-specific HTML generated - -> Returns escaped HTML string - -5. Form Assembly - -> All field HTML concatenated inside
wrapper - -> Submit button appended - -> Nonce field added - -> Final form HTML returned -``` - -## Related Pages - -- [Gutenberg Blocks](Gutenberg-Blocks) -- Block registration and editor components -- [Form Submission Flow](Form-Submission-Flow) -- How field data is validated and processed -- [WordPress Hooks Reference](WordPress-Hooks-Reference) -- Field-related filters -- [Payment Integration](Payment-Integration) -- Payment field details diff --git a/docs/wiki/Form-Submission-Flow.md b/docs/wiki/Form-Submission-Flow.md deleted file mode 100644 index 81a9e3806..000000000 --- a/docs/wiki/Form-Submission-Flow.md +++ /dev/null @@ -1,191 +0,0 @@ -# Form Submission Flow - -This page documents the end-to-end form submission process from frontend to entry storage. - -## Flow Diagram - -``` -+------------------+ +-------------------+ +------------------+ -| User fills form |---->| JavaScript fetch() |---->| REST API | -| in browser | | POST /submit-form | | Form_Submit | -+------------------+ +-------------------+ +--------+---------+ - | - +--------------------------------+ - | - +----------v-----------+ - | Permission Check | - | - X-WP-Submit-Nonce | - | - Form data exists | - +----------+-----------+ - | - +----------v-----------+ - | Form Restrictions | - | - Max entries check | - | - Date scheduling | - | - Login required | - +----------+-----------+ - | - +----------v-----------+ - | Field Validation | - | - Required fields | - | - Type validation | - | - Unique values | - +----------+-----------+ - | - +----------v-----------+ - | Security Checks | - | - CAPTCHA verify | - | - Honeypot check | - +----------+-----------+ - | - +----------v-----------+ - | Data Processing | - | - Sanitize fields | - | - Smart tag resolve | - | - Collect metadata | - +----------+-----------+ - | - +----------------+----------------+ - | | -+--------v--------+ +--------v--------+ -| Email Notify | | Entry Storage | -| Email_Template | | wp_srfm_entries | -+-----------------+ +--------+--------+ - | - +--------v--------+ - | Payment Process | - | (if applicable) | - | wp_srfm_payments| - +--------+--------+ - | - +--------v--------+ - | Confirmation | - | Response | - +-----------------+ -``` - -## Step-by-Step Process - -### 1. Frontend Submission - -The form is submitted via JavaScript `fetch()` to `POST /wp-json/sureforms/v1/submit-form` with: - -- Form field data as POST body -- `X-WP-Submit-Nonce` header for security (does not require logged-in user) -- Form ID to identify which form was submitted - -Nonces can be refreshed via `GET /refresh-nonces` (public, no auth required). - -### 2. Permission Check - -`Form_Submit::submit_form_permissions_check()`: - -- Verifies the `X-WP-Submit-Nonce` header -- Validates that form data and form ID are present -- Returns `WP_Error` on failure - -### 3. Form Restrictions - -`Form_Restriction` class checks: - -- **Maximum entries** -- Has the form reached its submission limit? -- **Date scheduling** -- Is the form within its active date range? -- **Login required** -- Does the form require a logged-in user? -- **Entry caps** -- Per-user submission limits - -### 4. Field Validation - -`Field_Validation` (`inc/field-validation.php`): - -- **Required fields** -- Ensures all required fields have non-empty values -- **Type validation** -- Email format, URL format, number ranges, phone format -- **Unique values** -- Checks existing entries for uniqueness if configured -- Returns validation errors that prevent submission - -### 5. Security Verification - -- **CAPTCHA** -- Validates reCAPTCHA v2/v3, hCaptcha, or Cloudflare Turnstile token -- **Honeypot** -- Checks the hidden honeypot field is empty (bots fill it) - -### 6. Data Processing - -- `apply_filters('srfm_form_submit_data', $data, $form_id)` -- allows modification -- Sanitizes each field value -- Resolves smart tags for email templates -- Collects submission metadata (IP, browser via Browser class, device info) -- `do_action('srfm_before_submission', $data, $form_id)` - -### 7. Email Notifications - -`Email_Template` sends configured email notifications: - -- Processes smart tags in subject and body -- Sends to configured recipients -- Handles CC/BCC -- See [Email Notifications](Email-Notifications) for details - -### 8. Entry Storage - -Checks GDPR compliance (`do_not_store_entries` setting). If storage is allowed: - -```php -Entries::add([ - 'form_id' => $form_id, - 'user_id' => get_current_user_id(), - 'form_data' => $sanitized_data, // JSON-encoded - 'submission_info' => $metadata, // JSON-encoded - 'logs' => $activity_logs, // JSON-encoded - 'status' => 'unread', - 'type' => $form_type, // 'standard', 'quiz', etc. -]); -``` - -### 9. Payment Processing - -If the form includes a payment block: - -- Stripe payment is processed -- Payment record created in `wp_srfm_payments` -- Payment ID linked to the entry -- See [Payment Integration](Payment-Integration) for details - -### 10. Post-Submission - -- `do_action('srfm_form_submit', $entry_id, $form_id, $form_data)` -- `do_action('srfm_after_submission_process', $entry_id, $form_id)` -- Returns confirmation response: - - **Message** -- Display a success message - - **Redirect** -- Redirect to a specified URL - -## Form Confirmation Types - -Configured via `_srfm_form_confirmation` post meta: - -| Type | Behavior | -|------|----------| -| Message | Display a success message on the same page | -| Redirect | Redirect to a specified URL after submission | - -Confirmation parameters are filterable via `srfm_form_confirmation_params`. - -## Error Handling - -Errors at any stage return a JSON error response to the frontend: - -```json -{ - "success": false, - "data": "Validation error message" -} -``` - -The frontend JavaScript displays errors inline next to the relevant fields. - -## Related Pages - -- [REST API Reference](REST-API-Reference) -- Submit endpoint details -- [Database Schema](Database-Schema) -- Entry and payment table structure -- [Email Notifications](Email-Notifications) -- Email dispatch details -- [Payment Integration](Payment-Integration) -- Payment processing -- [WordPress Hooks Reference](WordPress-Hooks-Reference) -- Submission hooks -- [Form Fields Architecture](Form-Fields-Architecture) -- Field validation diff --git a/docs/wiki/Frontend-Assets.md b/docs/wiki/Frontend-Assets.md deleted file mode 100644 index 99b4cca91..000000000 --- a/docs/wiki/Frontend-Assets.md +++ /dev/null @@ -1,122 +0,0 @@ -# Frontend Assets - -SureForms manages assets across three contexts: frontend (form display), admin (dashboard), and block editor. - -## Asset Loading Strategy - -### Frontend (Form Display) - -`inc/frontend-assets.php` (`Frontend_Assets` class) handles loading CSS/JS on pages containing SureForms forms: - -- Detects form blocks in page content -- Enqueues only necessary field-specific CSS/JS -- Loads Stripe JS SDK only when payment fields are present -- Enqueues `intl-tel-input` only when phone fields exist - -### Admin Dashboard - -Admin assets are enqueued only on SureForms admin pages: - -- React app bundle from `assets/build/` -- Tailwind CSS base styles from `src/admin/tw-base.scss` -- Localized data via `wp_localize_script()` - -### Block Editor - -`inc/gutenberg-hooks.php` (`Gutenberg_Hooks` class) loads editor assets: - -- Block editor JS/CSS from `assets/build/` -- Editor-specific stylesheets -- Block preview styles - -## Build Pipeline - -### wp-scripts (Webpack) - -Primary JS build tool. Configuration extends `@wordpress/scripts` defaults: - -```bash -npm start # Development with hot reload -npm run build:script # Production build -``` - -**Entry Points:** -- `src/blocks/blocks.js` -- Gutenberg block registration -- `src/admin/editor-scripts.js` -- Admin dashboard React app -- Additional entries per block type - -**Output:** `assets/build/` directory - -**Webpack Features:** -- Code splitting per entry point -- WordPress dependency extraction (`@wordpress/*` packages) -- Source maps in development -- Asset hashing for cache busting - -### Grunt (SASS / Minification) - -```bash -npm run build:sass # Compile SASS only -npm run build # Full build (JS + SASS + minify) -``` - -The `Gruntfile.js` tasks include: - -| Task | Description | -|------|-------------| -| `sass` | Compile SASS files from `sass/` to `assets/css/` | -| `postcss` | Run PostCSS with Autoprefixer | -| `cssmin` | Minify CSS to `assets/css/minified/` | -| `uglify` | Minify JS to `assets/js/minified/` | -| `copy` | Copy assets to distribution directories | - -### SASS Directory Structure - -``` -sass/ -|-- frontend block styles -|-- form field styles -|-- layout and grid styles -``` - -Compiled output: `assets/css/` (unminified) and `assets/css/minified/` - -### Tailwind CSS - -Used exclusively for admin dashboard pages: - -**Configuration (`tailwind.config.js`):** -- Content paths: `src/admin/**/*.{js,jsx}` -- Plugins: `@tailwindcss/forms` -- Custom theme extensions for Force UI compatibility -- `tailwind-merge` used for dynamic class composition - -**Base styles:** `src/admin/tw-base.scss` - -## CSS Naming Conventions - -| Context | Prefix | Example | -|---------|--------|---------| -| Frontend form styles | `srfm-` | `srfm-input-field`, `srfm-form-container` | -| Admin dashboard | Tailwind utilities | `flex items-center gap-2` | -| Block editor | `srfm-editor-` | `srfm-editor-preview` | - -## Asset Versioning - -All enqueued assets use `SRFM_VER` (currently `2.5.1`) for cache busting: - -```php -wp_enqueue_style( - 'srfm-frontend', - SRFM_URL . 'assets/css/minified/frontend.min.css', - [], - SRFM_VER -); -``` - -## Related Pages - -- [Admin Dashboard](Admin-Dashboard) -- React admin asset details -- [Gutenberg Blocks](Gutenberg-Blocks) -- Block editor assets -- [Environment Configuration](Environment-Configuration) -- Build tool setup -- [Contributing Guide](Contributing-Guide) -- CSS/JS conventions diff --git a/docs/wiki/Getting-Started.md b/docs/wiki/Getting-Started.md deleted file mode 100644 index ab30b0818..000000000 --- a/docs/wiki/Getting-Started.md +++ /dev/null @@ -1,149 +0,0 @@ -# Getting Started - -This guide walks you through setting up a SureForms development environment from scratch. - -## Prerequisites - -| Tool | Version | Notes | -|------|---------|-------| -| PHP | 7.4+ | Required for plugin runtime | -| WordPress | 6.4+ | Required for block editor features | -| Node.js | 18.15.0 | Managed via Volta (auto-switches) | -| Composer | 2.x | PHP dependency manager | -| Git | 2.x | Version control | -| Docker | Latest | Optional, for wp-env test environment | - -### Installing Volta (Recommended) - -[Volta](https://volta.sh/) ensures you use the correct Node.js version automatically: - -```bash -curl https://get.volta.sh | bash -``` - -The `package.json` pins Node 18.15.0 via Volta config -- it activates automatically when you enter the project directory. - -## Initial Setup - -### 1. Clone the Repository - -```bash -git clone https://github.com/brainstormforce/sureforms.git -cd sureforms -``` - -### 2. Install Dependencies - -```bash -composer install # PHP dependencies -npm install # Node dependencies -``` - -### 3. Build the Plugin - -```bash -npm run build # Full production build (JS + SASS + minify) -``` - -This runs three steps: -1. `wp-scripts build` -- Bundles JS/React from `src/` to `build/` -2. SASS compilation -- Compiles `sass/` to `assets/css/` -3. `grunt minify` -- Minifies CSS and JS to `assets/css/minified/` and `assets/js/minified/` - -### 4. Start Development Server - -```bash -npm start # wp-scripts dev server with hot reload -``` - -This watches `src/` for changes and rebuilds JS automatically. For SASS changes, run `npm run build:sass` separately. - -## WordPress Environment - -### Option A: Local WordPress Installation - -1. Set up a local WordPress site (e.g., using Local, MAMP, or Docker) -2. Symlink or copy the plugin into `wp-content/plugins/sureforms/` -3. Activate the plugin from the WordPress admin - -### Option B: wp-env (Docker-Based) - -The project includes a `.wp-env.json` configuration for a Docker-based WordPress environment: - -```bash -npm run play:up # Start WordPress + MySQL containers -``` - -This provides: -- WordPress at `http://localhost:8888` (admin: `admin` / `password`) -- Test WordPress at `http://localhost:8889` -- Plugin auto-mounted and activated -- Consistent environment across developers - -Additional commands: -```bash -npm run play:stop # Stop containers -npm run env:clean # Reset all data -``` - -## Verifying Your Setup - -### Run Linters - -```bash -vendor/bin/phpcs # PHP CodeSniffer -npm run lint-js # ESLint -npm run lint-css # Stylelint -npm run pretty # Prettier -``` - -### Run Tests - -```bash -vendor/bin/phpunit # PHP unit tests -npm run test:unit # JavaScript unit tests -``` - -### Build Check - -```bash -npm run build # Should complete without errors -``` - -## Project Structure Overview - -``` -sureforms/ -โ”œโ”€โ”€ sureforms.php # Plugin entry point -โ”œโ”€โ”€ plugin-loader.php # Autoloader and bootstrap -โ”œโ”€โ”€ inc/ # PHP classes (core logic) -โ”œโ”€โ”€ src/ # JS/React source (compiled by wp-scripts) -โ”‚ โ”œโ”€โ”€ admin/ # Admin dashboard React app -โ”‚ โ”œโ”€โ”€ blocks/ # Gutenberg block components -โ”‚ โ”œโ”€โ”€ components/ # Shared React components -โ”‚ โ””โ”€โ”€ store/ # WordPress data store -โ”œโ”€โ”€ sass/ # SASS source files -โ”œโ”€โ”€ assets/ # Compiled assets (CSS, JS, images) -โ”œโ”€โ”€ templates/ # PHP templates (BladeOne) -โ”œโ”€โ”€ tests/ # Test files -โ”œโ”€โ”€ modules/ # Feature modules -โ””โ”€โ”€ admin/ # Admin PHP + assets -``` - -See [Architecture Overview](Architecture-Overview) for a detailed breakdown. - -## Key Concepts - -- **Custom Post Type**: Forms are stored as `sureforms_form` posts with block content -- **Custom Database Tables**: Entries in `wp_srfm_entries`, payments in `wp_srfm_payments` -- **REST API**: All data operations use the `sureforms/v1` REST namespace -- **Block Editor**: Form fields are Gutenberg blocks registered via `block.json` -- **Admin SPA**: The dashboard is a React single-page application using Force UI components - -## Next Steps - -- [Architecture Overview](Architecture-Overview) -- Understand the codebase -- [Contributing Guide](Contributing-Guide) -- Development workflow and standards -- [Gutenberg Blocks](Gutenberg-Blocks) -- How form blocks work -- [REST API Reference](REST-API-Reference) -- Available API endpoints -- [Testing Guide](Testing-Guide) -- Running and writing tests diff --git a/docs/wiki/Gutenberg-Blocks.md b/docs/wiki/Gutenberg-Blocks.md deleted file mode 100644 index ed38cd9b3..000000000 --- a/docs/wiki/Gutenberg-Blocks.md +++ /dev/null @@ -1,129 +0,0 @@ -# Gutenberg Blocks - -SureForms provides 14+ Gutenberg block types for building forms in the WordPress block editor. - -## Block Types - -### Field Blocks - -| Block | Slug | Description | -|-------|------|-------------| -| Input | `srfm/input` | Text input (text, hidden, etc.) | -| Email | `srfm/email` | Email address input with validation | -| Textarea | `srfm/textarea` | Multi-line text area | -| Number | `srfm/number` | Numeric input with min/max | -| Phone | `srfm/phone` | Phone number with country selector (intl-tel-input) | -| URL | `srfm/url` | URL input with validation | -| Dropdown | `srfm/dropdown` | Select dropdown with options | -| Checkbox | `srfm/checkbox` | Single/multiple checkboxes | -| Multi Choice | `srfm/multichoice` | Radio/checkbox group | -| Address | `srfm/address` | Address field with subfields (street, city, state, zip, country) | -| GDPR | `srfm/gdpr` | GDPR consent checkbox | -| Payment | `srfm/payment` | Payment collection (Stripe integration) | -| Inline Button | `srfm/inlinebutton` | Inline form button | - -### Container Block - -| Block | Slug | Description | -|-------|------|-------------| -| SForm | `srfm/sform` | Main form wrapper block (required container for all field blocks) | - -## Block Registration - -### Server-Side (PHP) - -Blocks are registered in `inc/blocks/register.php` via the `Blocks\Register` class, initialized on the `init` hook: - -```php -// inc/blocks/register.php -register_block_type_from_metadata( - SRFM_DIR . 'inc/blocks/{block-type}/', - [ - 'render_callback' => [ $block_instance, 'render' ], - ] -); -``` - -Each block type has: -- `block.json` -- Block metadata, attributes, and category -- `block.php` -- Server-side rendering class extending `Blocks\Base` - -### Client-Side (JavaScript) - -Block registration happens in `src/blocks/blocks.js`: - -```javascript -// src/blocks/blocks.js -import { registerBlockType } from '@wordpress/blocks'; -// Block imports and registrations... -``` - -The `src/blocks/register-block.js` utility handles individual block registration. - -## Block Architecture - -### Base Class: `Blocks\Base` - -All block PHP classes extend `SRFM\Inc\Blocks\Base`, which provides: - -- `render()` -- Main render callback invoked by WordPress -- Access to block attributes from `block.json` -- Common rendering logic shared across field types -- Integration with field markup classes - -### Block to Field Mapping - -Each block delegates HTML generation to its corresponding field markup class in `inc/fields/`: - -``` -Block (inc/blocks/input/block.php) - -> Field Markup (inc/fields/input-markup.php) - -> Base Field (inc/fields/base.php) - -> HTML output -``` - -### block.json Structure - -Each block directory contains a `block.json` file defining: - -```json -{ - "apiVersion": 3, - "name": "srfm/input", - "title": "Input", - "category": "sureforms", - "attributes": { - "label": { "type": "string", "default": "Input" }, - "required": { "type": "boolean", "default": false }, - "placeholder": { "type": "string", "default": "" } - }, - "supports": { "html": false } -} -``` - -## Adding a New Block Type - -1. **Create block directory:** `inc/blocks/{new-type}/` -2. **Add `block.json`** with attributes, name, and category -3. **Create `block.php`** extending `Blocks\Base` with a `render()` method -4. **Create field markup:** `inc/fields/{new-type}-markup.php` extending `Fields\Base` -5. **Register in `Blocks\Register`** -- add to the blocks array -6. **Create editor component:** `src/blocks/{new-type}/` with `edit.js` and `index.js` -7. **Add to `src/blocks/blocks.js`** -- import and register the new block - -## The sform Container Block - -The `srfm/sform` block is the required wrapper for all form fields. It: - -- Renders the `` HTML element -- Handles form-level settings (styling, confirmation, CAPTCHA) -- Manages submission nonce generation -- Controls form layout and submit button -- Integrates with frontend JavaScript for submission handling - -## Related Pages - -- [Form Fields Architecture](Form-Fields-Architecture) -- Field markup and validation -- [Block Editor Controls](Block-Editor-Controls) -- Custom inspector controls -- [Architecture Overview](Architecture-Overview) -- Block registration in bootstrap -- [Frontend Assets](Frontend-Assets) -- Block editor asset loading diff --git a/docs/wiki/Home.md b/docs/wiki/Home.md deleted file mode 100644 index 1c270a210..000000000 --- a/docs/wiki/Home.md +++ /dev/null @@ -1,58 +0,0 @@ -# SureForms Wiki - -Welcome to the SureForms developer wiki. This documentation covers the architecture, APIs, development workflows, and internals of the SureForms WordPress form builder plugin. - -**Version:** 2.5.1 | **WordPress:** 6.4+ | **PHP:** 7.4+ | **Node:** 18.15.0 - -## Quick Links - -- [Getting Started](Getting-Started) -- Set up your development environment -- [Architecture Overview](Architecture-Overview) -- Understand the codebase structure -- [Contributing Guide](Contributing-Guide) -- How to contribute - -## Architecture & Core - -| Page | Description | -|------|-------------| -| [Architecture Overview](Architecture-Overview) | Plugin bootstrap, namespaces, directory layout, design patterns | -| [Database Schema](Database-Schema) | Custom tables (`wp_srfm_entries`, `wp_srfm_payments`), post meta keys | -| [Environment Configuration](Environment-Configuration) | Constants, build tools, linting, development setup | -| [Form Submission Flow](Form-Submission-Flow) | End-to-end submission pipeline from frontend to storage | - -## WordPress / Backend - -| Page | Description | -|------|-------------| -| [Gutenberg Blocks](Gutenberg-Blocks) | Block types, registration, `block.json` structure | -| [Form Fields Architecture](Form-Fields-Architecture) | Field type hierarchy, validation, rendering pipeline | -| [WordPress Hooks Reference](WordPress-Hooks-Reference) | Custom actions, filters, and execution order | -| [Payment Integration](Payment-Integration) | Stripe setup, payment flow, webhooks, refunds | -| [Email Notifications](Email-Notifications) | Email templates, smart tags, notification settings | -| [AI Form Builder](AI-Form-Builder) | AI-powered form generation process | -| [Data Export & Import](Data-Export-Import) | Form/entry export, import, duplication | - -## Frontend / React - -| Page | Description | -|------|-------------| -| [Admin Dashboard](Admin-Dashboard) | React SPA architecture, routing, data fetching | -| [State Management](State-Management) | WordPress data store, actions, selectors | -| [Frontend Assets](Frontend-Assets) | Asset loading, build pipeline, SASS, Tailwind | -| [Block Editor Controls](Block-Editor-Controls) | Custom inspector controls, CSS generation, icons | - -## API - -| Page | Description | -|------|-------------| -| [REST API Reference](REST-API-Reference) | All endpoints with methods, parameters, authentication | - -## Development Workflow - -| Page | Description | -|------|-------------| -| [Getting Started](Getting-Started) | Prerequisites, installation, first build | -| [Contributing Guide](Contributing-Guide) | Git workflow, coding standards, PR process | -| [Testing Guide](Testing-Guide) | PHPUnit, Playwright, Jest setup and execution | -| [Deployment Guide](Deployment-Guide) | CI/CD pipelines, release process, version bumping | -| [Troubleshooting & FAQ](Troubleshooting-FAQ) | Common issues and debugging tips | -| [Changelog](Changelog) | Recent version history | diff --git a/docs/wiki/Payment-Integration.md b/docs/wiki/Payment-Integration.md deleted file mode 100644 index 28d985e6e..000000000 --- a/docs/wiki/Payment-Integration.md +++ /dev/null @@ -1,127 +0,0 @@ -# Payment Integration - -SureForms supports Stripe payment processing with one-time payments and recurring subscriptions. - -## Architecture Overview - -``` -inc/payments/ -|-- payments.php # Main payments orchestrator -|-- front-end.php # Frontend payment handling -|-- payment-helper.php # Shared payment utilities -|-- admin/ -| |-- admin-handler.php # Admin payment management UI -|-- stripe/ - |-- payments-settings.php # Stripe settings + REST routes - |-- stripe-helper.php # Stripe API utilities - |-- stripe-webhook.php # Webhook event handler - |-- admin-stripe-handler.php # Admin Stripe config -``` - -## Stripe Setup - -### Configuration - -Stripe settings are managed via the admin settings page and stored as WordPress options: - -1. Navigate to SureForms > Settings > Payments -2. Connect your Stripe account via OAuth flow -3. Configure test/live mode -4. Set default currency - -The `Payments_Settings` class registers REST routes for settings management and handles the Stripe OAuth callback via `admin_init`. - -### OAuth Flow - -1. Admin clicks "Connect Stripe" in settings -2. `intercept_stripe_callback()` on `admin_init` handles the OAuth redirect -3. Stripe credentials are securely stored in WordPress options - -## Payment Flow - -``` -1. FORM DISPLAY - - Payment block renders Stripe Elements - - Frontend_Assets enqueues Stripe JS SDK - - Payment form elements injected into the form - -2. FORM SUBMISSION - - User fills form + enters payment details - - Frontend JavaScript creates Stripe PaymentIntent - - Form data + payment token submitted to /submit-form - -3. SERVER PROCESSING - - Form_Submit validates form data - - Payment processing triggered - - Stripe API called to confirm payment - - Payment record created in wp_srfm_payments table - - Entry created in wp_srfm_entries table - - Payment ID linked to entry - -4. WEBHOOK HANDLING - - Stripe sends webhook events to /wp-json endpoint - - Stripe_Webhook validates signature - - Payment status updated in database - - Subscription events handled (renewal, cancellation, etc.) -``` - -## Payment Database Schema - -Payments are stored in the `wp_srfm_payments` custom table. See [Database Schema](Database-Schema) for full column definitions. - -### Payment Types - -| Type | Description | -|------|-------------| -| `payment` | One-time payment | -| `subscription` | Recurring subscription record | -| `renewal` | Subscription renewal payment | - -### Payment Statuses - -`pending`, `succeeded`, `failed`, `canceled`, `requires_action`, `requires_payment_method`, `processing`, `refunded`, `partially_refunded` - -### Subscription Statuses - -`active`, `canceled`, `past_due`, `unpaid`, `trialing`, `incomplete`, `incomplete_expired`, `paused` - -## Webhook Handling - -The `Stripe_Webhook` class (`inc/payments/stripe/stripe-webhook.php`) processes Stripe webhook events: - -- Validates webhook signature using Stripe signing secret -- Handles payment status updates (succeeded, failed, etc.) -- Processes subscription lifecycle events (renewal, cancellation) -- Creates renewal payment records for subscription billing cycles -- Updates payment and subscription statuses in the database - -## Refund Management - -The `Payments` table class provides refund tracking: - -- `add_refund_to_payment_data()` -- Record refund details in payment_data JSON -- `add_refund_amount()` -- Increment the refunded_amount column -- `get_refundable_amount()` -- Calculate remaining refundable balance -- `is_fully_refunded()` / `is_partially_refunded()` -- Status checks - -## Supported Currencies - -USD, EUR, GBP, JPY, CAD, AUD, CHF, CNY, SEK, NZD, MXN, SGD, HKD, NOK, TRY, RUB, INR, BRL, ZAR, KRW - -## Payment Modes - -| Mode | Description | -|------|-------------| -| `test` | Stripe test mode (test API keys) | -| `live` | Stripe live mode (production) | - -## Admin Payment Management - -The `Admin_Handler` class provides the admin interface for viewing and managing payments. Payment IDs in entry views are rendered as clickable links via the `srfm_entry_value` filter. - -## Related Pages - -- [Database Schema](Database-Schema) -- Payment table columns and relationships -- [Form Submission Flow](Form-Submission-Flow) -- Payment processing in submission pipeline -- [REST API Reference](REST-API-Reference) -- Payment-related endpoints -- [Gutenberg Blocks](Gutenberg-Blocks) -- Payment block type diff --git a/docs/wiki/REST-API-Reference.md b/docs/wiki/REST-API-Reference.md deleted file mode 100644 index d366470e5..000000000 --- a/docs/wiki/REST-API-Reference.md +++ /dev/null @@ -1,114 +0,0 @@ -# REST API Reference - -All endpoints are registered under the namespace `sureforms/v1` and accessible at `/wp-json/sureforms/v1/`. - -## Authentication - -### Admin Endpoints -All admin endpoints require the `manage_options` capability. Authentication is via WordPress REST API nonce (`X-WP-Nonce` header) or cookie-based auth. - -Permission check: `Helper::get_items_permissions_check()` verifies `current_user_can('manage_options')`. - -### Public Endpoints -The form submission endpoint uses a custom nonce (`X-WP-Submit-Nonce` header) that does not require a logged-in user. - -## Endpoints - -### AI Form Builder - -| Method | Endpoint | Description | -|--------|----------|-------------| -| POST | `/generate-form` | Generate a form using AI | -| POST | `/map-fields` | Map AI response to SureForms Gutenberg blocks | -| GET | `/initiate-auth` | Get auth URL for AI billing portal | -| POST | `/handle-access-key` | Decrypt and save AI access key | - -### Dashboard - -| Method | Endpoint | Description | -|--------|----------|-------------| -| GET | `/entries-chart-data` | Get entries chart data for analytics | -| GET | `/form-data` | Get all forms data for dashboard | -| GET | `/plugin-status` | Check integration plugin install status | - -### Onboarding - -| Method | Endpoint | Description | -|--------|----------|-------------| -| POST | `/onboarding/set-status` | Mark onboarding as complete | -| GET | `/onboarding/get-status` | Get current onboarding status | - -### Entries - -| Method | Endpoint | Description | Parameters | -|--------|----------|-------------|------------| -| GET | `/entries/list` | Paginated entries listing | `form_id`, `status`, `search`, `date_from`, `date_to`, `orderby`, `order`, `per_page`, `page` | -| POST | `/entries/read-status` | Bulk mark entries read/unread | `entry_ids` (required), `action` (required: read/unread) | -| POST | `/entries/trash` | Bulk trash/restore entries | `entry_ids` (required), `action` (required: trash/restore) | -| POST | `/entries/delete` | Permanently delete entries | `entry_ids` (required) | -| POST | `/entries/export` | Export entries to CSV/ZIP | `entry_ids`, `form_id`, `status`, `search`, `date_from`, `date_to` | -| GET | `/entry/{id}/details` | Single entry with form data | `id` (required) | -| GET | `/entry/{id}/logs` | Entry activity logs | `id` (required), `page`, `per_page` | - -### Forms - -| Method | Endpoint | Description | Parameters | -|--------|----------|-------------|------------| -| GET | `/forms` | Paginated forms listing | `page`, `per_page`, `search`, `status`, `orderby`, `order`, `date_from`, `date_to` | -| POST | `/forms/export` | Export forms as JSON | `form_ids` (required) | -| POST | `/forms/import` | Import forms from JSON | File upload | -| POST | `/forms/manage` | Manage form lifecycle | `form_ids` (required), `action` (trash/restore/delete) | -| POST | `/forms/duplicate` | Duplicate a form | `form_id` (required) | - -### Form Submission (Public) - -| Method | Endpoint | Auth | Description | -|--------|----------|------|-------------| -| POST | `/submit-form` | Custom nonce | Public form submission | -| GET | `/refresh-nonces` | None | Refresh frontend nonces | - -## Extending the API - -Endpoints are extensible via the `srfm_rest_api_endpoints` filter: - -```php -add_filter( 'srfm_rest_api_endpoints', function( $endpoints ) { - $endpoints['custom/endpoint'] = [ - 'methods' => 'GET', - 'callback' => [ $this, 'handle_custom' ], - 'permission_callback' => [ Helper::class, 'get_items_permissions_check' ], - ]; - return $endpoints; -} ); -``` - -## Error Responses - -Errors are returned via `wp_send_json_error()`: - -```json -{ - "success": false, - "data": "Error message string" -} -``` - -## Pagination - -List endpoints support pagination with consistent parameters: - -| Parameter | Default | Description | -|-----------|---------|-------------| -| `page` | 1 | Current page number | -| `per_page` | 20 | Items per page | -| `orderby` | `created_at` | Sort column | -| `order` | `DESC` | Sort direction (ASC/DESC) | - -Response includes total counts for pagination UI. - -## Related Pages - -- [Architecture Overview](Architecture-Overview) -- API registration flow -- [Form Submission Flow](Form-Submission-Flow) -- Submit endpoint details -- [Data Export Import](Data-Export-Import) -- Export/import endpoints -- [Payment Integration](Payment-Integration) -- Payment API endpoints diff --git a/docs/wiki/State-Management.md b/docs/wiki/State-Management.md deleted file mode 100644 index 6cb4b072a..000000000 --- a/docs/wiki/State-Management.md +++ /dev/null @@ -1,109 +0,0 @@ -# State Management - -SureForms uses the `@wordpress/data` package to create a Redux-like data store for managing application state in the block editor. - -## Store Structure - -Located in `src/store/`: - -``` -src/store/ -|-- store.js # Store registration -|-- reducer.js # State reducers -|-- actions.js # Action creators -|-- selectors.js # State selectors -|-- constants.js # Store constants -|-- setInitialState.js # Initial state configuration -``` - -## Store Registration - -The store is registered with `@wordpress/data` in `store.js`: - -```javascript -import { createReduxStore, register } from '@wordpress/data'; -import reducer from './reducer'; -import * as actions from './actions'; -import * as selectors from './selectors'; - -const store = createReduxStore('sureforms', { - reducer, - actions, - selectors, -}); - -register(store); -``` - -The store namespace is `sureforms`. - -## Initial State - -`setInitialState.js` configures the initial state from server-side localized data (`wp_localize_script`), providing: - -- Form settings and metadata -- Block defaults -- User preferences -- Plugin configuration - -## Actions - -Actions are defined in `actions.js` and dispatched to modify the store state. They follow the WordPress data store pattern: - -```javascript -// Dispatching an action -import { dispatch } from '@wordpress/data'; -dispatch('sureforms').updateFormSettings({ key: 'value' }); -``` - -## Selectors - -Selectors in `selectors.js` extract specific data from the store state: - -```javascript -// Using a selector -import { select } from '@wordpress/data'; -const settings = select('sureforms').getFormSettings(); -``` - -## Component Integration - -Components connect to the store using WordPress data hooks: - -```javascript -import { useSelect, useDispatch } from '@wordpress/data'; - -function MyComponent() { - const formData = useSelect((select) => { - return select('sureforms').getFormSettings(); - }, []); - - const { updateFormSettings } = useDispatch('sureforms'); - - return ( - - ); -} -``` - -## Constants - -`constants.js` defines store-wide constants used across actions, reducers, and selectors to ensure consistency. - -## Usage Context - -The WordPress data store is primarily used in: - -- **Block editor** -- Form-level settings and block state -- **Inspector controls** -- Sidebar settings panels -- **Block attributes** -- Synchronized state between blocks - -For the admin dashboard pages, `@tanstack/react-query` is used instead for server state management. See [Admin Dashboard](Admin-Dashboard) for details. - -## Related Pages - -- [Admin Dashboard](Admin-Dashboard) -- React admin app architecture -- [Block Editor Controls](Block-Editor-Controls) -- Inspector controls using the store -- [Gutenberg Blocks](Gutenberg-Blocks) -- Block registration and attributes diff --git a/docs/wiki/Testing-Guide.md b/docs/wiki/Testing-Guide.md deleted file mode 100644 index 393f57583..000000000 --- a/docs/wiki/Testing-Guide.md +++ /dev/null @@ -1,172 +0,0 @@ -# Testing Guide - -SureForms uses three testing frameworks: PHPUnit for PHP unit tests, Playwright for end-to-end tests, and Jest for JavaScript unit tests. - -## Testing Strategy - -| Level | Framework | Location | Purpose | -|-------|-----------|----------|---------| -| Unit (PHP) | PHPUnit 9.x | `tests/unit/` | PHP class and function testing | -| Unit (JS) | Jest | Via `wp-scripts` | JavaScript utility testing | -| E2E | Playwright 1.48+ | `tests/play/` | Full browser-based workflow testing | - -## PHPUnit (PHP Unit Tests) - -### Setup - -1. Install PHP dependencies: - ```bash - composer install - ``` - -2. WordPress test environment must be available (via wp-env or local setup) - -### Running Tests - -```bash -# Run all PHP unit tests -vendor/bin/phpunit - -# Run a specific test file -vendor/bin/phpunit tests/unit/test-specific.php - -# Run tests with verbose output -vendor/bin/phpunit --verbose -``` - -### Test File Conventions - -- Location: `tests/unit/` -- File prefix: `test-` (e.g., `test-helper.php`) -- Class naming: `Test_ClassName` extending `WP_UnitTestCase` -- Method naming: `test_` prefix (e.g., `test_form_submission()`) - -### CI Configuration - -PHPUnit runs in GitHub Actions (`.github/workflows/phpunit.yml`): -- PHP: 8.2 -- WordPress: trunk -- MySQL: 5.7 -- Triggered on pull requests - -## Playwright (E2E Tests) - -### Prerequisites - -- Node.js 18.15.0 (Volta) -- Docker (for wp-env) - -### Setup - -```bash -# Install dependencies -npm install - -# Start the WordPress environment -npm run play:up - -# Build the plugin -npm run build - -# Install Playwright browsers -npx playwright install -``` - -### Running Tests - -```bash -# Run all E2E tests (headless) -npm run play:run - -# Run tests in headed mode (visible browser) -npm run play:run:interactive - -# Run a specific test file -npx playwright test tests/play/specific-test.spec.js -``` - -### Test File Conventions - -- Location: `tests/play/` -- File suffix: `.spec.js` -- Uses Playwright Test runner with `expect` assertions -- Page Object Model pattern for reusable interactions - -### CI Configuration - -Playwright runs in GitHub Actions (`.github/workflows/playwright.yml`): -- Triggered when PR is labeled with `e2e` -- Node: 18.15 -- Builds plugin and starts wp-env -- Generates HTML test report (30-day artifact retention) - -## Jest (JavaScript Unit Tests) - -### Running Tests - -```bash -npm run test:unit -``` - -Uses `@wordpress/scripts` Jest configuration with WordPress-specific transforms and module resolution. - -## Test Environment (wp-env) - -The Docker-based test environment is configured in `.wp-env.json`: - -```bash -# Start environment -npm run play:up - -# Stop environment -npm run play:stop - -# Clean all data -npm run env:clean -``` - -wp-env provides: -- WordPress installation with the plugin active -- MySQL database -- Consistent environment across developers -- Used by both Playwright E2E tests and local development - -## Writing New Tests - -### PHP Unit Test - -```php -class Test_My_Feature extends WP_UnitTestCase { - public function test_feature_works() { - // Arrange - $form_id = $this->factory->post->create([ - 'post_type' => 'sureforms_form', - ]); - - // Act - $result = some_function($form_id); - - // Assert - $this->assertEquals('expected', $result); - } -} -``` - -### Playwright E2E Test - -```javascript -const { test, expect } = require('@playwright/test'); - -test('form submission works', async ({ page }) => { - await page.goto('/form-page/'); - await page.fill('[name="email"]', 'test@example.com'); - await page.click('button[type="submit"]'); - await expect(page.locator('.success-message')).toBeVisible(); -}); -``` - -## Related Pages - -- [Environment Configuration](Environment-Configuration) -- Development setup -- [Contributing Guide](Contributing-Guide) -- Test requirements for PRs -- [Deployment Guide](Deployment-Guide) -- CI/CD test pipeline diff --git a/docs/wiki/Troubleshooting-FAQ.md b/docs/wiki/Troubleshooting-FAQ.md deleted file mode 100644 index 871e632b7..000000000 --- a/docs/wiki/Troubleshooting-FAQ.md +++ /dev/null @@ -1,232 +0,0 @@ -# Troubleshooting & FAQ - -Common issues, debugging tips, and frequently asked questions for SureForms development. - -## Common Development Issues - -### Build Failures - -**Problem:** `npm run build` fails with errors. - -**Solutions:** -1. Ensure Node.js 18.15.0 is active (Volta manages this automatically via `package.json`): - ```bash - node -v # Should output v18.15.0 - ``` -2. Clear and reinstall dependencies: - ```bash - rm -rf node_modules - npm install - ``` -3. If SASS compilation fails, check that `sass/` source files have valid syntax -4. If Grunt minification fails, ensure Grunt CLI is available: - ```bash - npx grunt minify - ``` - -### wp-env Issues - -**Problem:** `npm run play:up` fails to start the Docker environment. - -**Solutions:** -1. Ensure Docker is installed and running -2. Clean the environment: - ```bash - npm run env:clean - ``` -3. Restart the environment: - ```bash - npm run play:stop - npm run play:up - ``` -4. If port conflicts occur, check for other services on ports 8888/8889 - -### PHPCS Errors - -**Problem:** `vendor/bin/phpcs` reports violations. - -**Solutions:** -1. Auto-fix what's possible: - ```bash - vendor/bin/phpcbf - ``` -2. Common issues: - - Missing text domain: Add `'sureforms'` to all translatable strings - - Unescaped output: Wrap output in `esc_html()`, `esc_attr()`, etc. - - Missing nonce verification: Add nonce checks for form/AJAX handlers - - Short array syntax: Use `[]` instead of `array()` (enforced by config) - -### PHPUnit Test Failures - -**Problem:** `vendor/bin/phpunit` tests fail. - -**Solutions:** -1. Ensure WordPress test environment is available (wp-env or local setup) -2. Check database connectivity for the test suite -3. Run a specific test to isolate the issue: - ```bash - vendor/bin/phpunit tests/unit/test-specific.php - ``` - -### JavaScript Lint Errors - -**Problem:** `npm run lint-js` reports errors. - -**Solutions:** -1. Auto-fix most issues: - ```bash - npm run lint-js:fix - ``` -2. Format code with Prettier: - ```bash - npm run pretty:fix - ``` -3. Common issues: - - Import ordering: WordPress dependencies should use `@wordpress/*` - - Unused variables: Remove or prefix with underscore - - Missing dependencies in `useEffect`: Add to dependency array - -## Form Submission Issues - -### Nonce Verification Fails - -**Cause:** The `X-WP-Submit-Nonce` has expired (default: 24-hour lifetime). - -**Debug:** -- Nonces can be refreshed via `GET /wp-json/sureforms/v1/refresh-nonces` -- Check that the nonce is being sent in the request header -- Caching plugins may cache the nonce -- exclude form pages from page cache - -### CAPTCHA Validation Fails - -**Cause:** CAPTCHA keys are misconfigured or the token is expired. - -**Debug:** -1. Verify CAPTCHA keys in SureForms global settings -2. Check browser console for CAPTCHA loading errors -3. Ensure the CAPTCHA provider (reCAPTCHA, hCaptcha, Turnstile) is correctly configured -4. reCAPTCHA v3 can trigger multiple times on pages with multiple forms - -### File Upload Errors - -**Debug:** -1. Check PHP `upload_max_filesize` and `post_max_size` in `php.ini` -2. Verify allowed file types in form field settings -3. Check file size against the configured maximum -4. Ensure the `wp-content/uploads/` directory is writable - -## Database Issues - -### Custom Tables Missing - -**Cause:** The `wp_srfm_entries` or `wp_srfm_payments` table was not created. - -**Debug:** -1. Deactivate and reactivate the plugin to trigger table creation -2. Check the `srfm_db_version` option in `wp_options` -3. Verify database user has `CREATE TABLE` permissions -4. Check for errors in `debug.log` during activation - -### Entry Data Not Saving - -**Debug:** -1. Check the `do_not_store_entries` form setting (GDPR compliance) -2. Verify the form submission response for error messages -3. Check `debug.log` for database insert errors -4. Ensure the entries table schema is up to date - -## REST API Issues - -### 401 Unauthorized on Admin Endpoints - -**Cause:** User is not authenticated or lacks required capabilities. - -**Debug:** -1. Admin endpoints require `manage_options` capability -2. Ensure the user is logged in with a valid session -3. Check that the REST API nonce is being sent (via `X-WP-Nonce` header) -4. WordPress cookie authentication must be active - -### 403 on Form Submission - -**Cause:** The submit nonce is invalid or form restrictions are blocking submission. - -**Debug:** -1. Check the `X-WP-Submit-Nonce` header value -2. Review form restriction settings (max entries, date scheduling, login required) -3. Check the `srfm_form_submit_permissions_check` filter - -## Performance Issues - -### Slow Admin Dashboard - -**Causes & Solutions:** -1. **Large number of entries:** Entries are paginated -- default page size is managed by REST API -2. **Unoptimized queries:** The entries table has indexes on `form_id`, `user_id`, and a composite index on `(form_id, created_at, status)` -3. **Asset loading:** Admin assets are conditionally loaded only on SureForms admin pages - -### Slow Form Rendering - -**Causes & Solutions:** -1. **Too many blocks:** Complex forms with many fields may benefit from multi-step layout -2. **External scripts:** CAPTCHA and payment scripts load conditionally based on form settings -3. **CSS generation:** Each block generates dynamic CSS -- review `generateCSS.js` for optimization - -## Debugging Tips - -### Enable WordPress Debug Mode - -Add to `wp-config.php`: -```php -define( 'WP_DEBUG', true ); -define( 'WP_DEBUG_LOG', true ); -define( 'WP_DEBUG_DISPLAY', false ); -define( 'SCRIPT_DEBUG', true ); -``` - -### Check REST API Responses - -Use the browser developer tools Network tab to inspect REST API calls: -- Filter by `sureforms/v1` to see plugin API requests -- Check response status codes and error messages - -### Inspect Form Data Store - -In the browser console on a form editor page: -```javascript -wp.data.select('starter-starter/starter-starter-forms-data').getFormSettings(); -``` - -## FAQ - -### What WordPress version is required? - -WordPress 6.4 or higher is required. - -### What PHP version is required? - -PHP 7.4 or higher. The `phpcs.xml` enforces PHP 7.4+ compatibility. - -### Can I modify bundled libraries? - -Files in `inc/lib/` are third-party libraries and should not be modified directly. If changes are needed, they should be managed upstream. - -### Where do I put new PHP classes? - -New PHP classes go in the `inc/` directory following the existing namespace structure (`SRFM\Inc\*`). The autoloader in `plugin-loader.php` handles class loading. - -### How do I add a new admin page? - -Admin pages are rendered by the React SPA in `src/admin/`. Add new routes using `react-router-dom` and register the corresponding menu items in PHP. See [Admin Dashboard](Admin-Dashboard) for details. - -### How do I add a new form field type? - -See [Form Fields Architecture](Form-Fields-Architecture) for the field type hierarchy and the process for adding new field types. - -## Related Pages - -- [Environment Configuration](Environment-Configuration) -- Development setup -- [Testing Guide](Testing-Guide) -- Running tests -- [Architecture Overview](Architecture-Overview) -- Codebase structure -- [REST API Reference](REST-API-Reference) -- API endpoints -- [Database Schema](Database-Schema) -- Table structure diff --git a/docs/wiki/WordPress-Hooks-Reference.md b/docs/wiki/WordPress-Hooks-Reference.md deleted file mode 100644 index 1db16e372..000000000 --- a/docs/wiki/WordPress-Hooks-Reference.md +++ /dev/null @@ -1,152 +0,0 @@ -# WordPress Hooks Reference - -SureForms exposes custom actions and filters for extensibility, and hooks into WordPress core lifecycle events. - -## Custom Actions - -| Action | Parameters | Description | -|--------|-----------|-------------| -| `srfm_core_loaded` | -- | Fired after Plugin_Loader singleton is created | -| `srfm_before_submission` | `$form_data`, `$form_id` | Before form submission is processed | -| `srfm_form_submit` | `$entry_id`, `$form_id`, `$form_data` | After form submission is complete | -| `srfm_after_submission_process` | `$entry_id`, `$form_id` | After all post-submission processing | -| `srfm_before_delete_entry` | `$entry_id` | Before an entry is permanently deleted | - -## Custom Filters - -### REST API - -| Filter | Parameters | Description | -|--------|-----------|-------------| -| `srfm_rest_api_endpoints` | `$endpoints` | Add/modify REST API endpoints | - -### Form Data - -| Filter | Parameters | Description | -|--------|-----------|-------------| -| `srfm_form_submit_data` | `$form_data`, `$form_id` | Modify form data before processing | -| `srfm_entry_value` | `$value`, `$args` | Transform entry field values in responses | -| `srfm_normalize_csv_field_value` | `$value`, `$field` | Custom CSV export value formatting | -| `srfm_form_confirmation_params` | `$params`, `$form_id` | Modify confirmation settings | - -### Post Meta - -| Filter | Parameters | Description | -|--------|-----------|-------------| -| `srfm_register_post_meta` | `$meta_keys` | Register additional form post meta keys | - -### Blocks - -| Filter | Parameters | Description | -|--------|-----------|-------------| -| `srfm_is_special_block` | `$is_special`, `$block_name` | Declare a block as special (nested) | -| `srfm_handle_special_block` | `$result`, `$block` | Custom processing for special blocks | -| `srfm_extract_form_fields_field_name` | `$field_name`, `$block` | Modify generated field names | - -### Settings - -| Filter | Parameters | Description | -|--------|-----------|-------------| -| `srfm_global_settings_data` | `$settings` | Extend global settings data | -| `srfm_disable_nps_survey` | `$disable` | Disable NPS survey module | -| `srfm_enable_redirect_activation` | `$enable` | Control activation redirect behavior | - -## WordPress Core Hooks Used - -### plugins_loaded - -| Priority | Callback | Class | -|----------|----------|-------| -| default | `load_textdomain()` | Plugin_Loader | -| 99 | `load_plugin()` | Plugin_Loader | - -### init - -| Priority | Callback | Purpose | -|----------|----------|---------| -| 10 | `load_classes()` | Block registration, admin, payments | - -### rest_api_init - -| Callback | Class | Purpose | -|----------|-------|---------| -| `register_endpoints()` | Rest_Api | Register all admin REST endpoints | -| `register_routes()` | Form_Submit | Register public submission endpoints | -| `register_rest_routes()` | Payments_Settings | Register payment REST routes | - -### admin_init - -| Callback | Purpose | -|----------|---------| -| `activation_redirect()` | Redirect to onboarding after activation | -| `intercept_stripe_callback()` | Handle Stripe OAuth callback | - -### wp_enqueue_scripts - -| Callback | Class | Purpose | -|----------|-------|---------| -| Asset enqueue | Frontend_Assets | Load form CSS/JS on pages with forms | - -### enqueue_block_editor_assets - -| Callback | Class | Purpose | -|----------|-------|---------| -| Editor asset enqueue | Gutenberg_Hooks | Load block editor JS/CSS | - -## Hook Execution Order (Form Submission) - -``` -1. REST API receives POST /submit-form -2. Form_Submit::submit_form_permissions_check() - -> Nonce verification -3. Form_Submit::handle_form_submission() - -> apply_filters('srfm_form_submit_data', $data, $form_id) - -> Field validation - -> CAPTCHA verification - -> Honeypot check -4. do_action('srfm_before_submission', $data, $form_id) -5. Email notification sent -6. Entry stored in database -7. do_action('srfm_form_submit', $entry_id, $form_id, $data) -8. do_action('srfm_after_submission_process', $entry_id, $form_id) -9. Confirmation response returned -``` - -## Usage Examples - -### Adding a Custom REST Endpoint - -```php -add_filter( 'srfm_rest_api_endpoints', function( $endpoints ) { - $endpoints['my-custom/data'] = [ - 'methods' => 'GET', - 'callback' => 'my_custom_callback', - 'permission_callback' => [ \SRFM\Inc\Helper::class, 'get_items_permissions_check' ], - ]; - return $endpoints; -} ); -``` - -### Modifying Form Data Before Processing - -```php -add_filter( 'srfm_form_submit_data', function( $data, $form_id ) { - // Add custom processing - $data['custom_field'] = 'custom_value'; - return $data; -}, 10, 2 ); -``` - -### Running Code After Submission - -```php -add_action( 'srfm_form_submit', function( $entry_id, $form_id, $form_data ) { - // Send to external service, trigger automation, etc. -}, 10, 3 ); -``` - -## Related Pages - -- [Architecture Overview](Architecture-Overview) -- Plugin bootstrap and hook registration -- [REST API Reference](REST-API-Reference) -- Full endpoint documentation -- [Form Submission Flow](Form-Submission-Flow) -- Submission hook execution order diff --git a/docs/wiki/_Footer.md b/docs/wiki/_Footer.md deleted file mode 100644 index 0a54d2e24..000000000 --- a/docs/wiki/_Footer.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - -**SureForms** by [Brainstorm Force](https://brainstormforce.com/) | [GitHub](https://github.com/brainstormforce/sureforms) | [Website](https://sureforms.com/) | [Support](https://support.brainstormforce.com/) diff --git a/docs/wiki/_Sidebar.md b/docs/wiki/_Sidebar.md deleted file mode 100644 index aedcc5e5b..000000000 --- a/docs/wiki/_Sidebar.md +++ /dev/null @@ -1,35 +0,0 @@ -**[Home](Home)** - -**Getting Started** -- [Getting Started](Getting-Started) -- [Environment Configuration](Environment-Configuration) - -**Architecture** -- [Architecture Overview](Architecture-Overview) -- [Database Schema](Database-Schema) -- [Form Submission Flow](Form-Submission-Flow) - -**WordPress / Backend** -- [Gutenberg Blocks](Gutenberg-Blocks) -- [Form Fields Architecture](Form-Fields-Architecture) -- [WordPress Hooks Reference](WordPress-Hooks-Reference) -- [Payment Integration](Payment-Integration) -- [Email Notifications](Email-Notifications) -- [AI Form Builder](AI-Form-Builder) -- [Data Export & Import](Data-Export-Import) - -**Frontend / React** -- [Admin Dashboard](Admin-Dashboard) -- [State Management](State-Management) -- [Frontend Assets](Frontend-Assets) -- [Block Editor Controls](Block-Editor-Controls) - -**API** -- [REST API Reference](REST-API-Reference) - -**Development** -- [Contributing Guide](Contributing-Guide) -- [Testing Guide](Testing-Guide) -- [Deployment Guide](Deployment-Guide) -- [Troubleshooting & FAQ](Troubleshooting-FAQ) -- [Changelog](Changelog) diff --git a/images/suredonation.svg b/images/suredonation.svg new file mode 100644 index 000000000..d4c8d93d1 --- /dev/null +++ b/images/suredonation.svg @@ -0,0 +1,4 @@ + + + + diff --git a/inc/abilities/CLAUDE.md b/inc/abilities/CLAUDE.md deleted file mode 100644 index 0a7af5e04..000000000 --- a/inc/abilities/CLAUDE.md +++ /dev/null @@ -1,66 +0,0 @@ -# Abilities โ€” Development Guide - -## Adding a New Ability - -1. Create a class extending `Abstract_Ability` in the appropriate subdirectory: - - `forms/` โ€” form CRUD operations - - `entries/` โ€” entry/submission operations - - `embedding/` โ€” shortcodes, block markup, rendering - - `settings/` โ€” global settings read/write - - `analytics/` โ€” form analytics and reporting - - `export/` โ€” form and entry import/export -2. Register it in `Abilities_Registrar::register_abilities()` - -## Abstract_Ability Contract - -Every ability must implement: -- **Constructor** โ€” set `$id`, `$label`, `$description`, `$capability` -- **`get_input_schema()`** โ€” JSON Schema for input validation -- **`get_output_schema()`** โ€” JSON Schema for output contract -- **`execute( $input )`** โ€” business logic, return array or `WP_Error` -- **`get_annotations()`** โ€” override if not default (`readonly`, `destructive`, `idempotent`) - -## Conventions - -- ID format: `sureforms/-` (e.g. `sureforms/list-forms`) -- Namespace: `SRFM\Inc\Abilities\\` -- Return `WP_Error` for failures, never throw exceptions -- Default capability: `edit_posts` โ€” override per-ability where needed -- Destructive abilities must set `destructive: true` in annotations -- All classes need `@since x.x.x` tags -- Add PHPUnit tests in `tests/unit/inc/abilities/` for every new ability - -## Architecture - -``` -inc/abilities/ -โ”œโ”€โ”€ abstract-ability.php # Base class โ€” do not modify without updating all abilities -โ”œโ”€โ”€ abilities-registrar.php # Singleton โ€” registers category + all abilities -โ”œโ”€โ”€ forms/ -โ”‚ โ”œโ”€โ”€ list-forms.php # readonly, idempotent -โ”‚ โ”œโ”€โ”€ create-form.php # uses Field_Mapping engine -โ”‚ โ”œโ”€โ”€ get-form.php # readonly, idempotent โ€” parses Gutenberg blocks -โ”‚ โ”œโ”€โ”€ delete-form.php # destructive -โ”‚ โ”œโ”€โ”€ duplicate-form.php # delegates to \SRFM\Inc\Duplicate_Form -โ”‚ โ”œโ”€โ”€ update-form.php # write, idempotent โ€” title/status/metadata -โ”‚ โ””โ”€โ”€ get-form-stats.php # readonly, idempotent โ€” entry counts -โ”œโ”€โ”€ entries/ -โ”‚ โ”œโ”€โ”€ list-entries.php # readonly, idempotent โ€” paginated listing -โ”‚ โ”œโ”€โ”€ get-entry.php # readonly, idempotent โ€” decrypted form_data -โ”‚ โ”œโ”€โ”€ update-entry-status.php # write, idempotent โ€” read/unread/trash/restore -โ”‚ โ””โ”€โ”€ delete-entry.php # destructive โ€” permanent delete -โ”œโ”€โ”€ embedding/ -โ”‚ โ””โ”€โ”€ get-shortcode.php # readonly, idempotent -โ”œโ”€โ”€ settings/ -โ”‚ โ”œโ”€โ”€ get-global-settings.php # readonly, idempotent โ€” all setting categories -โ”‚ โ””โ”€โ”€ update-global-settings.php # write, idempotent โ€” delegates to Global_Settings -โ””โ”€โ”€ analytics/ - โ””โ”€โ”€ get-form-analytics.php # readonly, idempotent โ€” submission date queries -``` - -## Extensibility - -- **Filter:** `srfm_register_abilities` โ€” third-party plugins can add abilities (must extend `Abstract_Ability`) -- **Hooks:** `srfm_before_ability_execute` / `srfm_after_ability_execute` โ€” fire around every execution -- **Collision guard:** Registrar checks `wp_has_ability()` before registering to avoid duplicates with zipwp-mcp -- **WP < 6.9:** Registrar bails in constructor โ€” zero overhead when Abilities API is unavailable diff --git a/inc/field-validation.php b/inc/field-validation.php index dd555f24f..e02c0e9d2 100644 --- a/inc/field-validation.php +++ b/inc/field-validation.php @@ -551,6 +551,16 @@ private static function process_number_block( $attrs ) { $number_config['max'] = floatval( $attrs['max'] ); } + // Capture calculation config (Pro feature) so a calculation-driven number field used as a + // payment amount source can be re-derived server-side instead of trusting the submitted + // value. Harmless when the calculation feature is not in use. + if ( ! empty( $attrs['enableCalculation'] ) ) { + $number_config['enableCalculation'] = true; + $number_config['calculationFormula'] = isset( $attrs['calculationFormula'] ) && is_string( $attrs['calculationFormula'] ) ? $attrs['calculationFormula'] : ''; + // Stored as null when unset so the validator rounds only when a precision is configured. + $number_config['calculationRound'] = isset( $attrs['calculationRound'] ) && is_numeric( $attrs['calculationRound'] ) ? absint( $attrs['calculationRound'] ) : null; + } + return $number_config; } } diff --git a/inc/fields/phone-markup.php b/inc/fields/phone-markup.php index fe166502c..866cf16df 100644 --- a/inc/fields/phone-markup.php +++ b/inc/fields/phone-markup.php @@ -87,23 +87,31 @@ public function __construct( $attributes ) { $this->include_countries = $attributes['includeCountries'] ?? []; $this->exclude_countries = $attributes['excludeCountries'] ?? []; - // When auto country is enabled, detect the visitor's country via server-side - // IP geolocation (ipapi.co) instead of a client-side fetch. + // When auto country is enabled, resolve a best-effort country here at render + // time to seed the baked `default-country` attribute (a sensible flag before + // any JS runs). The authoritative per-visitor detection happens client-side: + // phone.js applies an immediate network-free Intl guess and then refines it + // from the same-origin geo-country REST endpoint โ€” so it stays correct even on + // full-page-cached sites, where this baked value would otherwise be the first + // visitor's country. // // Why not get_locale()? // WordPress get_locale() returns the *site's* configured language (e.g. 'en_US'), // not the visitor's physical location. A site set to English would show 'US' for // every visitor worldwide โ€” defeating the purpose of auto-country detection. // - // Why server-side instead of client-side? - // The previous client-side fetch('https://ipapi.co/json') caused CORS failures, - // 429 rate limits on high-traffic sites, and exposed visitor IPs to a third party - // directly from the browser. Moving it server-side eliminates all three issues. - // - // Performance: The API is called only once per visitor IP and cached in a transient - // for 24 hours โ€” subsequent page loads for the same IP resolve instantly from cache. + // Why resolve server-side at all (vs. a browser geo-IP fetch)? + // A client-side fetch('https://ipapi.co/json') caused CORS failures, 429 rate + // limits on high-traffic sites, and exposed visitor IPs to a third party from the + // browser. The server path (CDN header first, then a capped, cached ipapi.co + // lookup in Helper::get_geo_country()) avoids all three. if ( $this->auto_country ) { - $this->default_country = $this->get_geo_country(); + // Pass the configured default as the fallback so a detection failure + // degrades to the user's chosen country instead of a hardcoded 'us'. + $fallback = ! empty( $this->default_country ) && is_string( $this->default_country ) + ? strtolower( $this->default_country ) + : 'us'; + $this->default_country = Helper::get_geo_country( $fallback ); } $this->set_unique_slug(); $this->set_field_name( $this->unique_slug ); @@ -132,6 +140,9 @@ class="srfm-input-common srfm-input-slug ); ?>" data-required="data_require_attr ); ?>" aria-required="data_require_attr ); ?>" default-country="default_country ); ?>" + auto_country ) { ?> + data-auto-country="true" + enable_country_filter ) { ?> data-enable-country-filter="true" data-country-filter-type="country_filter_type ); ?>" @@ -153,98 +164,4 @@ class="srfm-input-common srfm-input-slug ); ?>" return ob_get_clean(); } - /** - * Detect the visitor's 2-letter country code via server-side IP geolocation. - * - * Calls ipapi.co once per visitor IP and caches the result in a transient for - * 24 hours so subsequent page loads resolve instantly without any API call. - * - * Failure responses (network error, non-200, malformed body, invalid country code) - * are also cached as 'us' for 1 hour to prevent a thundering-herd retry storm - * if ipapi.co goes down or rate-limits us. - * - * Private/reserved IPs (e.g., 10.x, 192.168.x, 127.0.0.1, ::1) are rejected up - * front โ€” ipapi.co cannot geolocate them, and accepting them would let spoofed - * X-Forwarded-For headers flood the transient cache. - * - * A site-wide hourly cap (default 40, filterable via `srfm_geo_api_hourly_cap`) - * bounds outbound calls so a determined attacker can't exhaust the ipapi free-tier - * quota (1,000/day) by rotating spoofed public IPs. - * - * Note on page caching: When a full-page cache plugin is active, the HTML - * (including default-country) is served from cache. The first visitor's country - * is baked into the cached page. This is an acceptable tradeoff โ€” the alternative - * (client-side fetch) caused CORS failures and 429 rate limits. Sites needing - * per-visitor precision can set a specific default country per field. - * - * @since 2.8.0 - * @return string Lowercase 2-letter country code, defaults to 'us'. - */ - private function get_geo_country() { - $ip = Helper::get_visitor_ip(); - if ( empty( $ip ) ) { - return 'us'; - } - - // Reject private/reserved IPs: ipapi.co returns "Reserved IP Address" for them, - // and accepting them would let spoofed X-Forwarded-For headers flood the cache. - if ( ! filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE ) ) { - return 'us'; - } - - $cache_key = 'srfm_geo_' . md5( $ip ); - $cached = get_transient( $cache_key ); - if ( is_string( $cached ) && '' !== $cached ) { - return $cached; - } - - // Site-wide hourly cap on outbound ipapi calls. The counter rolls over every hour - // (key includes YmdH) so we never need to explicitly reset it. Default 40 stays - // well under ipapi's 1,000/day free tier; paid-tier sites can raise via filter. - $quota_key = 'srfm_geo_quota_' . gmdate( 'YmdH' ); - $quota_cap = Helper::get_integer_value( apply_filters( 'srfm_geo_api_hourly_cap', 40 ) ); - $count = Helper::get_integer_value( get_transient( $quota_key ) ); - if ( $count >= $quota_cap ) { - set_transient( $cache_key, 'us', HOUR_IN_SECONDS ); - return 'us'; - } - set_transient( $quota_key, $count + 1, HOUR_IN_SECONDS ); - - // ipapi.co's /json/ endpoint geolocates the *caller's* IP. Since this request - // originates from the WordPress server (not the visitor's browser), we must - // pass the visitor's IP explicitly via /{ip}/json/ โ€” otherwise ipapi.co - // returns the hosting datacenter's country for every visitor. - $url = 'https://ipapi.co/' . rawurlencode( $ip ) . '/json/'; - $response = wp_remote_get( - $url, - [ - 'timeout' => 3, - 'user-agent' => 'SureForms/' . SRFM_VER . ' (+https://sureforms.com)', - ] - ); - - if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) { - set_transient( $cache_key, 'us', HOUR_IN_SECONDS ); - return 'us'; - } - - $body = json_decode( wp_remote_retrieve_body( $response ), true ); - - if ( ! is_array( $body ) || empty( $body['country_code'] ) || ! is_string( $body['country_code'] ) ) { - set_transient( $cache_key, 'us', HOUR_IN_SECONDS ); - return 'us'; - } - - $country = strtolower( $body['country_code'] ); - - // Validate the external API response is a valid 2-letter country code. - if ( ! preg_match( '/^[a-z]{2}$/', $country ) ) { - set_transient( $cache_key, 'us', HOUR_IN_SECONDS ); - return 'us'; - } - - set_transient( $cache_key, $country, DAY_IN_SECONDS ); - - return $country; - } } diff --git a/inc/frontend-assets.php b/inc/frontend-assets.php index 1eaa612eb..a5c05bb39 100644 --- a/inc/frontend-assets.php +++ b/inc/frontend-assets.php @@ -266,6 +266,18 @@ public function enqueue_srfm_script( $block_type, $attr ) { $block_dependencies = [ SRFM_SLUG . "-{$block_name}-intl-input-deps" ]; } wp_enqueue_script( SRFM_SLUG . "-{$block_name}", $js_uri . $block_name . $file_prefix . '.js', $block_dependencies, SRFM_VER, true ); + + if ( 'phone' === $block_name ) { + // Geo-country endpoint for per-visitor auto country detection. + // Built with rest_url() so it is correct regardless of permalink structure. + wp_localize_script( + SRFM_SLUG . "-{$block_name}", + 'srfm_phone_data', + [ + 'geo_endpoint' => esc_url_raw( rest_url( 'sureforms/v1/geo-country' ) ), + ] + ); + } } if ( 'input' === $block_name && isset( $attr['inputMask'] ) && 'none' !== $attr['inputMask'] ) { diff --git a/inc/helper.php b/inc/helper.php index 130a2354a..9cef03a61 100644 --- a/inc/helper.php +++ b/inc/helper.php @@ -1806,8 +1806,18 @@ public static function sureforms_get_integration() { $logo_starter_templates = file_get_contents( plugin_dir_path( SRFM_FILE ) . 'images/starterTemplates.svg' ); $logo_sure_rank = file_get_contents( plugin_dir_path( SRFM_FILE ) . 'images/surerank.svg' ); $logo_sure_contact = file_get_contents( plugin_dir_path( SRFM_FILE ) . 'images/surecontact.svg' ); + $logo_sure_donation = file_get_contents( plugin_dir_path( SRFM_FILE ) . 'images/suredonation.svg' ); $integrations = [ + 'sure_donation' => [ + 'title' => __( 'SureDonation', 'sureforms' ), + 'singleLineDescription' => __( 'Start Collecting Donations Today', 'sureforms' ), + 'subtitle' => __( 'Want to accept donations too? SureDonation makes it easy to collect contributions right on your WordPress site.', 'sureforms' ), + 'status' => self::get_plugin_status( 'suredonation/suredonation.php' ), + 'slug' => 'suredonation', + 'path' => 'suredonation/suredonation.php', + 'logo' => self::encode_svg( is_string( $logo_sure_donation ) ? $logo_sure_donation : '' ), + ], 'sure_contact' => [ 'title' => __( 'SureContact', 'sureforms' ), 'singleLineDescription' => __( 'Turn Emails Into Revenue with a CRM Built for Your Website!', 'sureforms' ), @@ -2436,4 +2446,199 @@ public static function get_visitor_ip() { return ''; } + /** + * Detect the visitor's 2-letter country code via server-side IP geolocation. + * + * Prefers a CDN/server-provided country header (Cloudflare, CloudFront, mod_geoip) + * when present โ€” free, instant and cache-safe. Otherwise calls ipapi.co once per + * visitor IP and caches the result in a transient for 24 hours so subsequent + * lookups for the same IP resolve instantly. Failures are cached for a short TTL + * (see get_geo_failure_ttl()) to avoid retry storms while still self-healing, and + * a site-wide hourly cap (filterable via `srfm_geo_api_hourly_cap`, default 40) + * bounds outbound calls. Private/reserved IPs are rejected up front. + * + * Intended to be called per-visitor (e.g. via the geo-country REST route) so + * the result is correct on full-page-cached sites instead of being baked into + * the cached HTML. + * + * Local testing: private/loopback IPs (e.g. 127.0.0.1) cannot be geolocated, so + * inject a public IP via the `srfm_visitor_ip` filter to exercise detection: + * + * add_filter( 'srfm_visitor_ip', static fn() => '8.8.8.8' ); // US; try 1.1.1.1 etc. + * + * @param string $fallback Country code returned when detection is unavailable. + * @since 2.11.1 + * @return string Lowercase 2-letter country code. + */ + public static function get_geo_country( $fallback = 'us' ) { + // Prefer a CDN/server-provided country header โ€” free, instant, per-visitor + // and cache-safe. It is independent of the connecting IP (it still resolves + // when the visitor IP is private/loopback, e.g. local dev or behind a + // proxy), so it must be checked before the IP-based path below. + $cdn_country = self::get_cdn_country(); + if ( '' !== $cdn_country ) { + return $cdn_country; + } + + $ip = self::get_visitor_ip(); + if ( empty( $ip ) ) { + return $fallback; + } + + // Reject private/reserved IPs: ipapi.co cannot geolocate them, and accepting + // them would let spoofed X-Forwarded-For headers flood the transient cache. + if ( ! filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE ) ) { + return $fallback; + } + + // Versioned key (v2) so stale failure transients written by older code + // (which used the byte-identical 'srfm_geo_' key and a 1h TTL) don't shadow + // the current CDN/fallback logic for the failure-TTL window after an upgrade. + $cache_key = 'srfm_geo_v2_' . md5( $ip ); + $cached = get_transient( $cache_key ); + if ( is_string( $cached ) && '' !== $cached ) { + return $cached; + } + + // Site-wide hourly cap on outbound ipapi calls; the counter rolls over + // every hour (key includes YmdH) so it never needs an explicit reset. + $quota_key = 'srfm_geo_quota_' . gmdate( 'YmdH' ); + $quota_cap = self::get_integer_value( apply_filters( 'srfm_geo_api_hourly_cap', 40 ) ); + $count = self::get_integer_value( get_transient( $quota_key ) ); + if ( $count >= $quota_cap ) { + self::srfm_log( $quota_cap, 'SRFM geo lookup skipped (hourly cap reached):' ); + // Do NOT cache a per-IP transient here: the hourly counter already + // blocks outbound calls, and writing per IP is the one path not bounded + // by the cap โ€” it would let spoofed X-Forwarded-For headers churn + // wp_options / the object cache under sustained traffic. + return $fallback; + } + set_transient( $quota_key, $count + 1, HOUR_IN_SECONDS ); + + // Pass the visitor's IP explicitly via /{ip}/json/ โ€” the request originates + // from the server, so the bare /json/ endpoint would return the host's country. + $url = 'https://ipapi.co/' . rawurlencode( $ip ) . '/json/'; + + // ipapi.co's free (keyless) tier is heavily rate-limited, so unauthenticated + // lookups are best-effort and often fail to the configured fallback. Sites + // that need reliable IP-based detection can supply a paid ipapi.co key via + // this filter; CDN-fronted sites resolve earlier via get_cdn_country() and + // never reach this call. + $api_key = self::get_string_value( apply_filters( 'srfm_ipapi_api_key', '' ) ); + if ( '' !== $api_key ) { + $url = add_query_arg( 'key', rawurlencode( $api_key ), $url ); + } + + $response = wp_remote_get( + $url, + [ + 'timeout' => 3, + 'user-agent' => 'SureForms/' . SRFM_VER . ' (+https://sureforms.com)', + ] + ); + + if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) { + $detail = is_wp_error( $response ) ? $response->get_error_message() : wp_remote_retrieve_response_code( $response ); + self::srfm_log( $detail, 'SRFM geo lookup failed (transport):' ); + set_transient( $cache_key, $fallback, self::get_geo_failure_ttl() ); + return $fallback; + } + + $body = json_decode( wp_remote_retrieve_body( $response ), true ); + + // ipapi.co's free tier returns HTTP 200 with a JSON error body + // (e.g. {"error":true,"reason":"RateLimited"}) when throttled โ€” treat as a failure. + if ( is_array( $body ) && ! empty( $body['error'] ) ) { + $reason = ! empty( $body['reason'] ) && is_string( $body['reason'] ) ? $body['reason'] : 'unknown'; + self::srfm_log( $reason, 'SRFM geo lookup failed (ipapi error):' ); + set_transient( $cache_key, $fallback, self::get_geo_failure_ttl() ); + return $fallback; + } + + if ( ! is_array( $body ) || empty( $body['country_code'] ) || ! is_string( $body['country_code'] ) ) { + self::srfm_log( wp_remote_retrieve_response_code( $response ), 'SRFM geo lookup failed (no country_code):' ); + set_transient( $cache_key, $fallback, self::get_geo_failure_ttl() ); + return $fallback; + } + + $country = strtolower( $body['country_code'] ); + + // Validate the external API response is a valid 2-letter country code. + if ( ! preg_match( '/^[a-z]{2}$/', $country ) ) { + self::srfm_log( $country, 'SRFM geo lookup failed (invalid country code):' ); + set_transient( $cache_key, $fallback, self::get_geo_failure_ttl() ); + return $fallback; + } + + set_transient( $cache_key, $country, DAY_IN_SECONDS ); + + return $country; + } + + /** + * Read a visitor country code from a CDN / server geo header, if present. + * + * Many hosts sit behind Cloudflare, CloudFront or a geo-aware web server that + * injects the visitor's country as a request header. This is free, instant, + * per-visitor and works on full-page-cached sites, so we prefer it over an + * outbound API call. Returns '' when no usable header is present. + * + * NOTE: these headers are client-spoofable when the site is NOT actually behind + * the named CDN/proxy. The value is used only as a phone-field UI default (the + * pre-selected flag), never for access control, so spoofing has no security + * impact here โ€” at worst a visitor sees a different default country. + * + * @since 2.11.1 + * @return string Lowercase 2-letter country code, or '' when unavailable. + */ + private static function get_cdn_country() { + $headers = [ + 'HTTP_CF_IPCOUNTRY', // Cloudflare. + 'HTTP_CLOUDFRONT_VIEWER_COUNTRY', // AWS CloudFront. + 'GEOIP_COUNTRY_CODE', // Apache/Nginx mod_geoip / MaxMind. + 'HTTP_X_GEO_COUNTRY', // Some CDNs / reverse proxies. + 'HTTP_X_COUNTRY_CODE', // Some CDNs. + ]; + + foreach ( $headers as $header ) { + if ( empty( $_SERVER[ $header ] ) ) { + continue; + } + + // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Validated by the regex below. + $code = strtolower( trim( sanitize_text_field( wp_unslash( $_SERVER[ $header ] ) ) ) ); + + // Cloudflare sends 'xx' for unknown and 't1' for Tor; reject non-ISO values. + if ( preg_match( '/^[a-z]{2}$/', $code ) && 'xx' !== $code && 't1' !== $code ) { + return $code; + } + } + + /** + * Filters the CDN-derived visitor country code, before the ipapi.co fallback. + * + * Lets sites short-circuit detection with a server-side country code (e.g. + * from a custom header) without any outbound API call. + * + * @since 2.11.1 + * + * @param string $code Lowercase 2-letter country code, or '' if none found. + */ + return apply_filters( 'srfm_cdn_country', '' ); + } + + /** + * TTL (in seconds) for caching a failed geo lookup. + * + * Short by default so a transient blip (rate-limit, timeout) self-heals on the + * next visit instead of pinning the fallback country for a full hour, while + * still preventing per-request retry storms. Filterable via `srfm_geo_failure_ttl`. + * + * @since 2.11.1 + * @return int + */ + private static function get_geo_failure_ttl() { + return self::get_integer_value( apply_filters( 'srfm_geo_failure_ttl', 5 * MINUTE_IN_SECONDS ) ); + } + } diff --git a/inc/payments/front-end.php b/inc/payments/front-end.php index df9f8878e..bd82eb39c 100644 --- a/inc/payments/front-end.php +++ b/inc/payments/front-end.php @@ -798,6 +798,17 @@ public function verify_stripe_subscription_intent_and_save( $subscription_value, $form_id = isset( $form_data['form-id'] ) && ! empty( $form_data['form-id'] ) ? $form_data['form-id'] : 0; $subscription_status = isset( $subscription['status'] ) && ! empty( $subscription['status'] ) && is_string( $subscription['status'] ) ? $subscription['status'] : ''; + // Defense-in-depth: re-validate the amount Stripe actually invoiced against the form's + // server-side configuration. The recurring price is the invoiced amount, so an + // underpayment here would otherwise repeat every billing cycle. + $charged_amount = Stripe_Helper::amount_from_stripe_format( is_numeric( $amount ) ? (int) $amount : 0, is_string( $currency ) ? $currency : 'usd' ); + $charge_validation = Payment_Helper::validate_amount_against_config( $block_id, is_numeric( $form_id ) ? (int) $form_id : 0, $form_data, $charged_amount, 'subscription' ); + if ( false === $charge_validation['valid'] ) { + return [ + 'error' => $charge_validation['message'], + ]; + } + $invoice_status = isset( $paid_invoice['status'] ) && ! empty( $paid_invoice['status'] ) && is_string( $paid_invoice['status'] ) ? $paid_invoice['status'] : ''; // Extract customer data. @@ -1225,6 +1236,16 @@ private function verify_stripe_payment_intent_and_save( $payment_value, $payment $confirm_payment_currency = is_array( $confirmed_payment_intent ) && isset( $confirmed_payment_intent['currency'] ) && ! empty( $confirmed_payment_intent['currency'] ) ? (string) $confirmed_payment_intent['currency'] : 'usd'; $confirm_payment_id = is_array( $confirmed_payment_intent ) && isset( $confirmed_payment_intent['id'] ) && ! empty( $confirmed_payment_intent['id'] ) ? (string) $confirmed_payment_intent['id'] : ''; + // Defense-in-depth: re-validate the amount Stripe actually charged against the form's + // server-side configuration โ€” not only the amount recorded when the intent was created. + $charged_amount = Stripe_Helper::amount_from_stripe_format( $confirm_payment_amount, $confirm_payment_currency ); + $charge_validation = Payment_Helper::validate_amount_against_config( $block_id, $form_id, $form_data, $charged_amount, 'one-time' ); + if ( false === $charge_validation['valid'] ) { + return [ + 'error' => $charge_validation['message'], + ]; + } + // Extract customer data. $customer_data = $this->extract_customer_data( $payment_value ); diff --git a/inc/payments/payment-helper.php b/inc/payments/payment-helper.php index 13843f38e..fd120e352 100644 --- a/inc/payments/payment-helper.php +++ b/inc/payments/payment-helper.php @@ -777,6 +777,25 @@ public static function verify_payment_intent( $block_id, $payment_intent_id, $fo ]; } + /** + * Validate an arbitrary amount against the form's server-side payment configuration. + * + * Public wrapper around the amount validator so the submission flow can re-check the amount + * Stripe actually charged (defense-in-depth) โ€” not only the amount recorded when the intent was + * created. + * + * @param string $block_id Block identifier. + * @param int $form_id Form post ID. + * @param array $form_data Submitted form data. + * @param float $amount Amount to validate (decimal, in the form currency). + * @param string $active_type Optional. 'one-time' or 'subscription' for "both" mode resolution. + * @since 2.11.1 + * @return array Validation result with 'valid' (bool) and 'message' (string) keys. + */ + public static function validate_amount_against_config( $block_id, $form_id, $form_data, $amount, $active_type = '' ) { + return self::validate_payment_intent_amount( $block_id, $form_id, $form_data, $amount, $active_type ); + } + /** * Delete payment intent metadata from transient. * @@ -810,6 +829,37 @@ public static function get_currency_sign_position() { return ! empty( $result ) && is_string( $result ) ? $result : 'left'; } + /** + * Get a submitted form value by field slug. + * + * Matches the SureForms field-name convention `{block}-{block_id}-lbl-{label}-{slug}` by + * suffix, regardless of block type. Used to resolve `{form:slug}` tokens when recomputing a + * calculation server-side. Returns null when the slug is not present in the submission. + * + * @param string $slug The field slug to look up. + * @param array $form_data Submitted form data. + * @since 2.11.1 + * @return mixed|null The submitted value, or null when not found. + */ + public static function get_submitted_value_by_slug( $slug, $form_data ) { + if ( empty( $slug ) || ! is_string( $slug ) || ! is_array( $form_data ) ) { + return null; + } + + $suffix = '-' . $slug; + foreach ( $form_data as $field_key => $field_value ) { + if ( ! is_string( $field_key ) || false === strpos( $field_key, '-lbl-' ) ) { + continue; + } + + if ( substr( $field_key, -strlen( $suffix ) ) === $suffix ) { + return $field_value; + } + } + + return null; + } + /** * Validate dynamic amount field from dropdown or multi-choice. * @@ -1016,14 +1066,61 @@ private static function validate_payment_intent_amount( $block_id, $form_id, $fo $dynamic_amount_field_block_name = $resolved_config['variable_amount_field_block_name'] ?? ''; $variable_amount_field_slug = $resolved_config['variable_amount_field'] ?? ''; - // Skipping if it is old form configuration. + // "Variant B": legacy/stale config may not have recorded the amount-source field + // (empty source reference). Without it we cannot derive a server-side expected + // amount. First try to recover it by refreshing the block config from the form's + // current content โ€” forms saved with current code record the source โ€” which + // self-heals legacy forms whose source field still exists. if ( empty( $dynamic_amount_field_block_name ) || empty( $variable_amount_field_slug ) ) { + $refreshed_config = self::refresh_block_config( $form_id ); + if ( is_array( $refreshed_config ) && isset( $refreshed_config[ $block_id ] ) && is_array( $refreshed_config[ $block_id ] ) ) { + $block_config = $refreshed_config; + $resolved_config = self::resolve_payment_config_for_active_type( $block_config[ $block_id ], $active_type ); + $dynamic_amount_field_block_name = $resolved_config['variable_amount_field_block_name'] ?? ''; + $variable_amount_field_slug = $resolved_config['variable_amount_field'] ?? ''; + } + } + + // The source still cannot be identified (e.g. the amount-source field was deleted from + // the form while the payment amount type is still "variable", so there is no field-level + // config left to derive an expected amount from). + // + // Security: this branch previously returned a valid result unconditionally for such + // forms, which allowed an unauthenticated attacker to pay any amount (down to 1 cent + // when the form had no minimum-amount floor). + // + // If the admin configured a positive minimum amount we enforce it as the authoritative + // lower bound โ€” the only server-side guarantee available for such a form โ€” instead of + // rejecting outright. This keeps legacy forms (whose source field still has a floor) + // working without requiring a re-save. With no positive floor there is nothing safe to + // validate against, so we MUST fail safe and reject to avoid reopening the bypass. + if ( empty( $dynamic_amount_field_block_name ) || empty( $variable_amount_field_slug ) ) { + $minimum_amount = isset( $resolved_config['minimum_amount'] ) ? floatval( $resolved_config['minimum_amount'] ) : 0; + + if ( $minimum_amount > 0 ) { + if ( $payment_amount < $minimum_amount ) { + return [ + 'valid' => false, + /* translators: %1$s: minimum amount, %2$s: payment amount */ + 'message' => sprintf( __( 'Payment amount below minimum. Minimum: %1$s, received %2$s.', 'sureforms' ), $minimum_amount, $payment_amount ), + ]; + } + + return [ + 'valid' => true, + 'message' => '', + ]; + } + return [ - 'valid' => true, - 'message' => '', + 'valid' => false, + 'message' => __( 'Payment amount could not be verified for this form. Please edit and re-save the form, then try again.', 'sureforms' ), ]; } + // The amount source is identified: validate the charged amount against the + // server-derived expected amount for that source. The configured minimum-amount + // floor below is always enforced as an additional lower bound. $submitted_field_value = self::get_form_submitted_value_by_slug_and_block_name( $variable_amount_field_slug, $dynamic_amount_field_block_name, $form_data ); if ( empty( $submitted_field_value ) ) { @@ -1044,76 +1141,106 @@ private static function validate_payment_intent_amount( $block_id, $form_id, $fo ]; } - // To get the expected amount we need to check by the value of the submitted field. we will have the values now we need to check the expected amount in the block config. because block config dropdown/multi-choice has the expected amount in the options. + // The expected amount is read from the server-side option config keyed by the + // submitted selection โ€” the attacker chooses the option, never its price. $get_expected_amount = self::get_amount_by_the_config_options( $submitted_field_value, $variable_amount_block_config ); - // Validate payment amount matches expected amount. - if ( abs( $payment_amount - $get_expected_amount ) > 0.01 ) { - return [ - 'valid' => false, - /* translators: %1$s: expected amount, %2$s: payment amount */ - 'message' => sprintf( __( 'Payment amount mismatch. Expected %1$s, received %2$s.', 'sureforms' ), $get_expected_amount, $payment_amount ), - ]; - } - } elseif ( 'srfm/number' === $dynamic_amount_field_block_name ) { - // Get the block config for the number field to retrieve the format type. - $number_block_config = self::get_block_config_by_name_and_slug( $block_config, $dynamic_amount_field_block_name, $variable_amount_field_slug ); - - if ( empty( $number_block_config ) ) { - return [ - 'valid' => false, - 'message' => __( 'Number field configuration not found.', 'sureforms' ), - ]; - } - - // Get the number format type from the block config (default to 'us-style'). - $number_format_type = isset( $number_block_config['format_type'] ) && ! empty( $number_block_config['format_type'] ) ? $number_block_config['format_type'] : 'us-style'; - - // If submitted_field_value is not string then convert the value to string. - $submitted_field_value = Helper::get_string_value( $submitted_field_value ); - - // Normalize the submitted amount based on the format type. - $converted_payment_amount = self::normalize_amount_by_format( $submitted_field_value, $number_format_type ); - - // Validate that the normalized amount is valid. - if ( ! is_numeric( $converted_payment_amount ) || $converted_payment_amount <= 0 ) { + // Fail safe when the submitted selection doesn't map to a configured + // option value: get_amount_by_the_config_options() returns null, and + // abs( $payment_amount - null ) would coerce null to 0 โ€” reject explicitly + // so the comparison can never be silently weakened by that coercion. + if ( ! is_numeric( $get_expected_amount ) ) { return [ 'valid' => false, - 'message' => __( 'Variable amount field value is required.', 'sureforms' ), + 'message' => __( 'Payment amount could not be verified for this form. Please edit and re-save the form, then try again.', 'sureforms' ), ]; } // Validate payment amount matches expected amount. - if ( abs( $payment_amount - $converted_payment_amount ) > 0.01 ) { + if ( abs( $payment_amount - $get_expected_amount ) > 0.01 ) { return [ 'valid' => false, /* translators: %1$s: expected amount, %2$s: payment amount */ - 'message' => sprintf( __( 'Payment amount mismatch. Expected %1$s, received %2$s.', 'sureforms' ), $converted_payment_amount, $payment_amount ), + 'message' => sprintf( __( 'Payment amount mismatch. Expected %1$s, received %2$s.', 'sureforms' ), $get_expected_amount, $payment_amount ), ]; } - } elseif ( 'srfm/hidden' === $dynamic_amount_field_block_name ) { - // Hidden field values are dynamic โ€” they may be set at runtime via - // URL params, cookies, or JS. Trust the value submitted with the - // form and verify the Stripe-charged amount matches it. - $expected_amount = is_numeric( $submitted_field_value ) ? floatval( $submitted_field_value ) : 0; + } else { + // Number and hidden fields. Their value may be server-determined โ€” a + // configured default value, or a calculation computed from other fields. + // In those cases the expected amount MUST be derived server-side and the + // value submitted with the request must never be trusted as the price. + $variable_amount_block_config = self::get_block_config_by_name_and_slug( $block_config, $dynamic_amount_field_block_name, $variable_amount_field_slug ); - if ( $expected_amount <= 0 ) { + if ( empty( $variable_amount_block_config ) ) { return [ 'valid' => false, - 'message' => __( 'Variable amount field value is required.', 'sureforms' ), + 'message' => __( 'Variable amount field configuration not found.', 'sureforms' ), ]; } - if ( abs( $payment_amount - $expected_amount ) > 0.01 ) { - return [ - 'valid' => false, - /* translators: %1$s: expected amount, %2$s: payment amount */ - 'message' => sprintf( __( 'Payment amount mismatch. Expected %1$s, received %2$s.', 'sureforms' ), $expected_amount, $payment_amount ), - ]; + $expected_amount = self::resolve_server_side_variable_amount( $variable_amount_block_config, $block_config, $form_data ); + + if ( null !== $expected_amount ) { + // Authoritative server-side amount (static default value or a + // server-recomputed calculation). Reject any mismatch. + if ( abs( $payment_amount - floatval( $expected_amount ) ) > 0.01 ) { + return [ + 'valid' => false, + /* translators: %1$s: expected amount, %2$s: payment amount */ + 'message' => sprintf( __( 'Payment amount mismatch. Expected %1$s, received %2$s.', 'sureforms' ), floatval( $expected_amount ), $payment_amount ), + ]; + } + } elseif ( 'srfm/number' === $dynamic_amount_field_block_name ) { + // Calculation-driven number: a null server amount means the formula + // could NOT be recomputed server-side (a referenced field was + // non-numeric, or the formula used something the parser can't + // evaluate). This is NOT "name your price" โ€” we must fail safe and + // reject, never fall back to the client-submitted amount, which + // would reopen the unauthenticated underpayment bypass. + if ( ! empty( $variable_amount_block_config['enableCalculation'] ) ) { + return [ + 'valid' => false, + 'message' => __( 'Payment amount could not be verified for this form. Please edit and re-save the form, then try again.', 'sureforms' ), + ]; + } + + // Plain user-entered number ("name your price"): the amount is the + // customer's own choice, so confirm the charge matches what they entered. + // The minimum-amount floor below guards the lower bound. + $number_format_type = isset( $variable_amount_block_config['format_type'] ) && ! empty( $variable_amount_block_config['format_type'] ) ? $variable_amount_block_config['format_type'] : 'us-style'; + $submitted_field_value = Helper::get_string_value( $submitted_field_value ); + $converted_payment_amount = self::normalize_amount_by_format( $submitted_field_value, $number_format_type ); + + if ( ! is_numeric( $converted_payment_amount ) || $converted_payment_amount <= 0 ) { + return [ + 'valid' => false, + 'message' => __( 'Variable amount field value is required.', 'sureforms' ), + ]; + } + + if ( abs( $payment_amount - $converted_payment_amount ) > 0.01 ) { + return [ + 'valid' => false, + /* translators: %1$s: expected amount, %2$s: payment amount */ + 'message' => sprintf( __( 'Payment amount mismatch. Expected %1$s, received %2$s.', 'sureforms' ), $converted_payment_amount, $payment_amount ), + ]; + } } + // Otherwise (e.g. a hidden field whose value could not be resolved + // server-side): do NOT trust the submitted value โ€” fall through to the + // minimum-amount floor below as the only safe guarantee. + // + // In practice this covers the documented dynamic-prefill case: a hidden field + // whose default value is a smart tag (e.g. {get_input:amount}) is stored raw and + // is therefore non-numeric, so resolve_server_side_variable_amount() returns null + // and the charge is validated against the floor only โ€” dynamic prefill keeps + // working. A hidden field with a literal numeric default, by contrast, is treated + // as authoritative above; merchants doing custom JS-driven dynamic pricing must + // supply a server-authoritative amount via the `srfm_server_side_variable_amount` + // filter or a calculation-enabled field rather than relying on the submitted value. } - // All variable amount sources (number, hidden) are subject to the configured minimum amount floor. + // All variable amount sources are subject to the configured minimum amount floor. // Use resolved_config so 'both'-mode forms read the active type's per-type minimum // (oneTimeMinimumAmount / subscriptionMinimumAmount) instead of the unset legacy scalar. $minimum_amount = isset( $resolved_config['minimum_amount'] ) ? floatval( $resolved_config['minimum_amount'] ) : 0; @@ -1134,6 +1261,95 @@ private static function validate_payment_intent_amount( $block_id, $form_id, $fo ]; } + /** + * Force a refresh of the form's stored block configuration from its current content. + * + * Recovers the amount-source field reference for legacy forms whose cached + * _srfm_block_config predates server-side source tracking (an empty + * variable_amount_field_block_name). Re-parses the form blocks and rebuilds the config โ€” + * forms saved with current code record the source โ€” then returns the refreshed config. + * + * @param int $form_id Form post ID. + * @since 2.11.1 + * @return array|null Refreshed block configuration, or null if it cannot be rebuilt. + */ + private static function refresh_block_config( $form_id ) { + if ( ! is_int( $form_id ) || $form_id <= 0 ) { + return null; + } + + $post = get_post( $form_id ); + if ( ! ( $post instanceof \WP_Post ) || empty( $post->post_content ) || ! function_exists( 'parse_blocks' ) ) { + return null; + } + + $blocks = parse_blocks( $post->post_content ); + if ( is_array( $blocks ) && ! empty( $blocks ) ) { + Field_Validation::add_block_config( $blocks, $form_id ); + } + + return Field_Validation::get_or_migrate_block_config_for_legacy_form( $form_id ); + } + + /** + * Resolve the authoritative server-side expected amount for a variable amount source. + * + * The expected amount is ALWAYS derived from server-side configuration โ€” the field's + * configured default value, or (for calculation-enabled fields) a value recomputed by + * SureForms Pro from the submitted inputs. It is NEVER taken from the value submitted with + * the request. Returns null when no authoritative amount can be determined server-side, in + * which case the caller falls back to the configured minimum-amount floor. + * + * @param array $source_config The amount-source field block config (block_name, slug, enableCalculation, defaultValue, calculationFormula, ...). + * @param array $block_config All block configurations for the form. + * @param array $form_data Submitted form data. + * @since 2.11.1 + * @return float|null Expected amount, or null if it cannot be determined server-side. + */ + private static function resolve_server_side_variable_amount( $source_config, $block_config, $form_data ) { + if ( empty( $source_config ) || ! is_array( $source_config ) ) { + return null; + } + + /** + * Compute the authoritative server-side amount for a variable payment source. + * + * SureForms Pro hooks this to recompute a field's calculation formula from the + * submitted field values. Handlers MUST return a numeric value derived only from + * server-side configuration and other submitted inputs โ€” never the raw value of the + * amount field submitted with the request โ€” or null if it cannot be computed. + * + * @since 2.11.1 + * @param float|null $amount The resolved amount. Default null. + * @param array $context Context: source_config, block_config, form_data. + */ + $expected = apply_filters( + 'srfm_server_side_variable_amount', + null, + [ + 'source_config' => $source_config, + 'block_config' => $block_config, + 'form_data' => $form_data, + ] + ); + + if ( is_numeric( $expected ) ) { + return floatval( $expected ); + } + + // Static hidden field: a *literal numeric* configured default value is the server-side + // source of truth and is authoritative. A non-numeric default (e.g. a smart tag such as + // {get_input:amount} stored raw, resolved to a runtime value only at render time) is NOT + // treated as authoritative here โ€” it returns null below so the caller validates against the + // minimum-amount floor instead, preserving the documented dynamic-prefill behavior. + $block_name = $source_config['block_name'] ?? ( $source_config['blockName'] ?? '' ); + if ( 'srfm/hidden' === $block_name && empty( $source_config['enableCalculation'] ) && isset( $source_config['defaultValue'] ) && is_numeric( $source_config['defaultValue'] ) ) { + return floatval( $source_config['defaultValue'] ); + } + + return null; + } + /** * Get amount by matching submitted value with config options. * @@ -1216,7 +1432,12 @@ private static function get_block_config_by_name_and_slug( $block_config, $block continue; } - if ( isset( $config['slug'] ) && $config['slug'] === $slug && isset( $config['block_name'] ) && $config['block_name'] === $block_name ) { + // Core blocks store the block name under 'block_name'; Pro blocks (e.g. the hidden + // field, registered via the srfm_block_config filter) store it under 'blockName'. + // Accept either so Pro-sourced amount fields resolve correctly. + $config_block_name = $config['block_name'] ?? ( $config['blockName'] ?? '' ); + + if ( isset( $config['slug'] ) && $config['slug'] === $slug && $config_block_name === $block_name ) { return $config; } } diff --git a/inc/rest-api.php b/inc/rest-api.php index 43df5c0e0..6d12f4a37 100644 --- a/inc/rest-api.php +++ b/inc/rest-api.php @@ -84,6 +84,32 @@ public function sanitize_boolean_field( $value ) { return filter_var( $value, FILTER_VALIDATE_BOOLEAN ); } + /** + * Return the visitor's detected country code. + * + * Public, read-only โ€” resolves the country for the *current* request's IP via + * Helper::get_geo_country(), so the phone field can fetch it per-visitor and + * work on full-page-cached sites. Outbound geolocation calls are bounded by + * the hourly cap inside Helper::get_geo_country(). + * + * @since 2.11.1 + * @return \WP_REST_Response + */ + public function get_geo_country() { + // Pass an empty fallback so '' unambiguously means "not confidently + // detected" (no CDN header and no successful IP lookup). The frontend then + // falls back to a privacy-safe, network-free Intl guess in the browser. + $country = Helper::get_geo_country( '' ); + + return new \WP_REST_Response( + [ + 'country' => $country, + 'detected' => '' !== $country, + ], + 200 + ); + } + /** * Get the data for generating entries chart. * @@ -1385,6 +1411,14 @@ private function get_endpoints() { 'callback' => [ AI_Auth::get_instance(), 'handle_access_key' ], 'permission_callback' => [ Helper::class, 'get_items_permissions_check' ], ], + // Public route: returns the visitor's detected country code. Called + // per-visitor from the phone field so auto-country detection works + // on full-page-cached sites (the value isn't baked into cached HTML). + 'geo-country' => [ + 'methods' => 'GET', + 'callback' => [ $this, 'get_geo_country' ], + 'permission_callback' => '__return_true', + ], // This route is to get the form submissions for the last 30 days. 'entries-chart-data' => [ 'methods' => 'GET', diff --git a/languages/sureforms.pot b/languages/sureforms.pot index db725dd47..59b0b3ede 100644 --- a/languages/sureforms.pot +++ b/languages/sureforms.pot @@ -2,14 +2,14 @@ # This file is distributed under the GPLv2 or later. msgid "" msgstr "" -"Project-Id-Version: SureForms 2.11.0\n" +"Project-Id-Version: SureForms 2.11.1\n" "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/sureforms\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"POT-Creation-Date: 2026-06-09T04:39:59+00:00\n" +"POT-Creation-Date: 2026-06-16T12:34:04+00:00\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "X-Generator: WP-CLI 2.12.0\n" "X-Domain: sureforms\n" @@ -27,8 +27,7 @@ msgstr "" #: inc/page-builders/elementor/form-widget.php:144 #: inc/page-builders/elementor/form-widget.php:301 #: inc/page-builders/elementor/service-provider.php:74 -#: assets/build/formEditor.js:124035 -#: assets/build/formEditor.js:113466 +#: assets/build/formEditor.js:172 msgid "SureForms" msgstr "" @@ -53,21 +52,17 @@ msgstr "" #: admin/admin.php:404 #: admin/admin.php:405 -#: assets/build/dashboard.js:94011 -#: assets/build/entries.js:67779 -#: assets/build/forms.js:62634 +#: assets/build/dashboard.js:172 +#: assets/build/entries.js:172 +#: assets/build/forms.js:172 #: assets/build/learn.js:172 #: assets/build/page_header.js:172 #: assets/build/partialEntriesEmptyState.js:172 #: assets/build/payments.js:172 #: assets/build/quizEmptyState.js:172 -#: assets/build/settings.js:71730 +#: assets/build/settings.js:172 #: assets/build/surveyEmptyState.js:172 #: assets/build/templatePicker.js:172 -#: assets/build/dashboard.js:79971 -#: assets/build/entries.js:58768 -#: assets/build/forms.js:53794 -#: assets/build/settings.js:63985 msgid "Dashboard" msgstr "" @@ -76,36 +71,27 @@ msgstr "" #: admin/admin.php:855 #: inc/compatibility/multilingual/string-collector.php:148 #: inc/compatibility/multilingual/string-collector.php:216 -#: assets/build/blocks.js:111707 -#: assets/build/dashboard.js:94027 -#: assets/build/entries.js:67795 -#: assets/build/forms.js:62650 +#: assets/build/blocks.js:172 +#: assets/build/dashboard.js:172 +#: assets/build/entries.js:172 +#: assets/build/forms.js:172 #: assets/build/learn.js:172 #: assets/build/page_header.js:172 #: assets/build/partialEntriesEmptyState.js:172 #: assets/build/payments.js:172 #: assets/build/quizEmptyState.js:172 -#: assets/build/settings.js:71746 +#: assets/build/settings.js:172 #: assets/build/surveyEmptyState.js:172 -#: assets/build/blocks.js:105801 -#: assets/build/dashboard.js:79992 -#: assets/build/entries.js:58789 -#: assets/build/forms.js:53815 -#: assets/build/settings.js:64006 msgid "Settings" msgstr "" #: admin/admin.php:475 #: admin/admin.php:476 #: admin/admin.php:2211 -#: assets/build/blocks.js:107421 -#: assets/build/dashboard.js:99338 -#: assets/build/entries.js:70177 -#: assets/build/formEditor.js:120309 -#: assets/build/blocks.js:101841 -#: assets/build/dashboard.js:85649 -#: assets/build/entries.js:61246 -#: assets/build/formEditor.js:109448 +#: assets/build/blocks.js:172 +#: assets/build/dashboard.js:172 +#: assets/build/entries.js:172 +#: assets/build/formEditor.js:172 msgid "Upgrade" msgstr "" @@ -115,20 +101,14 @@ msgstr "" #: admin/admin.php:492 #: admin/admin.php:1085 -#: assets/build/formEditor.js:124588 -#: assets/build/formEditor.js:124593 -#: assets/build/formEditor.js:124600 -#: assets/build/formEditor.js:114164 -#: assets/build/formEditor.js:114168 -#: assets/build/formEditor.js:114180 +#: assets/build/formEditor.js:172 msgid "Quizzes" msgstr "" #: admin/admin.php:494 #: admin/admin.php:527 #: admin/admin.php:560 -#: assets/build/settings.js:76109 -#: assets/build/settings.js:68538 +#: assets/build/settings.js:172 msgid "New" msgstr "" @@ -151,42 +131,32 @@ msgstr "" #: admin/admin.php:653 #: admin/admin.php:654 -#: assets/build/dashboard.js:94031 -#: assets/build/entries.js:67799 -#: assets/build/forms.js:62654 +#: assets/build/dashboard.js:172 +#: assets/build/entries.js:172 +#: assets/build/forms.js:172 #: assets/build/learn.js:172 #: assets/build/page_header.js:172 #: assets/build/partialEntriesEmptyState.js:172 #: assets/build/payments.js:172 #: assets/build/quizEmptyState.js:172 -#: assets/build/settings.js:71750 +#: assets/build/settings.js:172 #: assets/build/surveyEmptyState.js:172 -#: assets/build/dashboard.js:79997 -#: assets/build/entries.js:58794 -#: assets/build/forms.js:53820 -#: assets/build/settings.js:64011 msgid "Learn" msgstr "" #: admin/admin.php:682 #: admin/admin.php:683 #: inc/post-types.php:235 -#: assets/build/dashboard.js:94015 -#: assets/build/entries.js:67783 -#: assets/build/forms.js:62638 +#: assets/build/dashboard.js:172 +#: assets/build/entries.js:172 +#: assets/build/forms.js:172 #: assets/build/learn.js:172 #: assets/build/page_header.js:172 #: assets/build/partialEntriesEmptyState.js:172 #: assets/build/payments.js:172 #: assets/build/quizEmptyState.js:172 -#: assets/build/settings.js:71734 -#: assets/build/settings.js:76551 +#: assets/build/settings.js:172 #: assets/build/surveyEmptyState.js:172 -#: assets/build/dashboard.js:79976 -#: assets/build/entries.js:58773 -#: assets/build/forms.js:53799 -#: assets/build/settings.js:63990 -#: assets/build/settings.js:68988 msgid "Forms" msgstr "" @@ -200,47 +170,31 @@ msgstr "" #: admin/admin.php:701 #: admin/admin.php:1987 #: inc/global-settings/email-summary.php:225 -#: assets/build/dashboard.js:94019 -#: assets/build/dashboard.js:96080 -#: assets/build/entries.js:67787 -#: assets/build/entries.js:72069 -#: assets/build/forms.js:62642 -#: assets/build/forms.js:64782 +#: assets/build/dashboard.js:172 +#: assets/build/entries.js:172 +#: assets/build/forms.js:172 #: assets/build/learn.js:172 #: assets/build/page_header.js:172 #: assets/build/partialEntriesEmptyState.js:172 #: assets/build/payments.js:172 #: assets/build/quizEmptyState.js:172 -#: assets/build/settings.js:71738 +#: assets/build/settings.js:172 #: assets/build/surveyEmptyState.js:172 -#: assets/build/dashboard.js:79981 -#: assets/build/dashboard.js:82383 -#: assets/build/entries.js:58778 -#: assets/build/entries.js:63074 -#: assets/build/forms.js:53804 -#: assets/build/forms.js:55775 -#: assets/build/settings.js:63995 msgid "Entries" msgstr "" #: admin/admin.php:710 #: admin/admin.php:711 -#: assets/build/dashboard.js:94023 -#: assets/build/entries.js:67791 -#: assets/build/forms.js:62646 +#: assets/build/dashboard.js:172 +#: assets/build/entries.js:172 +#: assets/build/forms.js:172 #: assets/build/learn.js:172 #: assets/build/page_header.js:172 #: assets/build/partialEntriesEmptyState.js:172 #: assets/build/payments.js:172 #: assets/build/quizEmptyState.js:172 -#: assets/build/settings.js:71742 -#: assets/build/settings.js:74919 +#: assets/build/settings.js:172 #: assets/build/surveyEmptyState.js:172 -#: assets/build/dashboard.js:79986 -#: assets/build/entries.js:58783 -#: assets/build/forms.js:53809 -#: assets/build/settings.js:64000 -#: assets/build/settings.js:67352 msgid "Payments" msgstr "" @@ -255,36 +209,23 @@ msgid "Activating..." msgstr "" #: admin/admin.php:1015 -#: assets/build/dashboard.js:94201 -#: assets/build/entries.js:67969 -#: assets/build/formEditor.js:120755 -#: assets/build/forms.js:62824 +#: assets/build/dashboard.js:172 +#: assets/build/entries.js:172 +#: assets/build/formEditor.js:172 +#: assets/build/forms.js:172 #: assets/build/learn.js:172 #: assets/build/page_header.js:172 #: assets/build/partialEntriesEmptyState.js:172 #: assets/build/payments.js:172 #: assets/build/quizEmptyState.js:172 -#: assets/build/settings.js:71920 -#: assets/build/settings.js:78366 +#: assets/build/settings.js:172 #: assets/build/surveyEmptyState.js:172 -#: assets/build/dashboard.js:80237 -#: assets/build/entries.js:59034 -#: assets/build/formEditor.js:109869 -#: assets/build/forms.js:54060 -#: assets/build/settings.js:64251 -#: assets/build/settings.js:71071 msgid "Activated" msgstr "" #: admin/admin.php:1016 -#: assets/build/formEditor.js:120743 -#: assets/build/formEditor.js:120758 -#: assets/build/settings.js:78354 -#: assets/build/settings.js:78369 -#: assets/build/formEditor.js:109856 -#: assets/build/formEditor.js:109873 -#: assets/build/settings.js:71058 -#: assets/build/settings.js:71075 +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 msgid "Activate" msgstr "" @@ -409,11 +350,8 @@ msgstr "" #: admin/admin.php:1986 #: inc/global-settings/email-summary.php:224 -#: assets/build/entries.js:68998 -#: assets/build/entries.js:70250 +#: assets/build/entries.js:172 #: assets/build/payments.js:172 -#: assets/build/entries.js:60078 -#: assets/build/entries.js:61297 msgid "Form Name" msgstr "" @@ -523,8 +461,8 @@ msgstr "" #: inc/abilities/entries/bulk-get-entries.php:172 #: inc/abilities/entries/get-entry.php:121 -#: inc/rest-api.php:767 -#: inc/rest-api.php:910 +#: inc/rest-api.php:793 +#: inc/rest-api.php:936 msgid "Entry not found." msgstr "" @@ -549,7 +487,7 @@ msgstr "" #. translators: %d is the form ID. #: inc/abilities/entries/entry-parser.php:72 #: inc/compatibility/multilingual/string-translator.php:198 -#: inc/rest-api.php:838 +#: inc/rest-api.php:864 #, php-format msgid "SureForms Form #%d" msgstr "" @@ -967,8 +905,7 @@ msgstr "" #: inc/global-settings/email-summary.php:571 #: inc/global-settings/global-settings.php:262 #: inc/global-settings/global-settings.php:689 -#: assets/build/settings.js:76856 -#: assets/build/settings.js:69240 +#: assets/build/settings.js:172 msgid "Monday" msgstr "" @@ -1078,16 +1015,8 @@ msgstr "" #: inc/migrator/importers/gravity-importer.php:289 #: inc/migrator/importers/ninja-importer.php:309 #: inc/migrator/importers/wpforms-importer.php:286 -#: assets/build/blocks.js:107771 -#: assets/build/formEditor.js:127200 -#: assets/build/formEditor.js:127235 -#: assets/build/formEditor.js:128897 -#: assets/build/formEditor.js:129099 -#: assets/build/blocks.js:102089 -#: assets/build/formEditor.js:117103 -#: assets/build/formEditor.js:117152 -#: assets/build/formEditor.js:119120 -#: assets/build/formEditor.js:119254 +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 msgid "Submit" msgstr "" @@ -1121,8 +1050,7 @@ msgid "Hey! It looks like you're creating a form. Build a ready-to-use form in u msgstr "" #: inc/admin/editor-nudge.php:213 -#: assets/build/forms.js:64189 -#: assets/build/forms.js:55223 +#: assets/build/forms.js:172 msgid "Create Form" msgstr "" @@ -1133,8 +1061,8 @@ msgid "You are not allowed to perform this action." msgstr "" #: inc/admin/editor-nudge.php:237 -#: inc/helper.php:2062 -#: inc/helper.php:2070 +#: inc/helper.php:2072 +#: inc/helper.php:2080 msgid "Invalid security token." msgstr "" @@ -1171,20 +1099,20 @@ msgstr "" #: inc/migrator/bootstrap.php:357 #: inc/payments/front-end.php:78 #: inc/payments/front-end.php:263 -#: inc/rest-api.php:98 -#: inc/rest-api.php:157 -#: inc/rest-api.php:323 -#: inc/rest-api.php:355 -#: inc/rest-api.php:377 -#: inc/rest-api.php:482 -#: inc/rest-api.php:573 -#: inc/rest-api.php:618 -#: inc/rest-api.php:667 -#: inc/rest-api.php:716 -#: inc/rest-api.php:749 -#: inc/rest-api.php:888 -#: inc/rest-api.php:961 -#: inc/rest-api.php:1021 +#: inc/rest-api.php:124 +#: inc/rest-api.php:183 +#: inc/rest-api.php:349 +#: inc/rest-api.php:381 +#: inc/rest-api.php:403 +#: inc/rest-api.php:508 +#: inc/rest-api.php:599 +#: inc/rest-api.php:644 +#: inc/rest-api.php:693 +#: inc/rest-api.php:742 +#: inc/rest-api.php:775 +#: inc/rest-api.php:914 +#: inc/rest-api.php:987 +#: inc/rest-api.php:1047 #: inc/single-form-settings/form-settings-api.php:89 msgid "Security verification failed. Please refresh the page and try again." msgstr "" @@ -1222,7 +1150,7 @@ msgstr "" #: inc/forms-data.php:88 #: inc/global-settings/global-settings.php:88 #: inc/global-settings/global-settings.php:630 -#: inc/rest-api.php:177 +#: inc/rest-api.php:203 msgid "Nonce verification failed." msgstr "" @@ -1378,8 +1306,7 @@ msgstr "" #: inc/page-builders/bricks/elements/form-widget.php:508 #: inc/page-builders/elementor/form-widget.php:827 #: inc/post-types.php:1318 -#: assets/build/blocks.js:113925 -#: assets/build/blocks.js:108275 +#: assets/build/blocks.js:172 msgid "This form has been deleted or is unavailable." msgstr "" @@ -1409,16 +1336,8 @@ msgid "Message" msgstr "" #: inc/compatibility/multilingual/string-collector.php:188 -#: assets/build/formEditor.js:121232 -#: assets/build/formEditor.js:121236 -#: assets/build/formEditor.js:125633 -#: assets/build/settings.js:79205 -#: assets/build/settings.js:79209 -#: assets/build/formEditor.js:110358 -#: assets/build/formEditor.js:110362 -#: assets/build/formEditor.js:115238 -#: assets/build/settings.js:71972 -#: assets/build/settings.js:71976 +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 msgid "Subject" msgstr "" @@ -1448,10 +1367,8 @@ msgstr "" #: inc/compatibility/multilingual/string-collector.php:353 #: inc/page-builders/bricks/elements/form-widget.php:115 #: inc/page-builders/elementor/form-widget.php:751 -#: assets/build/blocks.js:114002 -#: assets/build/formEditor.js:128600 -#: assets/build/blocks.js:108413 -#: assets/build/formEditor.js:118840 +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 msgid "Fields" msgstr "" @@ -1466,20 +1383,7 @@ msgid "Label" msgstr "" #: inc/compatibility/multilingual/string-collector.php:464 -#: assets/build/blocks.js:109060 -#: assets/build/blocks.js:109442 -#: assets/build/blocks.js:110115 -#: assets/build/blocks.js:111436 -#: assets/build/blocks.js:113368 -#: assets/build/blocks.js:115156 -#: assets/build/blocks.js:115597 -#: assets/build/blocks.js:103238 -#: assets/build/blocks.js:103603 -#: assets/build/blocks.js:104157 -#: assets/build/blocks.js:105532 -#: assets/build/blocks.js:107651 -#: assets/build/blocks.js:109471 -#: assets/build/blocks.js:109848 +#: assets/build/blocks.js:172 msgid "Placeholder" msgstr "" @@ -1488,8 +1392,7 @@ msgid "Help text" msgstr "" #: inc/compatibility/multilingual/string-collector.php:466 -#: assets/build/blocks.js:109647 -#: assets/build/blocks.js:103786 +#: assets/build/blocks.js:172 msgid "Error message" msgstr "" @@ -1534,62 +1437,53 @@ msgid "Subscription label" msgstr "" #: inc/compatibility/multilingual/string-translator.php:146 -#: assets/build/settings.js:76724 +#: assets/build/settings.js:172 #: modules/gutenberg/build/blocks.js:6 -#: assets/build/settings.js:69150 msgid "Text" msgstr "" #: inc/compatibility/multilingual/string-translator.php:147 #: inc/fields/email-markup.php:79 -#: assets/build/settings.js:76725 -#: assets/build/settings.js:69151 +#: assets/build/settings.js:172 msgid "Email" msgstr "" #: inc/compatibility/multilingual/string-translator.php:148 #: inc/fields/phone-markup.php:79 #: modules/gutenberg/icons/icons-v6-2.php:3665 -#: assets/build/settings.js:76727 -#: assets/build/settings.js:69153 +#: assets/build/settings.js:172 msgid "Phone" msgstr "" #: inc/compatibility/multilingual/string-translator.php:149 #: inc/fields/number-markup.php:111 -#: assets/build/settings.js:76728 -#: assets/build/settings.js:69154 +#: assets/build/settings.js:172 msgid "Number" msgstr "" #: inc/compatibility/multilingual/string-translator.php:150 #: inc/fields/url-markup.php:38 -#: assets/build/formEditor.js:122622 -#: assets/build/settings.js:76726 +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 #: modules/gutenberg/build/blocks.js:9 -#: assets/build/formEditor.js:112032 -#: assets/build/settings.js:69152 msgid "URL" msgstr "" #: inc/compatibility/multilingual/string-translator.php:151 #: inc/fields/textarea-markup.php:111 -#: assets/build/settings.js:76729 -#: assets/build/settings.js:69155 +#: assets/build/settings.js:172 msgid "Textarea" msgstr "" #: inc/compatibility/multilingual/string-translator.php:152 #: inc/fields/address-markup.php:29 -#: assets/build/settings.js:76734 -#: assets/build/settings.js:69160 +#: assets/build/settings.js:172 msgid "Address" msgstr "" #: inc/compatibility/multilingual/string-translator.php:153 #: inc/fields/dropdown-markup.php:85 -#: assets/build/settings.js:76730 -#: assets/build/settings.js:69156 +#: assets/build/settings.js:172 msgid "Dropdown" msgstr "" @@ -1599,8 +1493,7 @@ msgstr "" #: inc/compatibility/multilingual/string-translator.php:155 #: inc/fields/checkbox-markup.php:29 -#: assets/build/settings.js:76732 -#: assets/build/settings.js:69158 +#: assets/build/settings.js:172 msgid "Checkbox" msgstr "" @@ -1611,27 +1504,15 @@ msgstr "" #: inc/compatibility/multilingual/string-translator.php:157 #: inc/page-builders/bricks/elements/form-widget.php:109 #: inc/page-builders/elementor/form-widget.php:699 -#: assets/build/blocks.js:114010 -#: assets/build/formEditor.js:128607 -#: assets/build/blocks.js:108429 -#: assets/build/formEditor.js:118848 +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 msgid "Button" msgstr "" #: inc/compatibility/multilingual/string-translator.php:158 -#: assets/build/blocks.js:125312 -#: assets/build/dashboard.js:101209 -#: assets/build/entries.js:73732 -#: assets/build/formEditor.js:138068 -#: assets/build/forms.js:67766 -#: assets/build/settings.js:83007 +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:2 #: assets/build/templatePicker.js:172 -#: assets/build/blocks.js:120046 -#: assets/build/dashboard.js:87323 -#: assets/build/entries.js:64544 -#: assets/build/formEditor.js:128681 -#: assets/build/forms.js:58466 -#: assets/build/settings.js:75499 msgid "Payment" msgstr "" @@ -1722,33 +1603,22 @@ msgstr "" #: inc/entries.php:729 #: inc/smart-tags.php:128 -#: assets/build/entries.js:68976 -#: assets/build/entries.js:70246 -#: assets/build/entries.js:60051 -#: assets/build/entries.js:61292 +#: assets/build/entries.js:172 msgid "Entry ID" msgstr "" #: inc/entries.php:729 -#: assets/build/formEditor.js:130698 -#: assets/build/formEditor.js:121061 +#: assets/build/formEditor.js:172 msgid "Date" msgstr "" #: inc/entries.php:729 #: inc/payments/payment-history-shortcode.php:318 -#: assets/build/entries.js:68773 -#: assets/build/entries.js:69014 -#: assets/build/entries.js:70253 -#: assets/build/formEditor.js:125629 +#: assets/build/entries.js:172 +#: assets/build/formEditor.js:172 #: assets/build/payments.js:2 #: assets/build/payments.js:172 -#: assets/build/settings.js:76086 -#: assets/build/entries.js:59807 -#: assets/build/entries.js:60098 -#: assets/build/entries.js:61301 -#: assets/build/formEditor.js:115232 -#: assets/build/settings.js:68509 +#: assets/build/settings.js:172 msgid "Status" msgstr "" @@ -1824,11 +1694,8 @@ msgstr "" #: inc/fields/payment-markup.php:247 #: inc/payments/admin/admin-handler.php:969 #: inc/payments/payment-history-shortcode.php:306 -#: assets/build/blocks.js:112472 -#: assets/build/blocks.js:112583 +#: assets/build/blocks.js:172 #: assets/build/payments.js:172 -#: assets/build/blocks.js:106555 -#: assets/build/blocks.js:106708 msgid "Subscription" msgstr "" @@ -1935,8 +1802,7 @@ msgstr "" #: inc/form-restriction.php:188 #: inc/form-restriction.php:189 #: inc/global-settings/global-settings-defaults.php:268 -#: assets/build/formEditor.js:126678 -#: assets/build/formEditor.js:116629 +#: assets/build/formEditor.js:172 msgid "This form is no longer accepting submissions. The submission period has ended." msgstr "" @@ -2039,26 +1905,19 @@ msgid "Captcha validation failed." msgstr "" #: inc/form-submit.php:1196 -#: assets/build/formEditor.js:123884 -#: assets/build/settings.js:75369 -#: assets/build/formEditor.js:113270 -#: assets/build/settings.js:67834 +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 msgid "Google reCAPTCHA" msgstr "" #: inc/form-submit.php:1200 -#: assets/build/formEditor.js:123890 -#: assets/build/settings.js:74878 -#: assets/build/settings.js:75226 -#: assets/build/formEditor.js:113275 -#: assets/build/settings.js:67285 -#: assets/build/settings.js:67696 +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 msgid "hCaptcha" msgstr "" #: inc/form-submit.php:1204 -#: assets/build/settings.js:75479 -#: assets/build/settings.js:67965 +#: assets/build/settings.js:172 msgid "Cloudflare Turnstile" msgstr "" @@ -2092,84 +1951,70 @@ msgstr "" msgid "HCaptcha sitekey verification failed. Please contact your site administrator." msgstr "" -#: inc/frontend-assets.php:288 -#: assets/build/formEditor.js:124970 -#: assets/build/settings.js:80159 -#: assets/build/formEditor.js:114613 -#: assets/build/settings.js:72985 +#: inc/frontend-assets.php:300 +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 msgctxt "Quill heading picker: default paragraph style" msgid "Normal" msgstr "" -#: inc/frontend-assets.php:289 -#: assets/build/formEditor.js:124958 -#: assets/build/settings.js:80147 -#: assets/build/formEditor.js:114607 -#: assets/build/settings.js:72979 +#: inc/frontend-assets.php:301 +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 msgid "Heading 1" msgstr "" -#: inc/frontend-assets.php:290 -#: assets/build/formEditor.js:124960 -#: assets/build/settings.js:80149 -#: assets/build/formEditor.js:114608 -#: assets/build/settings.js:72980 +#: inc/frontend-assets.php:302 +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 msgid "Heading 2" msgstr "" -#: inc/frontend-assets.php:291 -#: assets/build/formEditor.js:124962 -#: assets/build/settings.js:80151 -#: assets/build/formEditor.js:114609 -#: assets/build/settings.js:72981 +#: inc/frontend-assets.php:303 +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 msgid "Heading 3" msgstr "" -#: inc/frontend-assets.php:292 -#: assets/build/formEditor.js:124964 -#: assets/build/settings.js:80153 -#: assets/build/formEditor.js:114610 -#: assets/build/settings.js:72982 +#: inc/frontend-assets.php:304 +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 msgid "Heading 4" msgstr "" -#: inc/frontend-assets.php:293 -#: assets/build/formEditor.js:124966 -#: assets/build/settings.js:80155 -#: assets/build/formEditor.js:114611 -#: assets/build/settings.js:72983 +#: inc/frontend-assets.php:305 +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 msgid "Heading 5" msgstr "" -#: inc/frontend-assets.php:294 -#: assets/build/formEditor.js:124968 -#: assets/build/settings.js:80157 -#: assets/build/formEditor.js:114612 -#: assets/build/settings.js:72984 +#: inc/frontend-assets.php:306 +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 msgid "Heading 6" msgstr "" -#: inc/frontend-assets.php:295 +#: inc/frontend-assets.php:307 msgctxt "Quill link tooltip label" msgid "Visit URL:" msgstr "" -#: inc/frontend-assets.php:296 +#: inc/frontend-assets.php:308 msgctxt "Quill link tooltip label" msgid "Enter link:" msgstr "" -#: inc/frontend-assets.php:297 +#: inc/frontend-assets.php:309 msgctxt "Quill link tooltip action" msgid "Edit" msgstr "" -#: inc/frontend-assets.php:298 +#: inc/frontend-assets.php:310 msgctxt "Quill link tooltip action" msgid "Save" msgstr "" -#: inc/frontend-assets.php:299 +#: inc/frontend-assets.php:311 msgctxt "Quill link tooltip action" msgid "Remove" msgstr "" @@ -2297,8 +2142,7 @@ msgstr "" #: inc/global-settings/global-settings-defaults.php:173 #: inc/global-settings/global-settings.php:586 #: inc/post-types.php:1005 -#: assets/build/settings.js:74220 -#: assets/build/settings.js:66523 +#: assets/build/settings.js:172 #, php-format,js-format msgid "New Form Submission - %s" msgstr "" @@ -2306,14 +2150,12 @@ msgstr "" #: inc/global-settings/global-settings-defaults.php:260 #: inc/global-settings/global-settings.php:425 #: inc/global-settings/global-settings.php:613 -#: assets/build/settings.js:77324 -#: assets/build/settings.js:69749 +#: assets/build/settings.js:172 msgid "This form is now closed as we've received all the entries." msgstr "" #: inc/global-settings/global-settings-defaults.php:267 -#: assets/build/formEditor.js:126669 -#: assets/build/formEditor.js:116603 +#: assets/build/formEditor.js:172 msgid "This form is not yet available. Please check back after the scheduled start time." msgstr "" @@ -2326,16 +2168,14 @@ msgid "Settings Saved Successfully." msgstr "" #: inc/global-settings/global-settings.php:481 -#: assets/build/settings.js:74207 -#: assets/build/settings.js:66509 +#: assets/build/settings.js:172 msgid "Thank you for contacting us! We will be in touch with you shortly." msgstr "" #: inc/global-settings/global-settings.php:528 #: inc/migrator/base-migrator.php:548 #: inc/post-types.php:1081 -#: assets/build/formEditor.js:128930 -#: assets/build/formEditor.js:119154 +#: assets/build/formEditor.js:172 msgid "Thank you" msgstr "" @@ -2350,8 +2190,7 @@ msgid "General Fields" msgstr "" #: inc/gutenberg-hooks.php:119 -#: assets/build/dashboard.js:98935 -#: assets/build/dashboard.js:85147 +#: assets/build/dashboard.js:172 msgid "Advanced Fields" msgstr "" @@ -2377,103 +2216,105 @@ msgstr "" msgid "%s sitekey is missing. Please contact your site administrator." msgstr "" -#: inc/helper.php:1812 +#: inc/helper.php:1813 +msgid "SureDonation" +msgstr "" + +#: inc/helper.php:1814 +msgid "Start Collecting Donations Today" +msgstr "" + +#: inc/helper.php:1815 +msgid "Want to accept donations too? SureDonation makes it easy to collect contributions right on your WordPress site." +msgstr "" + +#: inc/helper.php:1822 msgid "SureContact" msgstr "" -#: inc/helper.php:1813 +#: inc/helper.php:1823 msgid "Turn Emails Into Revenue with a CRM Built for Your Website!" msgstr "" -#: inc/helper.php:1814 +#: inc/helper.php:1824 msgid "Send newsletters, run campaigns, set up automations, manage contacts, and see exactly how much revenue your emails generate, all in one place." msgstr "" -#: inc/helper.php:1821 +#: inc/helper.php:1831 msgid "SureMail" msgstr "" -#: inc/helper.php:1822 +#: inc/helper.php:1832 msgid "Boost Your Email Deliverability Instantly!" msgstr "" -#: inc/helper.php:1823 +#: inc/helper.php:1833 msgid "Access a powerful, easy-to-use email delivery service that ensures your emails land in inboxes, not spam folders. Automate your WordPress email workflows confidently with SureMail." msgstr "" -#: inc/helper.php:1830 -#: assets/build/formEditor.js:120815 -#: assets/build/formEditor.js:124499 -#: assets/build/formEditor.js:128782 -#: assets/build/settings.js:74889 -#: assets/build/settings.js:74894 -#: assets/build/settings.js:78426 -#: assets/build/formEditor.js:109960 -#: assets/build/formEditor.js:113963 -#: assets/build/formEditor.js:119007 -#: assets/build/settings.js:67303 -#: assets/build/settings.js:67309 -#: assets/build/settings.js:71162 +#: inc/helper.php:1840 +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 msgid "OttoKit" msgstr "" -#: inc/helper.php:1831 +#: inc/helper.php:1841 msgid "Automate your WordPress workflows effortlessly." msgstr "" -#: inc/helper.php:1832 +#: inc/helper.php:1842 msgid "Connect your WordPress plugins and favourite apps, automate tasks, and sync data effortlessly using OttoKitโ€™s clean, visual workflow builder โ€” no coding or complex setup required." msgstr "" -#: inc/helper.php:1842 +#: inc/helper.php:1852 msgid "Starter Templates" msgstr "" -#: inc/helper.php:1843 +#: inc/helper.php:1853 msgid "Launch Beautiful Websites in Minutes!" msgstr "" -#: inc/helper.php:1844 +#: inc/helper.php:1854 msgid "Choose from professionally designed templates, import with one click, and customize effortlessly to match your brand." msgstr "" -#: inc/helper.php:1856 +#: inc/helper.php:1866 msgid "Ultimate Addons for Elementor" msgstr "" -#: inc/helper.php:1857 +#: inc/helper.php:1867 msgid "Power Up Elementor to Build Stunning Websites Faster!" msgstr "" -#: inc/helper.php:1858 +#: inc/helper.php:1868 msgid "Enhance Elementor with powerful widgets and templates. Build stunning, high-performing websites faster with creative design elements and seamless customization." msgstr "" -#: inc/helper.php:1866 +#: inc/helper.php:1876 msgid "SureRank" msgstr "" -#: inc/helper.php:1867 +#: inc/helper.php:1877 msgid "Elevate Your SEO and Climb Search Rankings Effortlessly!" msgstr "" -#: inc/helper.php:1868 +#: inc/helper.php:1878 msgid "Boost your website's visibility with smart SEO automation. Optimize content, track keyword performance, and get actionable insights, all inside WordPress." msgstr "" -#: inc/helper.php:2052 +#: inc/helper.php:2062 msgid "Invalid nonce action or name." msgstr "" -#: inc/helper.php:2077 +#: inc/helper.php:2087 msgid "Invalid request type." msgstr "" -#: inc/helper.php:2085 +#: inc/helper.php:2095 msgid "You do not have permission to perform this action." msgstr "" -#: inc/helper.php:2210 +#: inc/helper.php:2220 msgid "Blank Form" msgstr "" @@ -2535,8 +2376,7 @@ msgstr "" #: inc/learn.php:129 #: inc/learn.php:137 #: inc/learn.php:143 -#: assets/build/formEditor.js:122355 -#: assets/build/formEditor.js:111609 +#: assets/build/formEditor.js:172 msgid "Instant Form" msgstr "" @@ -2566,10 +2406,7 @@ msgid "Stay on top of your form submissions with email notifications and the bui msgstr "" #: inc/learn.php:181 -#: assets/build/formEditor.js:125369 -#: assets/build/formEditor.js:125667 -#: assets/build/formEditor.js:114993 -#: assets/build/formEditor.js:115284 +#: assets/build/formEditor.js:172 msgid "Email Notifications" msgstr "" @@ -2644,8 +2481,7 @@ msgstr "" #: inc/migrator/importers/gravity-importer.php:965 #: inc/migrator/importers/wpforms-importer.php:984 -#: assets/build/settings.js:77118 -#: assets/build/settings.js:69553 +#: assets/build/settings.js:172 msgid "Admin Notification" msgstr "" @@ -2697,28 +2533,23 @@ msgstr "" #: inc/page-builders/bricks/elements/form-widget.php:103 #: inc/page-builders/elementor/form-widget.php:639 -#: assets/build/blocks.js:113993 +#: assets/build/blocks.js:172 #: modules/gutenberg/build/blocks.js:8 -#: assets/build/blocks.js:108397 msgid "Layout" msgstr "" #: inc/page-builders/bricks/elements/form-widget.php:135 #: inc/payments/payment-history-shortcode.php:312 -#: assets/build/entries.js:72309 -#: assets/build/formEditor.js:128595 +#: assets/build/entries.js:172 +#: assets/build/formEditor.js:172 #: assets/build/payments.js:2 -#: assets/build/settings.js:76078 -#: assets/build/entries.js:63289 -#: assets/build/formEditor.js:118834 -#: assets/build/settings.js:68500 +#: assets/build/settings.js:172 msgid "Form" msgstr "" #: inc/page-builders/bricks/elements/form-widget.php:138 #: inc/page-builders/elementor/form-widget.php:308 -#: assets/build/dashboard.js:96021 -#: assets/build/dashboard.js:82278 +#: assets/build/dashboard.js:172 msgid "Select Form" msgstr "" @@ -2737,122 +2568,83 @@ msgstr "" #: inc/page-builders/bricks/elements/form-widget.php:167 #: inc/page-builders/elementor/form-widget.php:382 -#: assets/build/blocks.js:113948 -#: assets/build/formEditor.js:128628 -#: assets/build/blocks.js:108318 -#: assets/build/formEditor.js:118876 +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 msgid "Form Theme" msgstr "" #: inc/page-builders/bricks/elements/form-widget.php:170 #: inc/page-builders/elementor/form-widget.php:386 -#: assets/build/blocks.js:113951 -#: assets/build/blocks.js:108322 +#: assets/build/blocks.js:172 msgid "Inherit Form's Original Style" msgstr "" #: inc/page-builders/bricks/elements/form-widget.php:171 #: inc/page-builders/elementor/form-widget.php:387 -#: assets/build/blocks.js:113954 +#: assets/build/blocks.js:172 #: modules/gutenberg/build/blocks.js:4 #: modules/gutenberg/build/blocks.js:6 #: modules/gutenberg/build/blocks.js:8 -#: assets/build/blocks.js:108329 msgid "Default" msgstr "" #: inc/page-builders/bricks/elements/form-widget.php:187 #: inc/page-builders/elementor/form-widget.php:397 -#: assets/build/blocks.js:114462 -#: assets/build/formEditor.js:128378 -#: assets/build/blocks.js:108852 -#: assets/build/formEditor.js:118553 +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 msgid "Primary Color" msgstr "" #: inc/page-builders/bricks/elements/form-widget.php:196 #: inc/page-builders/elementor/form-widget.php:409 -#: assets/build/blocks.js:114474 -#: assets/build/formEditor.js:128397 +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 #: modules/gutenberg/build/blocks.js:6 -#: assets/build/blocks.js:108867 -#: assets/build/formEditor.js:118579 msgid "Text Color" msgstr "" #: inc/page-builders/bricks/elements/form-widget.php:205 #: inc/page-builders/elementor/form-widget.php:421 -#: assets/build/blocks.js:114486 -#: assets/build/blocks.js:108882 +#: assets/build/blocks.js:172 msgid "Text on Primary" msgstr "" #: inc/page-builders/bricks/elements/form-widget.php:214 #: inc/page-builders/elementor/form-widget.php:433 -#: assets/build/blocks.js:114499 -#: assets/build/formEditor.js:128369 +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 #: modules/gutenberg/build/blocks.js:6 #: modules/gutenberg/build/blocks.js:8 -#: assets/build/blocks.js:108898 -#: assets/build/formEditor.js:118540 msgid "Background" msgstr "" #: inc/page-builders/bricks/elements/form-widget.php:222 #: inc/page-builders/elementor/form-widget.php:445 #: inc/payments/payment-history-shortcode.php:313 -#: assets/build/blocks.js:116897 -#: assets/build/blocks.js:117537 -#: assets/build/formEditor.js:130161 -#: assets/build/formEditor.js:131176 +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 #: assets/build/payments.js:172 #: modules/gutenberg/build/blocks.js:6 -#: assets/build/blocks.js:111129 -#: assets/build/blocks.js:112016 -#: assets/build/formEditor.js:120281 -#: assets/build/formEditor.js:121493 msgid "Type" msgstr "" #: inc/page-builders/bricks/elements/form-widget.php:225 #: inc/page-builders/elementor/form-widget.php:449 #: inc/page-builders/elementor/form-widget.php:463 -#: assets/build/blocks.js:116912 -#: assets/build/blocks.js:116936 -#: assets/build/blocks.js:117067 -#: assets/build/formEditor.js:122462 -#: assets/build/formEditor.js:130176 -#: assets/build/formEditor.js:130200 -#: assets/build/formEditor.js:130331 +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 #: modules/gutenberg/build/blocks.js:6 #: modules/gutenberg/build/blocks.js:8 #: modules/gutenberg/build/blocks.js:9 -#: assets/build/blocks.js:111148 -#: assets/build/blocks.js:111180 -#: assets/build/blocks.js:111366 -#: assets/build/formEditor.js:111777 -#: assets/build/formEditor.js:120300 -#: assets/build/formEditor.js:120332 -#: assets/build/formEditor.js:120518 msgid "Color" msgstr "" #: inc/page-builders/bricks/elements/form-widget.php:226 #: inc/page-builders/elementor/form-widget.php:450 #: inc/page-builders/elementor/form-widget.php:483 -#: assets/build/blocks.js:116916 -#: assets/build/blocks.js:116940 -#: assets/build/formEditor.js:128209 -#: assets/build/formEditor.js:128210 -#: assets/build/formEditor.js:130180 -#: assets/build/formEditor.js:130204 +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 #: modules/gutenberg/build/blocks.js:6 -#: assets/build/blocks.js:111153 -#: assets/build/blocks.js:111185 -#: assets/build/formEditor.js:118378 -#: assets/build/formEditor.js:118379 -#: assets/build/formEditor.js:120305 -#: assets/build/formEditor.js:120337 msgid "Gradient" msgstr "" @@ -2862,45 +2654,19 @@ msgstr "" #: inc/page-builders/elementor/form-widget.php:531 #: modules/gutenberg/classes/class-spec-block-config.php:562 #: modules/gutenberg/icons/icons-v6-1.php:5470 -#: assets/build/blocks.js:110858 -#: assets/build/blocks.js:116905 -#: assets/build/blocks.js:116920 -#: assets/build/blocks.js:116944 -#: assets/build/blocks.js:118404 -#: assets/build/formEditor.js:122465 -#: assets/build/formEditor.js:128213 -#: assets/build/formEditor.js:128214 -#: assets/build/formEditor.js:130169 -#: assets/build/formEditor.js:130184 -#: assets/build/formEditor.js:130208 -#: assets/build/formEditor.js:131422 +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 #: modules/gutenberg/build/blocks-placeholder.js:11 #: modules/gutenberg/build/blocks.js:6 #: modules/gutenberg/build/blocks.js:8 #: modules/gutenberg/build/blocks.js:9 -#: assets/build/blocks.js:104917 -#: assets/build/blocks.js:111140 -#: assets/build/blocks.js:111158 -#: assets/build/blocks.js:111190 -#: assets/build/blocks.js:112767 -#: assets/build/formEditor.js:111784 -#: assets/build/formEditor.js:118383 -#: assets/build/formEditor.js:118384 -#: assets/build/formEditor.js:120292 -#: assets/build/formEditor.js:120310 -#: assets/build/formEditor.js:120342 -#: assets/build/formEditor.js:121692 msgid "Image" msgstr "" #: inc/page-builders/bricks/elements/form-widget.php:236 -#: assets/build/blocks.js:117191 -#: assets/build/formEditor.js:122520 -#: assets/build/formEditor.js:130455 +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 #: modules/gutenberg/build/blocks.js:6 -#: assets/build/blocks.js:111593 -#: assets/build/formEditor.js:111881 -#: assets/build/formEditor.js:120745 msgid "Background Color" msgstr "" @@ -2925,89 +2691,58 @@ msgid "Gradient Type" msgstr "" #: inc/page-builders/bricks/elements/form-widget.php:286 -#: assets/build/blocks.js:117545 -#: assets/build/formEditor.js:131184 +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 #: modules/gutenberg/build/blocks.js:6 -#: assets/build/blocks.js:112025 -#: assets/build/formEditor.js:121502 msgid "Linear" msgstr "" #: inc/page-builders/bricks/elements/form-widget.php:287 -#: assets/build/blocks.js:117548 -#: assets/build/formEditor.js:131187 +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 #: modules/gutenberg/build/blocks.js:6 -#: assets/build/blocks.js:112029 -#: assets/build/formEditor.js:121506 msgid "Radial" msgstr "" #: inc/page-builders/bricks/elements/form-widget.php:295 #: inc/page-builders/elementor/form-widget.php:508 -#: assets/build/blocks.js:117575 -#: assets/build/formEditor.js:131214 +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 #: modules/gutenberg/build/blocks.js:6 -#: assets/build/blocks.js:112061 -#: assets/build/formEditor.js:121538 msgid "Angle" msgstr "" #: inc/page-builders/bricks/elements/form-widget.php:316 #: inc/page-builders/elementor/form-widget.php:547 -#: assets/build/blocks.js:117095 -#: assets/build/blocks.js:117266 -#: assets/build/formEditor.js:130359 -#: assets/build/formEditor.js:130530 +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 #: modules/gutenberg/build/blocks.js:6 #: modules/gutenberg/build/blocks.js:9 -#: assets/build/blocks.js:111414 -#: assets/build/blocks.js:111708 -#: assets/build/formEditor.js:120566 -#: assets/build/formEditor.js:120860 msgid "Size" msgstr "" #: inc/page-builders/bricks/elements/form-widget.php:319 #: inc/page-builders/elementor/form-widget.php:551 -#: assets/build/blocks.js:116951 -#: assets/build/blocks.js:116965 -#: assets/build/formEditor.js:130215 -#: assets/build/formEditor.js:130229 +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 #: modules/gutenberg/build/blocks.js:8 -#: assets/build/blocks.js:111201 -#: assets/build/blocks.js:111221 -#: assets/build/formEditor.js:120353 -#: assets/build/formEditor.js:120373 msgid "Cover" msgstr "" #: inc/page-builders/bricks/elements/form-widget.php:320 #: inc/page-builders/elementor/form-widget.php:552 -#: assets/build/blocks.js:116954 -#: assets/build/blocks.js:116968 -#: assets/build/formEditor.js:130218 -#: assets/build/formEditor.js:130232 +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 #: modules/gutenberg/build/blocks.js:8 -#: assets/build/blocks.js:111205 -#: assets/build/blocks.js:111225 -#: assets/build/formEditor.js:120357 -#: assets/build/formEditor.js:120377 msgid "Contain" msgstr "" #: inc/page-builders/bricks/elements/form-widget.php:321 #: inc/page-builders/elementor/form-widget.php:553 -#: assets/build/blocks.js:116948 -#: assets/build/blocks.js:116962 -#: assets/build/formEditor.js:130212 -#: assets/build/formEditor.js:130226 -#: assets/build/settings.js:75451 +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 #: modules/gutenberg/build/blocks.js:8 -#: assets/build/blocks.js:111197 -#: assets/build/blocks.js:111217 -#: assets/build/formEditor.js:120349 -#: assets/build/formEditor.js:120369 -#: assets/build/settings.js:67933 msgid "Auto" msgstr "" @@ -3078,37 +2813,17 @@ msgstr "" #: inc/page-builders/elementor/form-widget.php:591 #: inc/page-builders/elementor/form-widget.php:596 #: modules/gutenberg/icons/icons-v6-2.php:4659 -#: assets/build/blocks.js:117073 -#: assets/build/blocks.js:117083 -#: assets/build/blocks.js:117244 -#: assets/build/blocks.js:117254 -#: assets/build/formEditor.js:130337 -#: assets/build/formEditor.js:130347 -#: assets/build/formEditor.js:130508 -#: assets/build/formEditor.js:130518 +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 #: modules/gutenberg/build/blocks.js:8 -#: assets/build/blocks.js:111374 -#: assets/build/blocks.js:111392 -#: assets/build/blocks.js:111669 -#: assets/build/blocks.js:111686 -#: assets/build/formEditor.js:120526 -#: assets/build/formEditor.js:120544 -#: assets/build/formEditor.js:120821 -#: assets/build/formEditor.js:120838 msgid "Repeat" msgstr "" #: inc/page-builders/bricks/elements/form-widget.php:351 #: inc/page-builders/elementor/form-widget.php:595 -#: assets/build/blocks.js:117080 -#: assets/build/blocks.js:117251 -#: assets/build/formEditor.js:130344 -#: assets/build/formEditor.js:130515 +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 #: modules/gutenberg/build/blocks.js:8 -#: assets/build/blocks.js:111385 -#: assets/build/blocks.js:111679 -#: assets/build/formEditor.js:120537 -#: assets/build/formEditor.js:120831 msgid "No Repeat" msgstr "" @@ -3124,41 +2839,23 @@ msgstr "" #: inc/page-builders/bricks/elements/form-widget.php:362 #: inc/page-builders/elementor/form-widget.php:611 -#: assets/build/blocks.js:117020 -#: assets/build/blocks.js:117228 -#: assets/build/formEditor.js:130284 -#: assets/build/formEditor.js:130492 -#: assets/build/blocks.js:111292 -#: assets/build/blocks.js:111646 -#: assets/build/formEditor.js:120444 -#: assets/build/formEditor.js:120798 +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 msgid "Attachment" msgstr "" #: inc/page-builders/bricks/elements/form-widget.php:365 #: inc/page-builders/elementor/form-widget.php:615 #: modules/gutenberg/icons/icons-v6-3.php:213 -#: assets/build/blocks.js:117030 -#: assets/build/blocks.js:117238 -#: assets/build/formEditor.js:130294 -#: assets/build/formEditor.js:130502 -#: assets/build/blocks.js:111307 -#: assets/build/blocks.js:111661 -#: assets/build/formEditor.js:120459 -#: assets/build/formEditor.js:120813 +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 msgid "Scroll" msgstr "" #: inc/page-builders/bricks/elements/form-widget.php:366 #: inc/page-builders/elementor/form-widget.php:616 -#: assets/build/blocks.js:117027 -#: assets/build/blocks.js:117235 -#: assets/build/formEditor.js:130291 -#: assets/build/formEditor.js:130499 -#: assets/build/blocks.js:111303 -#: assets/build/blocks.js:111657 -#: assets/build/formEditor.js:120455 -#: assets/build/formEditor.js:120809 +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 msgid "Fixed" msgstr "" @@ -3182,97 +2879,67 @@ msgstr "" #: inc/page-builders/bricks/elements/form-widget.php:432 #: inc/page-builders/elementor/form-widget.php:716 -#: assets/build/blocks.js:114698 -#: assets/build/blocks.js:121414 -#: assets/build/formEditor.js:128544 -#: assets/build/formEditor.js:133957 +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 #: modules/gutenberg/build/blocks.js:6 #: modules/gutenberg/build/blocks.js:8 #: modules/gutenberg/build/blocks.js:9 -#: assets/build/blocks.js:109117 -#: assets/build/blocks.js:115957 -#: assets/build/formEditor.js:118759 -#: assets/build/formEditor.js:124442 msgid "Left" msgstr "" #: inc/page-builders/bricks/elements/form-widget.php:433 #: inc/page-builders/elementor/form-widget.php:720 -#: assets/build/blocks.js:114704 -#: assets/build/formEditor.js:128550 +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 #: modules/gutenberg/build/blocks.js:6 #: modules/gutenberg/build/blocks.js:8 #: modules/gutenberg/build/blocks.js:9 -#: assets/build/blocks.js:109124 -#: assets/build/formEditor.js:118766 msgid "Center" msgstr "" #: inc/page-builders/bricks/elements/form-widget.php:434 #: inc/page-builders/elementor/form-widget.php:724 -#: assets/build/blocks.js:114710 -#: assets/build/blocks.js:121410 -#: assets/build/formEditor.js:128556 -#: assets/build/formEditor.js:133953 +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 #: modules/gutenberg/build/blocks.js:6 #: modules/gutenberg/build/blocks.js:8 #: modules/gutenberg/build/blocks.js:9 -#: assets/build/blocks.js:109129 -#: assets/build/blocks.js:115951 -#: assets/build/formEditor.js:118771 -#: assets/build/formEditor.js:124436 msgid "Right" msgstr "" #: inc/page-builders/bricks/elements/form-widget.php:435 #: inc/page-builders/elementor/form-widget.php:728 -#: assets/build/blocks.js:114716 -#: assets/build/formEditor.js:128562 -#: assets/build/blocks.js:109136 -#: assets/build/formEditor.js:118778 +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 msgid "Full Width" msgstr "" #: inc/page-builders/bricks/elements/form-widget.php:455 #: inc/page-builders/elementor/form-widget.php:765 -#: assets/build/blocks.js:114647 -#: assets/build/formEditor.js:128496 -#: assets/build/blocks.js:109059 -#: assets/build/formEditor.js:118699 +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 msgid "Field Spacing" msgstr "" #: inc/page-builders/bricks/elements/form-widget.php:458 #: inc/page-builders/elementor/form-widget.php:769 -#: assets/build/blocks.js:114653 -#: assets/build/blocks.js:114655 -#: assets/build/formEditor.js:128503 -#: assets/build/blocks.js:109066 -#: assets/build/blocks.js:109068 -#: assets/build/formEditor.js:118707 +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 msgid "Small" msgstr "" #: inc/page-builders/bricks/elements/form-widget.php:459 #: inc/page-builders/elementor/form-widget.php:770 #: modules/gutenberg/icons/icons-v6-2.php:1591 -#: assets/build/blocks.js:114657 -#: assets/build/blocks.js:114659 -#: assets/build/formEditor.js:128506 -#: assets/build/blocks.js:109071 -#: assets/build/blocks.js:109073 -#: assets/build/formEditor.js:118711 +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 msgid "Medium" msgstr "" #: inc/page-builders/bricks/elements/form-widget.php:460 #: inc/page-builders/elementor/form-widget.php:771 -#: assets/build/blocks.js:114661 -#: assets/build/blocks.js:114663 -#: assets/build/formEditor.js:128509 -#: assets/build/blocks.js:109076 -#: assets/build/blocks.js:109078 -#: assets/build/formEditor.js:118715 +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 msgid "Large" msgstr "" @@ -3283,48 +2950,36 @@ msgstr "" #: inc/page-builders/elementor/form-widget.php:318 #: inc/smart-tags.php:113 -#: assets/build/blocks.js:113940 -#: assets/build/formEditor.js:123539 -#: assets/build/blocks.js:108307 -#: assets/build/formEditor.js:112977 +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 msgid "Form Title" msgstr "" #: inc/page-builders/elementor/form-widget.php:320 -#: assets/build/blocks.js:116701 -#: assets/build/blocks.js:110964 +#: assets/build/blocks.js:172 msgid "Show" msgstr "" #: inc/page-builders/elementor/form-widget.php:321 -#: assets/build/blocks.js:116704 -#: assets/build/blocks.js:110968 +#: assets/build/blocks.js:172 msgid "Hide" msgstr "" #: inc/page-builders/elementor/form-widget.php:332 #: inc/post-types.php:95 #: inc/post-types.php:232 -#: assets/build/blocks.js:113975 -#: assets/build/blocks.js:108360 +#: assets/build/blocks.js:172 msgid "Edit Form" msgstr "" #: inc/page-builders/elementor/form-widget.php:335 -#: assets/build/formEditor.js:125725 -#: assets/build/formEditor.js:125727 -#: assets/build/forms.js:64829 -#: assets/build/formEditor.js:115369 -#: assets/build/formEditor.js:115375 -#: assets/build/forms.js:55833 +#: assets/build/formEditor.js:172 +#: assets/build/forms.js:172 msgid "Edit" msgstr "" #: inc/page-builders/elementor/form-widget.php:346 -#: assets/build/dashboard.js:96215 -#: assets/build/dashboard.js:96223 -#: assets/build/dashboard.js:82533 -#: assets/build/dashboard.js:82546 +#: assets/build/dashboard.js:2 msgid "Create New Form" msgstr "" @@ -3333,38 +2988,30 @@ msgid "Create" msgstr "" #: inc/page-builders/elementor/form-widget.php:487 -#: assets/build/blocks.js:117508 -#: assets/build/formEditor.js:131147 +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 #: modules/gutenberg/build/blocks.js:6 -#: assets/build/blocks.js:111967 -#: assets/build/formEditor.js:121444 msgid "Color 1" msgstr "" #: inc/page-builders/elementor/form-widget.php:491 -#: assets/build/blocks.js:117551 -#: assets/build/formEditor.js:131190 +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 #: modules/gutenberg/build/blocks.js:6 -#: assets/build/blocks.js:112034 -#: assets/build/formEditor.js:121511 msgid "Location 1" msgstr "" #: inc/page-builders/elementor/form-widget.php:497 -#: assets/build/blocks.js:117522 -#: assets/build/formEditor.js:131161 +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 #: modules/gutenberg/build/blocks.js:6 -#: assets/build/blocks.js:111991 -#: assets/build/formEditor.js:121468 msgid "Color 2" msgstr "" #: inc/page-builders/elementor/form-widget.php:501 -#: assets/build/blocks.js:117563 -#: assets/build/formEditor.js:131202 +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 #: modules/gutenberg/build/blocks.js:6 -#: assets/build/blocks.js:112047 -#: assets/build/formEditor.js:121524 msgid "Location 2" msgstr "" @@ -3573,11 +3220,8 @@ msgid "Renewal" msgstr "" #: inc/payments/admin/admin-handler.php:973 -#: assets/build/blocks.js:112469 -#: assets/build/blocks.js:112580 +#: assets/build/blocks.js:172 #: assets/build/payments.js:172 -#: assets/build/blocks.js:106551 -#: assets/build/blocks.js:106704 msgid "One Time" msgstr "" @@ -3592,8 +3236,8 @@ msgstr "" #: inc/payments/admin/admin-handler.php:1501 #: inc/payments/admin/admin-handler.php:1505 #: inc/payments/admin/admin-handler.php:1509 -#: inc/payments/front-end.php:854 -#: inc/payments/front-end.php:1253 +#: inc/payments/front-end.php:865 +#: inc/payments/front-end.php:1274 msgid "Guest User" msgstr "" @@ -3625,7 +3269,7 @@ msgstr "" #: inc/payments/front-end.php:121 #: inc/payments/front-end.php:346 #: inc/payments/front-end.php:634 -#: inc/payments/front-end.php:1142 +#: inc/payments/front-end.php:1153 msgid "Stripe secret key not found." msgstr "" @@ -3737,26 +3381,26 @@ msgid "Subscription not found for the payment." msgstr "" #. translators: %d: User ID -#: inc/payments/front-end.php:852 -#: inc/payments/front-end.php:1253 +#: inc/payments/front-end.php:863 +#: inc/payments/front-end.php:1274 #, php-format msgid "User ID: %d" msgstr "" #. translators: %s: Invoice status -#: inc/payments/front-end.php:860 +#: inc/payments/front-end.php:871 #, php-format msgid "Invoice Status: %s" msgstr "" #. translators: Title for subscription verification log -#: inc/payments/front-end.php:867 +#: inc/payments/front-end.php:878 msgid "Subscription Verification" msgstr "" #. translators: %s: Subscription ID #. translators: %s: Stripe subscription ID -#: inc/payments/front-end.php:871 +#: inc/payments/front-end.php:882 #: inc/payments/stripe/admin-stripe-handler.php:119 #: inc/payments/stripe/admin-stripe-handler.php:204 #: inc/payments/stripe/admin-stripe-handler.php:506 @@ -3772,8 +3416,8 @@ msgstr "" #. translators: %s: payment gateway name (e.g., Stripe) #. translators: %s: payment gateway #. translators: %s: Payment gateway name (e.g., Stripe). -#: inc/payments/front-end.php:873 -#: inc/payments/front-end.php:1264 +#: inc/payments/front-end.php:884 +#: inc/payments/front-end.php:1285 #: inc/payments/stripe/admin-stripe-handler.php:124 #: inc/payments/stripe/admin-stripe-handler.php:209 #: inc/payments/stripe/admin-stripe-handler.php:511 @@ -3788,13 +3432,13 @@ msgid "Payment Gateway: %s" msgstr "" #. translators: %s: Payment Intent ID -#: inc/payments/front-end.php:875 +#: inc/payments/front-end.php:886 #, php-format msgid "Payment Intent ID: %s" msgstr "" #. translators: %s: Charge ID -#: inc/payments/front-end.php:877 +#: inc/payments/front-end.php:888 #: inc/payments/stripe/stripe-webhook.php:1050 #, php-format msgid "Charge ID: %s" @@ -3802,7 +3446,7 @@ msgstr "" #. translators: %s: Subscription Status #. translators: %s: subscription status -#: inc/payments/front-end.php:879 +#: inc/payments/front-end.php:890 #: inc/payments/stripe/admin-stripe-handler.php:129 #: inc/payments/stripe/admin-stripe-handler.php:214 #: inc/payments/stripe/admin-stripe-handler.php:516 @@ -3811,7 +3455,7 @@ msgid "Subscription Status: %s" msgstr "" #. translators: %s: Customer ID -#: inc/payments/front-end.php:881 +#: inc/payments/front-end.php:892 #: inc/payments/stripe/stripe-webhook.php:1124 #, php-format msgid "Customer ID: %s" @@ -3819,8 +3463,8 @@ msgstr "" #. translators: 1: Amount, 2: Currency #. translators: %1$s: amount, %2$s: currency. -#: inc/payments/front-end.php:883 -#: inc/payments/front-end.php:1266 +#: inc/payments/front-end.php:894 +#: inc/payments/front-end.php:1287 #: inc/payments/stripe/stripe-webhook.php:1055 #: inc/payments/stripe/stripe-webhook.php:1116 #, php-format @@ -3829,34 +3473,34 @@ msgstr "" #. translators: %s: Payment mode (e.g. Live or Test) #. translators: %s: payment mode -#: inc/payments/front-end.php:886 -#: inc/payments/front-end.php:1271 +#: inc/payments/front-end.php:897 +#: inc/payments/front-end.php:1292 #, php-format msgid "Mode: %s" msgstr "" -#: inc/payments/front-end.php:920 +#: inc/payments/front-end.php:931 msgid "Failed to verify subscription." msgstr "" -#: inc/payments/front-end.php:1175 -#: inc/payments/front-end.php:1193 -#: inc/payments/front-end.php:1201 -#: inc/payments/front-end.php:1208 +#: inc/payments/front-end.php:1186 +#: inc/payments/front-end.php:1204 +#: inc/payments/front-end.php:1212 +#: inc/payments/front-end.php:1219 msgid "Failed to retrieve payment intent." msgstr "" -#: inc/payments/front-end.php:1216 +#: inc/payments/front-end.php:1227 msgid "Payment was not confirmed successfully." msgstr "" -#: inc/payments/front-end.php:1258 +#: inc/payments/front-end.php:1279 msgid "Payment Verification" msgstr "" #. translators: %s: Stripe transaction ID #. translators: %s: Charge ID -#: inc/payments/front-end.php:1262 +#: inc/payments/front-end.php:1283 #: inc/payments/stripe/stripe-webhook.php:1112 #, php-format msgid "Transaction ID: %s" @@ -3864,18 +3508,18 @@ msgstr "" #. translators: %s: payment status #. translators: %s: Status -#: inc/payments/front-end.php:1268 +#: inc/payments/front-end.php:1289 #: inc/payments/stripe/stripe-webhook.php:576 #: inc/payments/stripe/stripe-webhook.php:1118 #, php-format msgid "Status: %s" msgstr "" -#: inc/payments/front-end.php:1374 +#: inc/payments/front-end.php:1395 msgid "Failed to create Stripe customer." msgstr "" -#: inc/payments/front-end.php:1438 +#: inc/payments/front-end.php:1459 msgid "Failed to create Stripe guest customer." msgstr "" @@ -4303,48 +3947,51 @@ msgstr "" msgid "Payment verification failed. Payment type mismatch." msgstr "" -#: inc/payments/payment-helper.php:903 -#: inc/payments/payment-helper.php:1043 +#: inc/payments/payment-helper.php:953 +#: inc/payments/payment-helper.php:1140 +#: inc/payments/payment-helper.php:1177 msgid "Variable amount field configuration not found." msgstr "" -#: inc/payments/payment-helper.php:924 +#: inc/payments/payment-helper.php:974 msgid "No payment options are configured for this field." msgstr "" #. translators: %s: currency code -#: inc/payments/payment-helper.php:950 +#: inc/payments/payment-helper.php:1000 msgid "Invalid payment amount. Please select a valid amount from the available options." msgstr "" #. translators: %1$s: expected amount, %2$s: payment amount -#: inc/payments/payment-helper.php:986 +#: inc/payments/payment-helper.php:1036 msgid "Payment configuration not found." msgstr "" #. translators: %1$s: expected amount, %2$s: payment amount -#: inc/payments/payment-helper.php:1003 -#: inc/payments/payment-helper.php:1055 -#: inc/payments/payment-helper.php:1091 -#: inc/payments/payment-helper.php:1111 +#: inc/payments/payment-helper.php:1053 +#: inc/payments/payment-helper.php:1164 +#: inc/payments/payment-helper.php:1190 +#: inc/payments/payment-helper.php:1225 #, php-format msgid "Payment amount mismatch. Expected %1$s, received %2$s." msgstr "" -#: inc/payments/payment-helper.php:1032 -#: inc/payments/payment-helper.php:1082 -#: inc/payments/payment-helper.php:1103 -msgid "Variable amount field value is required." +#. translators: %1$s: minimum amount, %2$s: payment amount +#: inc/payments/payment-helper.php:1105 +#: inc/payments/payment-helper.php:1252 +#, php-format +msgid "Payment amount below minimum. Minimum: %1$s, received %2$s." msgstr "" -#: inc/payments/payment-helper.php:1065 -msgid "Number field configuration not found." +#: inc/payments/payment-helper.php:1117 +#: inc/payments/payment-helper.php:1155 +#: inc/payments/payment-helper.php:1203 +msgid "Payment amount could not be verified for this form. Please edit and re-save the form, then try again." msgstr "" -#. translators: %1$s: minimum amount, %2$s: payment amount -#: inc/payments/payment-helper.php:1125 -#, php-format -msgid "Payment amount below minimum. Minimum: %1$s, received %2$s." +#: inc/payments/payment-helper.php:1129 +#: inc/payments/payment-helper.php:1217 +msgid "Variable amount field value is required." msgstr "" #: inc/payments/payment-history-shortcode.php:247 @@ -4401,16 +4048,10 @@ msgid "Cancel Subscription" msgstr "" #: inc/payments/payment-history-shortcode.php:305 -#: assets/build/blocks.js:107781 -#: assets/build/dashboard.js:96732 -#: assets/build/formEditor.js:129109 -#: assets/build/settings.js:75865 -#: assets/build/settings.js:76178 -#: assets/build/blocks.js:102093 -#: assets/build/dashboard.js:83009 -#: assets/build/formEditor.js:119258 -#: assets/build/settings.js:68346 -#: assets/build/settings.js:68617 +#: assets/build/blocks.js:172 +#: assets/build/dashboard.js:172 +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 msgid "Back" msgstr "" @@ -4482,8 +4123,6 @@ msgstr "" #: inc/payments/payment-history-shortcode.php:886 #: inc/payments/payment-history-shortcode.php:911 #: assets/build/payments.js:2 -#: assets/build/settings.js:72883 -#: assets/build/settings.js:65189 msgid "Active" msgstr "" @@ -4507,48 +4146,36 @@ msgstr "" #: inc/payments/payment-history-shortcode.php:890 #: inc/payments/stripe/admin-stripe-handler.php:517 #: assets/build/payments.js:2 -#: assets/build/settings.js:72884 -#: assets/build/settings.js:65190 msgid "Paused" msgstr "" #: inc/payments/payment-history-shortcode.php:331 #: inc/payments/payment-history-shortcode.php:904 #: assets/build/payments.js:2 -#: assets/build/settings.js:72877 -#: assets/build/settings.js:65183 msgid "Paid" msgstr "" #: inc/payments/payment-history-shortcode.php:332 #: inc/payments/payment-history-shortcode.php:905 #: assets/build/payments.js:2 -#: assets/build/settings.js:72879 -#: assets/build/settings.js:65185 msgid "Pending" msgstr "" #: inc/payments/payment-history-shortcode.php:333 #: inc/payments/payment-history-shortcode.php:906 #: assets/build/payments.js:2 -#: assets/build/settings.js:72880 -#: assets/build/settings.js:65186 msgid "Failed" msgstr "" #: inc/payments/payment-history-shortcode.php:334 #: inc/payments/payment-history-shortcode.php:908 #: assets/build/payments.js:2 -#: assets/build/settings.js:72881 -#: assets/build/settings.js:65187 msgid "Refunded" msgstr "" #: inc/payments/payment-history-shortcode.php:335 #: inc/payments/payment-history-shortcode.php:909 #: assets/build/payments.js:2 -#: assets/build/settings.js:72878 -#: assets/build/settings.js:65184 msgid "Partially Refunded" msgstr "" @@ -4608,32 +4235,18 @@ msgid "Showing %1$dโ€“%2$d of %3$d transactions" msgstr "" #: inc/payments/payment-history-shortcode.php:529 -#: assets/build/entries.js:69720 -#: assets/build/entries.js:69826 -#: assets/build/formEditor.js:128903 +#: assets/build/entries.js:172 +#: assets/build/formEditor.js:172 #: assets/build/payments.js:172 -#: assets/build/entries.js:60804 -#: assets/build/entries.js:60894 -#: assets/build/formEditor.js:119126 msgid "Previous" msgstr "" #: inc/payments/payment-history-shortcode.php:534 -#: assets/build/blocks.js:107778 -#: assets/build/dashboard.js:96745 -#: assets/build/dashboard.js:99338 -#: assets/build/entries.js:69727 -#: assets/build/entries.js:69841 -#: assets/build/formEditor.js:128904 -#: assets/build/formEditor.js:129106 +#: assets/build/blocks.js:172 +#: assets/build/dashboard.js:172 +#: assets/build/entries.js:172 +#: assets/build/formEditor.js:172 #: assets/build/payments.js:172 -#: assets/build/blocks.js:102092 -#: assets/build/dashboard.js:83022 -#: assets/build/dashboard.js:85650 -#: assets/build/entries.js:60814 -#: assets/build/entries.js:60908 -#: assets/build/formEditor.js:119127 -#: assets/build/formEditor.js:119257 msgid "Next" msgstr "" @@ -4696,8 +4309,6 @@ msgstr "" #: inc/payments/stripe/admin-stripe-handler.php:130 #: inc/payments/stripe/admin-stripe-handler.php:215 #: assets/build/payments.js:2 -#: assets/build/settings.js:72882 -#: assets/build/settings.js:65188 msgid "Canceled" msgstr "" @@ -4865,19 +4476,14 @@ msgid "%s Payment Refund" msgstr "" #. translators: %1$s: Payment settings link -#. translators: %1$s: Stripe dashboard button #: inc/payments/stripe/admin-stripe-handler.php:797 #: assets/build/payments.js:2 -#: assets/build/settings.js:73010 -#: assets/build/settings.js:65359 #, php-format,js-format msgid "Webhooks keep SureForms in sync with Stripe by automatically updating payment and subscription data. Please %1$s Webhook." msgstr "" #: inc/payments/stripe/admin-stripe-handler.php:804 #: assets/build/payments.js:2 -#: assets/build/settings.js:73021 -#: assets/build/settings.js:65382 msgid "configure" msgstr "" @@ -5165,8 +4771,7 @@ msgstr "" #. translators: %s: Canceled by method (e.g., Webhook). #: inc/payments/stripe/stripe-webhook.php:732 #: inc/payments/stripe/stripe-webhook.php:896 -#: assets/build/settings.js:73698 -#: assets/build/settings.js:66051 +#: assets/build/settings.js:172 msgid "Webhook" msgstr "" @@ -5263,15 +4868,13 @@ msgid "Add New" msgstr "" #: inc/post-types.php:230 -#: assets/build/forms.js:64534 -#: assets/build/forms.js:55582 +#: assets/build/forms.js:172 msgid "Add New Form" msgstr "" #: inc/post-types.php:233 -#: assets/build/forms.js:64842 +#: assets/build/forms.js:172 #: assets/build/payments.js:172 -#: assets/build/forms.js:55842 msgid "View Form" msgstr "" @@ -5308,85 +4911,85 @@ msgstr "" msgid "This form is closed. The submission period has ended." msgstr "" -#: inc/rest-api.php:104 +#: inc/rest-api.php:130 msgid "Missing required parameters." msgstr "" -#: inc/rest-api.php:111 +#: inc/rest-api.php:137 msgid "Invalid date range." msgstr "" -#: inc/rest-api.php:388 +#: inc/rest-api.php:414 msgid "Invalid onboarding user details." msgstr "" -#: inc/rest-api.php:493 +#: inc/rest-api.php:519 msgid "Plugin identifier is required." msgstr "" -#: inc/rest-api.php:502 +#: inc/rest-api.php:528 msgid "Integration not found." msgstr "" -#: inc/rest-api.php:628 -#: inc/rest-api.php:677 -#: inc/rest-api.php:725 +#: inc/rest-api.php:654 +#: inc/rest-api.php:703 +#: inc/rest-api.php:751 msgid "Select at least one entry." msgstr "" -#: inc/rest-api.php:635 -#: inc/rest-api.php:684 +#: inc/rest-api.php:661 +#: inc/rest-api.php:710 msgid "Action is required." msgstr "" -#: inc/rest-api.php:643 +#: inc/rest-api.php:669 msgid "Invalid action. Use \"read\" or \"unread\"." msgstr "" -#: inc/rest-api.php:692 +#: inc/rest-api.php:718 msgid "Invalid action. Use \"trash\" or \"restore\"." msgstr "" -#: inc/rest-api.php:758 -#: inc/rest-api.php:901 +#: inc/rest-api.php:784 +#: inc/rest-api.php:927 msgid "Entry ID is required." msgstr "" -#: inc/rest-api.php:1035 +#: inc/rest-api.php:1061 msgid "Select at least one form and specify an action." msgstr "" -#: inc/rest-api.php:1050 +#: inc/rest-api.php:1076 msgid "Form not found or is not a valid form type." msgstr "" -#: inc/rest-api.php:1062 +#: inc/rest-api.php:1088 msgid "This form is already in the trash." msgstr "" -#: inc/rest-api.php:1073 +#: inc/rest-api.php:1099 msgid "This form is not in the trash." msgstr "" -#: inc/rest-api.php:1089 +#: inc/rest-api.php:1115 msgid "Use the restore action to recover a trashed form before switching it to draft." msgstr "" -#: inc/rest-api.php:1094 +#: inc/rest-api.php:1120 msgid "This form is already a draft." msgstr "" -#: inc/rest-api.php:1109 +#: inc/rest-api.php:1135 msgid "Invalid action." msgstr "" #. translators: %s: action name -#: inc/rest-api.php:1124 +#: inc/rest-api.php:1150 #, php-format msgid "Failed to %s this form. Please try again." msgstr "" -#: inc/rest-api.php:1805 +#: inc/rest-api.php:1839 msgid " (Copy)" msgstr "" @@ -5399,12 +5002,7 @@ msgid "Invalid form id." msgstr "" #: inc/single-form-settings/form-settings-api.php:187 -#: assets/build/formEditor.js:126441 -#: assets/build/formEditor.js:134275 -#: assets/build/formEditor.js:134366 -#: assets/build/formEditor.js:116145 -#: assets/build/formEditor.js:124686 -#: assets/build/formEditor.js:124785 +#: assets/build/formEditor.js:172 msgid "Form settings saved." msgstr "" @@ -5548,14 +5146,11 @@ msgid "Separator" msgstr "" #: modules/gutenberg/classes/class-spec-block-config.php:574 -#: assets/build/blocks.js:110855 -#: assets/build/blocks.js:117947 +#: assets/build/blocks.js:172 #: modules/gutenberg/build/blocks-placeholder.js:10 #: modules/gutenberg/build/blocks.js:4 #: modules/gutenberg/build/blocks.js:6 #: modules/gutenberg/build/blocks.js:9 -#: assets/build/blocks.js:104913 -#: assets/build/blocks.js:112343 msgid "Icon" msgstr "" @@ -7288,8 +6883,7 @@ msgid "Cookie Bite" msgstr "" #: modules/gutenberg/icons/icons-v6-0.php:5049 -#: assets/build/dashboard.js:99428 -#: assets/build/dashboard.js:85772 +#: assets/build/dashboard.js:172 msgid "Copy" msgstr "" @@ -7483,11 +7077,9 @@ msgid "Deskpro" msgstr "" #: modules/gutenberg/icons/icons-v6-1.php:290 -#: assets/build/blocks.js:120512 -#: assets/build/formEditor.js:133446 +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 #: modules/gutenberg/build/blocks.js:1 -#: assets/build/blocks.js:115057 -#: assets/build/formEditor.js:123884 msgid "Desktop" msgstr "" @@ -8546,8 +8138,7 @@ msgid "Git Alt" msgstr "" #: modules/gutenberg/icons/icons-v6-1.php:3450 -#: assets/build/settings.js:77959 -#: assets/build/settings.js:70543 +#: assets/build/settings.js:172 msgid "GitHub" msgstr "" @@ -9445,8 +9036,7 @@ msgid "Landmark Flag" msgstr "" #: modules/gutenberg/icons/icons-v6-2.php:636 -#: assets/build/entries.js:69067 -#: assets/build/entries.js:60170 +#: assets/build/entries.js:172 msgid "Language" msgstr "" @@ -9882,11 +9472,9 @@ msgid "Mizuni" msgstr "" #: modules/gutenberg/icons/icons-v6-2.php:1882 -#: assets/build/blocks.js:120522 -#: assets/build/formEditor.js:133456 +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 #: modules/gutenberg/build/blocks.js:1 -#: assets/build/blocks.js:115069 -#: assets/build/formEditor.js:123896 msgid "Mobile" msgstr "" @@ -11257,8 +10845,7 @@ msgid "Signal" msgstr "" #: modules/gutenberg/icons/icons-v6-3.php:625 -#: assets/build/formEditor.js:126984 -#: assets/build/formEditor.js:116882 +#: assets/build/formEditor.js:172 msgid "Signature" msgstr "" @@ -11764,11 +11351,9 @@ msgid "Table Tennis Paddle Ball" msgstr "" #: modules/gutenberg/icons/icons-v6-3.php:2125 -#: assets/build/blocks.js:120517 -#: assets/build/formEditor.js:133451 +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 #: modules/gutenberg/build/blocks.js:1 -#: assets/build/blocks.js:115063 -#: assets/build/formEditor.js:123890 msgid "Tablet" msgstr "" @@ -12053,14 +11638,8 @@ msgid "Transgender" msgstr "" #: modules/gutenberg/icons/icons-v6-3.php:2916 -#: assets/build/entries.js:70218 -#: assets/build/entries.js:72242 -#: assets/build/forms.js:64317 -#: assets/build/forms.js:64394 -#: assets/build/entries.js:61266 -#: assets/build/entries.js:63218 -#: assets/build/forms.js:55335 -#: assets/build/forms.js:55417 +#: assets/build/entries.js:172 +#: assets/build/forms.js:172 msgid "Trash" msgstr "" @@ -12279,10 +11858,8 @@ msgid "Up Right From Square" msgstr "" #: modules/gutenberg/icons/icons-v6-3.php:3548 -#: assets/build/entries.js:69039 -#: assets/build/formEditor.js:126968 -#: assets/build/entries.js:60130 -#: assets/build/formEditor.js:116869 +#: assets/build/entries.js:172 +#: assets/build/formEditor.js:172 msgid "Upload" msgstr "" @@ -12856,8 +12433,7 @@ msgid "Brands" msgstr "" #: modules/gutenberg/icons/icons-v6-3.php:5206 -#: assets/build/dashboard.js:99296 -#: assets/build/dashboard.js:85572 +#: assets/build/dashboard.js:172 msgid "Business" msgstr "" @@ -12911,5681 +12487,3774 @@ msgstr "" msgid "Instant Form Disabled" msgstr "" -#: assets/build/blocks.js:107411 -#: assets/build/dashboard.js:99265 -#: assets/build/formEditor.js:120299 -#: assets/build/blocks.js:101823 -#: assets/build/dashboard.js:85532 -#: assets/build/formEditor.js:109430 -msgid "Premium" +#: assets/build/blocks.js:2 +#: assets/build/forms.js:172 +#: assets/build/settings.js:172 +msgid "(no title)" msgstr "" -#: assets/build/blocks.js:107775 -#: assets/build/formEditor.js:129103 -#: assets/build/blocks.js:102091 -#: assets/build/formEditor.js:119256 -msgid "Page Break Label" +#: assets/build/blocks.js:2 +msgid "Select a Form" msgstr "" -#: assets/build/blocks.js:107958 -#: assets/build/blocks.js:102206 -msgid "Field preview" +#: assets/build/blocks.js:2 +msgid "No forms foundโ€ฆ" msgstr "" -#: assets/build/blocks.js:108102 -#: assets/build/blocks.js:108291 -#: assets/build/blocks.js:109143 -#: assets/build/blocks.js:109405 -#: assets/build/blocks.js:109640 -#: assets/build/blocks.js:110281 -#: assets/build/blocks.js:111079 -#: assets/build/blocks.js:111595 -#: assets/build/blocks.js:112941 -#: assets/build/blocks.js:113331 -#: assets/build/blocks.js:115267 -#: assets/build/blocks.js:115560 -#: assets/build/blocks.js:102332 -#: assets/build/blocks.js:102485 -#: assets/build/blocks.js:103343 -#: assets/build/blocks.js:103566 -#: assets/build/blocks.js:103778 -#: assets/build/blocks.js:104368 -#: assets/build/blocks.js:105221 -#: assets/build/blocks.js:105722 -#: assets/build/blocks.js:107285 -#: assets/build/blocks.js:107614 -#: assets/build/blocks.js:109607 -#: assets/build/blocks.js:109811 -msgid "Attributes" +#: assets/build/blocks.js:2 +msgid "Choose" msgstr "" -#: assets/build/blocks.js:108105 -#: assets/build/blocks.js:108320 -#: assets/build/blocks.js:109049 -#: assets/build/blocks.js:109430 -#: assets/build/blocks.js:109661 -#: assets/build/blocks.js:110100 -#: assets/build/blocks.js:110962 -#: assets/build/blocks.js:111421 -#: assets/build/blocks.js:112427 -#: assets/build/blocks.js:113356 -#: assets/build/blocks.js:115141 -#: assets/build/blocks.js:115585 -#: assets/build/blocks.js:102336 -#: assets/build/blocks.js:102515 -#: assets/build/blocks.js:103228 -#: assets/build/blocks.js:103592 -#: assets/build/blocks.js:103799 -#: assets/build/blocks.js:104143 -#: assets/build/blocks.js:105060 -#: assets/build/blocks.js:105516 -#: assets/build/blocks.js:106504 -#: assets/build/blocks.js:107640 -#: assets/build/blocks.js:109457 -#: assets/build/blocks.js:109837 -msgid "Help Text" +#: assets/build/blocks.js:2 +msgid "Create New" msgstr "" -#: assets/build/blocks.js:108294 -#: assets/build/blocks.js:109017 -#: assets/build/blocks.js:109408 -#: assets/build/blocks.js:110072 -#: assets/build/blocks.js:110930 -#: assets/build/blocks.js:111393 -#: assets/build/blocks.js:113334 -#: assets/build/blocks.js:115113 -#: assets/build/blocks.js:115563 -#: assets/build/blocks.js:102489 -#: assets/build/blocks.js:103194 -#: assets/build/blocks.js:103570 -#: assets/build/blocks.js:104113 -#: assets/build/blocks.js:105026 -#: assets/build/blocks.js:105486 -#: assets/build/blocks.js:107618 -#: assets/build/blocks.js:109427 -#: assets/build/blocks.js:109815 -msgid "Required" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:2 +#, js-format +msgid "%s - Order ID" msgstr "" -#: assets/build/blocks.js:108306 -#: assets/build/blocks.js:109028 -#: assets/build/blocks.js:109416 -#: assets/build/blocks.js:110083 -#: assets/build/blocks.js:110945 -#: assets/build/blocks.js:111404 -#: assets/build/blocks.js:113342 -#: assets/build/blocks.js:115124 -#: assets/build/blocks.js:115571 -#: assets/build/blocks.js:102501 -#: assets/build/blocks.js:103206 -#: assets/build/blocks.js:103578 -#: assets/build/blocks.js:104125 -#: assets/build/blocks.js:105042 -#: assets/build/blocks.js:105498 -#: assets/build/blocks.js:107626 -#: assets/build/blocks.js:109439 -#: assets/build/blocks.js:109823 -msgid "Error Message" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:2 +#, js-format +msgid "%s - Amount" msgstr "" -#: assets/build/blocks.js:108328 -#: assets/build/blocks.js:102522 -msgid "Checked by Default" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:2 +#, js-format +msgid "%s - Customer Email" msgstr "" -#: assets/build/blocks.js:108819 -#: assets/build/blocks.js:110706 -#: assets/build/blocks.js:102936 -#: assets/build/blocks.js:104735 -msgid "Minimum Selections" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:2 +#, js-format +msgid "%s - Customer Name" msgstr "" -#: assets/build/blocks.js:108843 -#: assets/build/blocks.js:110730 -#: assets/build/blocks.js:102961 -#: assets/build/blocks.js:104760 -msgid "Maximum Selections" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:2 +#, js-format +msgid "%s - Status" msgstr "" -#: assets/build/blocks.js:108868 -#: assets/build/blocks.js:110755 -#: assets/build/blocks.js:111588 -#: assets/build/blocks.js:102987 -#: assets/build/blocks.js:104786 -#: assets/build/blocks.js:105700 -msgid "Please check the Minimum and Maximum value" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:2 +#, js-format +msgid "%s - Description" msgstr "" -#: assets/build/blocks.js:108930 -#: assets/build/blocks.js:108931 -#: assets/build/blocks.js:110828 -#: assets/build/blocks.js:110829 -#: assets/build/blocks.js:103059 -#: assets/build/blocks.js:103063 -#: assets/build/blocks.js:104872 -#: assets/build/blocks.js:104876 -msgid "Preselect this option" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +msgid "Page Break Label" msgstr "" -#: assets/build/blocks.js:108950 -#: assets/build/blocks.js:110863 -#: assets/build/blocks.js:103091 -#: assets/build/blocks.js:104923 -msgid "Edit Options" +#. translators: abbreviation for units +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +#: modules/gutenberg/build/blocks.js:2 +msgid "Reset" msgstr "" -#: assets/build/blocks.js:108984 -#: assets/build/blocks.js:110897 -#: assets/build/blocks.js:103150 -#: assets/build/blocks.js:104982 -msgid "Add New Option" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +#: modules/gutenberg/build/blocks.js:4 +msgid "Clear" msgstr "" -#: assets/build/blocks.js:109002 -#: assets/build/blocks.js:110915 -#: assets/build/blocks.js:103171 -#: assets/build/blocks.js:105003 -msgid "ADD" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +#: modules/gutenberg/build/blocks.js:4 +msgid "Select Color" msgstr "" -#: assets/build/blocks.js:109086 -#: assets/build/blocks.js:111028 -#: assets/build/blocks.js:103266 -#: assets/build/blocks.js:105148 -msgid "Add Numeric Values to Options" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +#: modules/gutenberg/build/blocks.js:2 +#: modules/gutenberg/build/blocks.js:4 +#: modules/gutenberg/build/blocks.js:6 +#: modules/gutenberg/build/blocks.js:8 +msgid "Pixel" msgstr "" -#: assets/build/blocks.js:109097 -#: assets/build/blocks.js:103278 -msgid "Enable Dropdown Search" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +#: modules/gutenberg/build/blocks.js:2 +#: modules/gutenberg/build/blocks.js:4 +#: modules/gutenberg/build/blocks.js:6 +#: modules/gutenberg/build/blocks.js:8 +msgid "Em" msgstr "" -#: assets/build/blocks.js:109108 -#: assets/build/blocks.js:103290 -msgid "Allow Multiple" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +#: modules/gutenberg/build/blocks.js:4 +#: modules/gutenberg/build/blocks.js:6 +#: modules/gutenberg/build/blocks.js:8 +msgid "%" msgstr "" -#: assets/build/blocks.js:109119 -#: assets/build/blocks.js:111050 -#: assets/build/blocks.js:103302 -#: assets/build/blocks.js:105172 -msgid "Dynamic Default Value" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +#: modules/gutenberg/build/blocks.js:2 +#: modules/gutenberg/build/blocks.js:4 +#: modules/gutenberg/build/blocks.js:6 +msgid "Select Units" msgstr "" -#: assets/build/blocks.js:109123 -#: assets/build/blocks.js:103308 -msgid "Use a smart tag like {get_input:colors} and pass pipe separated values in the URL (for example ?colors=Red|Blue). Every option whose label matches a value will be preselected. You can also chain multiple smart tags separated by pipes." +#. translators: abbreviation for units +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +#: modules/gutenberg/build/blocks.js:3 +#: modules/gutenberg/build/blocks.js:4 +#: modules/gutenberg/build/blocks.js:5 +#: modules/gutenberg/build/blocks.js:6 +#: modules/gutenberg/build/blocks.js:7 +#: modules/gutenberg/build/blocks.js:8 +#, js-format +msgid "%s units" msgstr "" -#: assets/build/blocks.js:109123 -#: assets/build/blocks.js:103312 -msgid "Use a smart tag like {get_input:country}. The first option whose label matches the resolved value will be preselected." +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +#: modules/gutenberg/build/blocks.js:6 +msgid "Top" msgstr "" -#: assets/build/blocks.js:109454 -#: assets/build/blocks.js:110130 -#: assets/build/blocks.js:111451 -#: assets/build/blocks.js:115172 -#: assets/build/blocks.js:115609 -#: assets/build/blocks.js:103614 -#: assets/build/blocks.js:104173 -#: assets/build/blocks.js:105548 -#: assets/build/blocks.js:109488 -#: assets/build/blocks.js:109859 -msgid "Default Value" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +#: modules/gutenberg/build/blocks.js:6 +msgid "Bottom" msgstr "" -#: assets/build/blocks.js:109470 -#: assets/build/blocks.js:110222 -#: assets/build/blocks.js:111474 -#: assets/build/blocks.js:115193 -#: assets/build/blocks.js:115623 -#: assets/build/blocks.js:103629 -#: assets/build/blocks.js:104296 -#: assets/build/blocks.js:105576 -#: assets/build/blocks.js:109509 -#: assets/build/blocks.js:109873 -msgid "Read Only" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +#: modules/gutenberg/build/blocks.js:1 +msgid "Device" msgstr "" -#: assets/build/blocks.js:109478 -#: assets/build/blocks.js:110233 -#: assets/build/blocks.js:113382 -#: assets/build/blocks.js:103637 -#: assets/build/blocks.js:104308 -#: assets/build/blocks.js:107663 -msgid "Unique Entry" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +#: modules/gutenberg/build/blocks.js:4 +#: modules/gutenberg/build/blocks.js:6 +#: modules/gutenberg/build/blocks.js:8 +#: modules/gutenberg/build/blocks.js:9 +msgid "Margin" msgstr "" -#: assets/build/blocks.js:109486 -#: assets/build/blocks.js:110244 -#: assets/build/blocks.js:113390 -#: assets/build/blocks.js:103645 -#: assets/build/blocks.js:104320 -#: assets/build/blocks.js:107671 -msgid "Validation Message for Duplicate" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +#: modules/gutenberg/build/blocks.js:4 +msgid "Please add a option props to MultiButtonsControl" msgstr "" -#: assets/build/blocks.js:109499 -#: assets/build/blocks.js:103663 -msgid "Enable Email Confirmation" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +msgid "Select Gradient" msgstr "" -#: assets/build/blocks.js:109669 -#: assets/build/blocks.js:103806 -msgid "Checked by default" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +#: modules/gutenberg/build/blocks.js:6 +msgid "Basic" msgstr "" -#: assets/build/blocks.js:110155 -#: assets/build/blocks.js:104197 -msgid "Color Picker" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +#: modules/gutenberg/build/blocks.js:4 +#: modules/gutenberg/build/blocks.js:6 +msgid "Advanced" msgstr "" -#: assets/build/blocks.js:110159 -#: assets/build/blocks.js:104202 -msgid "Use Text Field as Color Picker" +#: assets/build/blocks.js:172 +#: assets/build/entries.js:172 +#: assets/build/formEditor.js:172 +#: assets/build/forms.js:172 +#: assets/build/payments.js:172 +#: assets/build/settings.js:172 +#: modules/gutenberg/build/blocks.js:6 +msgid "Confirm" msgstr "" -#: assets/build/blocks.js:110160 -#: assets/build/blocks.js:104206 -msgid "Upgrade to the SureForms Pro Plan to use the Text field as a color picker." +#: assets/build/blocks.js:172 +#: assets/build/dashboard.js:172 +#: assets/build/entries.js:172 +#: assets/build/formEditor.js:172 +#: assets/build/forms.js:172 +#: assets/build/payments.js:2 +#: assets/build/payments.js:172 +#: assets/build/settings.js:172 +#: modules/gutenberg/build/blocks.js:6 +msgid "Cancel" msgstr "" -#: assets/build/blocks.js:110168 -#: assets/build/blocks.js:104221 -msgid "Input Pattern" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +#: assets/build/payments.js:172 +#: modules/gutenberg/build/blocks.js:6 +msgid "Processingโ€ฆ" msgstr "" -#: assets/build/blocks.js:110171 -#: assets/build/blocks.js:116926 -#: assets/build/formEditor.js:123881 -#: assets/build/formEditor.js:123928 -#: assets/build/formEditor.js:127586 -#: assets/build/formEditor.js:130190 -#: modules/gutenberg/build/blocks.js:4 +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 #: modules/gutenberg/build/blocks.js:6 -#: modules/gutenberg/build/blocks.js:8 -#: assets/build/blocks.js:104225 -#: assets/build/blocks.js:111166 -#: assets/build/formEditor.js:113269 -#: assets/build/formEditor.js:113321 -#: assets/build/formEditor.js:117558 -#: assets/build/formEditor.js:120318 -msgid "None" +msgid "Select Video" msgstr "" -#: assets/build/blocks.js:110174 -#: assets/build/blocks.js:104229 -msgid "(###) ###-####" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +#: modules/gutenberg/build/blocks.js:6 +msgid "Change Video" msgstr "" -#: assets/build/blocks.js:110177 -#: assets/build/blocks.js:104233 -msgid "(##) ####-####" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +#: modules/gutenberg/build/blocks.js:6 +msgid "Select Lottie Animation" msgstr "" -#: assets/build/blocks.js:110180 -#: assets/build/blocks.js:104237 -msgid "27/08/2024" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +#: modules/gutenberg/build/blocks.js:6 +msgid "Change Lottie Animation" msgstr "" -#: assets/build/blocks.js:110183 -#: assets/build/blocks.js:104241 -msgid "23:59:59" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +#: modules/gutenberg/build/blocks.js:6 +msgid "Upload SVG" msgstr "" -#: assets/build/blocks.js:110186 -#: assets/build/blocks.js:104245 -msgid "27/08/2024 23:59:59" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +#: modules/gutenberg/build/blocks.js:6 +msgid "Change SVG" msgstr "" -#: assets/build/blocks.js:110189 -#: assets/build/blocks.js:111932 -#: assets/build/blocks.js:116957 -#: assets/build/formEditor.js:130221 -#: modules/gutenberg/build/blocks.js:8 -#: assets/build/blocks.js:104249 -#: assets/build/blocks.js:105999 -#: assets/build/blocks.js:111209 -#: assets/build/formEditor.js:120361 -msgid "Custom" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +#: modules/gutenberg/build/blocks.js:6 +msgid "Select Image" msgstr "" -#: assets/build/blocks.js:110201 -#: assets/build/blocks.js:104264 -msgid "Custom Mask" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +#: modules/gutenberg/build/blocks.js:6 +msgid "Change Image" msgstr "" -#: assets/build/blocks.js:110212 -#: assets/build/blocks.js:104275 -msgid "Please check the documentation to manage custom input pattern " +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +#: modules/gutenberg/build/blocks.js:6 +msgid "Upload SVG?" msgstr "" -#: assets/build/blocks.js:110217 -#: assets/build/blocks.js:104285 -msgid "here" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +#: modules/gutenberg/build/blocks.js:6 +msgid "Upload SVG can be potentially risky. Are you sure?" msgstr "" -#: assets/build/blocks.js:110260 -#: assets/build/blocks.js:115231 -#: assets/build/blocks.js:104340 -#: assets/build/blocks.js:109560 -msgid "Maximum Characters" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +#: modules/gutenberg/build/blocks.js:6 +msgid "Upload Anyway" msgstr "" -#: assets/build/blocks.js:110848 -#: assets/build/blocks.js:104905 -msgid "Option Type" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +#: modules/gutenberg/build/blocks.js:4 +#: modules/gutenberg/build/blocks.js:6 +#: modules/gutenberg/build/blocks.js:8 +msgid "None" msgstr "" -#: assets/build/blocks.js:110974 -#: assets/build/blocks.js:105071 -msgid "Select Layout" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +#: modules/gutenberg/build/blocks.js:6 +msgid "Classic" msgstr "" -#: assets/build/blocks.js:110981 -#: modules/gutenberg/build/blocks.js:6 +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 #: modules/gutenberg/build/blocks.js:8 -#: modules/gutenberg/build/blocks.js:9 -#: assets/build/blocks.js:105079 -msgid "Horizontal" +msgid "Custom" msgstr "" -#: assets/build/blocks.js:110985 -#: modules/gutenberg/build/blocks.js:6 +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 #: modules/gutenberg/build/blocks.js:8 -#: modules/gutenberg/build/blocks.js:9 -#: assets/build/blocks.js:105088 -msgid "Vertical" +msgid "Overlay Opacity" msgstr "" -#: assets/build/blocks.js:110994 -#: assets/build/blocks.js:105105 -msgid "Number of Columns" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +msgid "Overlay Type" msgstr "" -#: assets/build/blocks.js:111039 -#: assets/build/blocks.js:105160 -msgid "Single Choice Only" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +msgid "Image Overlay Color" msgstr "" -#: assets/build/blocks.js:111054 -#: assets/build/blocks.js:105178 -msgid "Use a smart tag like {get_input:country}. The first option whose title matches the resolved value will be preselected." +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +msgid "Image Position" msgstr "" -#: assets/build/blocks.js:111054 -#: assets/build/blocks.js:105182 -msgid "Use a smart tag like {get_input:colors} and pass pipe separated values in the URL (for example ?colors=Red|Blue). Every option whose title matches a value will be checked. You can also chain multiple smart tags separated by pipes." +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +msgid "Blend Mode" msgstr "" -#: assets/build/blocks.js:111485 -#: assets/build/blocks.js:105588 -msgid "Prefix Label" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +#: modules/gutenberg/build/blocks.js:4 +#: modules/gutenberg/build/blocks.js:6 +#: modules/gutenberg/build/blocks.js:8 +#: modules/gutenberg/build/blocks.js:9 +msgid "Normal" msgstr "" -#: assets/build/blocks.js:111500 -#: assets/build/blocks.js:105604 -msgid "Suffix Label" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +msgid "Multiply" msgstr "" -#: assets/build/blocks.js:111515 -#: assets/build/blocks.js:105620 -msgid "Number Format" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +msgid "Screen" msgstr "" -#: assets/build/blocks.js:111527 -#: assets/build/blocks.js:105633 -msgid "US Style (Eg: 9,999.99)" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +#: modules/gutenberg/build/blocks.js:8 +msgid "Overlay" msgstr "" -#: assets/build/blocks.js:111530 -#: assets/build/blocks.js:105637 -msgid "EU Style (Eg: 9.999,99)" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +msgid "Darken" msgstr "" -#: assets/build/blocks.js:111537 -#: assets/build/blocks.js:105648 -msgid "Minimum Value" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +msgid "Lighten" msgstr "" -#: assets/build/blocks.js:111562 -#: assets/build/blocks.js:105672 -msgid "Maximum Value" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +msgid "Color Dodge" msgstr "" -#: assets/build/blocks.js:111711 -#: assets/build/blocks.js:105806 -msgid "Payments Per Page" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +msgid "Saturation" msgstr "" -#: assets/build/blocks.js:111721 -#: assets/build/blocks.js:105815 -msgid "Show Subscriptions Section" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +msgid "Repeat-x" msgstr "" -#: assets/build/blocks.js:111728 -#: assets/build/blocks.js:105823 -msgid "Show a dedicated subscriptions section above payment history." +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +msgid "Repeat-y" msgstr "" -#: assets/build/blocks.js:111775 -#: assets/build/blocks.js:105870 -msgid "Payment Dashboard" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +#: modules/gutenberg/build/blocks.js:6 +#: modules/gutenberg/build/blocks.js:8 +msgid "Width" msgstr "" -#: assets/build/blocks.js:111779 -#: assets/build/blocks.js:105873 -msgid "View your payments and manage subscriptions in a single dashboard." +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +msgid "PX" msgstr "" -#: assets/build/blocks.js:111920 -#: assets/build/blocks.js:105983 -msgid "2 Payments" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +#: modules/gutenberg/build/blocks.js:6 +msgid "EM" msgstr "" -#: assets/build/blocks.js:111923 -#: assets/build/blocks.js:105987 -msgid "3 Payments" +#: assets/build/blocks.js:172 +msgid "Upgrade to Unlock" msgstr "" -#: assets/build/blocks.js:111926 -#: assets/build/blocks.js:105991 -msgid "4 Payments" +#: assets/build/blocks.js:172 +#: modules/gutenberg/build/blocks.js:4 +msgid "Close" msgstr "" -#: assets/build/blocks.js:111929 -#: assets/build/blocks.js:105995 -msgid "5 Payments" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +#: modules/gutenberg/build/blocks.js:6 +#: modules/gutenberg/build/blocks.js:9 +msgid "Padding" msgstr "" -#: assets/build/blocks.js:111935 -#: assets/build/blocks.js:106003 -msgid "Never" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +msgid "Border Radius" msgstr "" -#: assets/build/blocks.js:111940 -#: assets/build/blocks.js:106012 -msgid "Stop Subscription After" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +msgid "Button Alignment" msgstr "" -#: assets/build/blocks.js:111944 -#: assets/build/blocks.js:106016 -msgid "Choose when to automatically stop the subscription" +#: assets/build/blocks.js:172 +msgid "Change Form" msgstr "" -#: assets/build/blocks.js:111946 -#: assets/build/blocks.js:106023 -msgid "Number of Payments" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +msgid "Form Settings" msgstr "" -#: assets/build/blocks.js:111957 -#: assets/build/blocks.js:106034 -msgid "Enter a number between 1 to 100" +#: assets/build/blocks.js:172 +msgid "Show Form Title on this Page" msgstr "" -#. translators: %1$s: a comma-separated list of missing field names -#: assets/build/blocks.js:112129 -#: assets/build/blocks.js:106221 -#, js-format -msgid "%1$s fields are required. Please configure these fields in the block settings." +#: assets/build/blocks.js:172 +msgid "Custom (Premium)" msgstr "" -#. translators: %1$s: the missing field name -#: assets/build/blocks.js:112132 -#: assets/build/blocks.js:106230 -#, js-format -msgid "%1$s field is required. Please configure this field in the block settings." +#: assets/build/blocks.js:172 +msgid "Select a theme style for this form embed." msgstr "" -#: assets/build/blocks.js:112144 -#: assets/build/blocks.js:106253 -msgid "You need to configure a payment account to collect payments from this form. Please configure your payment provider to proceed." +#: assets/build/blocks.js:172 +msgid "Note: For editing SureForms, please refer to the SureForms Editor - " msgstr "" -#: assets/build/blocks.js:112148 -#: assets/build/blocks.js:106263 -msgid "Configure Payment Account" +#: assets/build/blocks.js:172 +msgid "Colors" msgstr "" -#: assets/build/blocks.js:112181 -#: assets/build/blocks.js:106306 -msgid "This is a placeholder for the Payment block. The actual payment fields for your configured payment provider(s) will only appear when you preview or publish the form." +#: assets/build/blocks.js:172 +msgid "Advanced Styling" msgstr "" -#: assets/build/blocks.js:112333 -#: assets/build/blocks.js:106415 -msgid "Form Field" +#: assets/build/blocks.js:172 +msgid "Unlock Custom Styling" msgstr "" -#: assets/build/blocks.js:112442 -#: assets/build/blocks.js:106518 -msgid "Payment Description" +#: assets/build/blocks.js:172 +msgid "Switch to Custom Mode to take full control of your form's design and spacing." msgstr "" -#: assets/build/blocks.js:112453 -#: assets/build/blocks.js:106527 -msgid "Shown on payment receipts and in your payment dashboard (Stripe and PayPal). Leave blank to use the default." +#: assets/build/blocks.js:172 +msgid "Full color control (buttons, fields, text)" msgstr "" -#: assets/build/blocks.js:112462 -#: assets/build/payments.js:172 -#: assets/build/blocks.js:106543 -msgid "Payment Type" +#: assets/build/blocks.js:172 +msgid "Row and column gap control" msgstr "" -#: assets/build/blocks.js:112477 -#: assets/build/blocks.js:106560 -msgid "Both" +#: assets/build/blocks.js:172 +msgid "Field spacing and layout precision" msgstr "" -#: assets/build/blocks.js:112486 -#: assets/build/blocks.js:112748 -#: assets/build/blocks.js:106574 -#: assets/build/blocks.js:106995 -msgid "Subscription Plan Name" +#: assets/build/blocks.js:172 +msgid "Complete button styling" msgstr "" -#: assets/build/blocks.js:112505 -#: assets/build/blocks.js:112769 -#: assets/build/blocks.js:106602 -#: assets/build/blocks.js:107023 -msgid "Billing Interval" +#: assets/build/blocks.js:172 +msgid "Field preview" msgstr "" -#: assets/build/blocks.js:112508 -#: assets/build/blocks.js:112772 -#: assets/build/blocks.js:106606 -#: assets/build/blocks.js:107026 -msgid "Daily" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +#: modules/gutenberg/build/blocks.js:4 +msgid "General" msgstr "" -#: assets/build/blocks.js:112511 -#: assets/build/blocks.js:112775 -#: assets/build/blocks.js:106610 -#: assets/build/blocks.js:107027 -msgid "Weekly" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +#: modules/gutenberg/build/blocks.js:4 +#: modules/gutenberg/build/blocks.js:6 +#: modules/gutenberg/build/blocks.js:8 +msgid "Style" msgstr "" -#: assets/build/blocks.js:112514 -#: assets/build/blocks.js:112778 -#: assets/build/blocks.js:106614 -#: assets/build/blocks.js:107028 -msgid "Monthly" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:2 +#: assets/build/settings.js:2 +msgid "No tags available" msgstr "" -#: assets/build/blocks.js:112517 -#: assets/build/blocks.js:112781 -#: assets/build/blocks.js:106618 -#: assets/build/blocks.js:107029 -msgid "Quarterly" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +msgid "Select Shortcodes" msgstr "" -#: assets/build/blocks.js:112520 -#: assets/build/blocks.js:112784 -#: assets/build/blocks.js:106622 -#: assets/build/blocks.js:107030 -msgid "Yearly" +#: assets/build/blocks.js:172 +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Generic tags" msgstr "" -#: assets/build/blocks.js:112540 -#: assets/build/blocks.js:106655 -msgid "One-Time Label" +#: assets/build/blocks.js:172 +#: assets/build/dashboard.js:172 +#: assets/build/formEditor.js:172 +msgid "Premium" msgstr "" -#: assets/build/blocks.js:112551 -#: assets/build/blocks.js:106664 -msgid "Label shown to users for the one-time payment option." +#: assets/build/blocks.js:172 +#: assets/build/dashboard.js:172 +msgid "Conditional Logic" msgstr "" -#: assets/build/blocks.js:112556 -#: assets/build/blocks.js:106675 -msgid "Subscription Label" +#: assets/build/blocks.js:172 +msgid "Unlock Conditional Logic Editor" msgstr "" -#: assets/build/blocks.js:112567 -#: assets/build/blocks.js:106684 -msgid "Label shown to users for the subscription option." +#: assets/build/blocks.js:172 +msgid "Upgrade to the SureForms Starter Plan to create dynamic forms that adapt based on user input, offering a personalised and efficient form experience." msgstr "" -#: assets/build/blocks.js:112573 -#: assets/build/blocks.js:106696 -msgid "Default Selection" +#: assets/build/blocks.js:172 +msgid "Enable Conditional Logic" msgstr "" -#: assets/build/blocks.js:112586 -#: assets/build/blocks.js:106712 -msgid "Which option is pre-selected when the form loads." +#: assets/build/blocks.js:172 +msgid "this field if" msgstr "" -#: assets/build/blocks.js:112595 -#: assets/build/blocks.js:106728 -msgid "One-Time Amount Type" +#: assets/build/blocks.js:172 +msgid "Configure Conditions" msgstr "" -#: assets/build/blocks.js:112602 -#: assets/build/blocks.js:112679 -#: assets/build/blocks.js:112818 -#: assets/build/blocks.js:112829 -#: assets/build/blocks.js:106736 -#: assets/build/blocks.js:106870 -#: assets/build/blocks.js:107076 -#: assets/build/blocks.js:107097 -msgid "Fixed Amount" +#: assets/build/blocks.js:172 +msgid "Required" msgstr "" -#: assets/build/blocks.js:112605 -#: assets/build/blocks.js:112682 -#: assets/build/blocks.js:112821 -#: assets/build/blocks.js:106740 -#: assets/build/blocks.js:106874 -#: assets/build/blocks.js:107080 -msgid "Dynamic Amount" +#: assets/build/blocks.js:172 +msgid "Error Message" msgstr "" -#: assets/build/blocks.js:112608 -#: assets/build/blocks.js:106744 -msgid "Set how the one-time payment amount is determined." +#: assets/build/blocks.js:172 +msgid "Help Text" msgstr "" -#: assets/build/blocks.js:112613 -#: assets/build/blocks.js:106757 -msgid "One-Time Fixed Amount" +#: assets/build/blocks.js:172 +msgid "Default Value" msgstr "" -#: assets/build/blocks.js:112625 -#: assets/build/blocks.js:106773 -msgid "Amount charged for a one-time payment." +#: assets/build/blocks.js:172 +msgid "Color Picker" msgstr "" -#: assets/build/blocks.js:112630 -#: assets/build/blocks.js:106788 -msgid "One-Time Amount Field" +#: assets/build/blocks.js:172 +msgid "Use Text Field as Color Picker" msgstr "" -#: assets/build/blocks.js:112633 -#: assets/build/blocks.js:112710 -#: assets/build/blocks.js:112850 -#: assets/build/blocks.js:112896 -#: assets/build/blocks.js:112920 -#: assets/build/blocks.js:106795 -#: assets/build/blocks.js:106931 -#: assets/build/blocks.js:107132 -#: assets/build/blocks.js:107211 -#: assets/build/blocks.js:107252 -msgid "Select a fieldโ€ฆ" +#: assets/build/blocks.js:172 +msgid "Upgrade to the SureForms Pro Plan to use the Text field as a color picker." msgstr "" -#: assets/build/blocks.js:112646 -#: assets/build/blocks.js:106814 -msgid "Pick a form field whose value determines the one-time payment amount." +#: assets/build/blocks.js:172 +msgid "Input Pattern" msgstr "" -#: assets/build/blocks.js:112651 -#: assets/build/blocks.js:106825 -msgid "One-Time Minimum Amount" +#: assets/build/blocks.js:172 +msgid "(###) ###-####" msgstr "" -#: assets/build/blocks.js:112663 -#: assets/build/blocks.js:106841 -msgid "Minimum amount users can enter for one-time payment (0 for no minimum)." +#: assets/build/blocks.js:172 +msgid "(##) ####-####" msgstr "" -#: assets/build/blocks.js:112672 -#: assets/build/blocks.js:106859 -msgid "Subscription Amount Type" +#: assets/build/blocks.js:172 +msgid "27/08/2024" msgstr "" -#: assets/build/blocks.js:112685 -#: assets/build/blocks.js:106878 -msgid "Set how the subscription amount is determined." +#: assets/build/blocks.js:172 +msgid "23:59:59" msgstr "" -#: assets/build/blocks.js:112690 -#: assets/build/blocks.js:106891 -msgid "Subscription Fixed Amount" +#: assets/build/blocks.js:172 +msgid "27/08/2024 23:59:59" msgstr "" -#: assets/build/blocks.js:112702 -#: assets/build/blocks.js:106907 -msgid "Recurring amount charged per billing interval." +#: assets/build/blocks.js:172 +msgid "Custom Mask" msgstr "" -#: assets/build/blocks.js:112707 -#: assets/build/blocks.js:106922 -msgid "Subscription Amount Field" +#: assets/build/blocks.js:172 +msgid "Please check the documentation to manage custom input pattern " msgstr "" -#: assets/build/blocks.js:112723 -#: assets/build/blocks.js:106951 -msgid "Pick a form field whose value determines the subscription amount." +#: assets/build/blocks.js:172 +msgid "here" msgstr "" -#: assets/build/blocks.js:112728 -#: assets/build/blocks.js:106962 -msgid "Subscription Minimum Amount" +#: assets/build/blocks.js:172 +msgid "Read Only" msgstr "" -#: assets/build/blocks.js:112740 -#: assets/build/blocks.js:106978 -msgid "Minimum amount users can enter for subscription (0 for no minimum)." +#: assets/build/blocks.js:172 +msgid "Unique Entry" msgstr "" -#: assets/build/blocks.js:112811 -#: assets/build/blocks.js:107068 -msgid "Amount Type" +#: assets/build/blocks.js:172 +msgid "Validation Message for Duplicate" msgstr "" -#: assets/build/blocks.js:112824 -#: assets/build/blocks.js:107084 -msgid "Choose whether to charge a fixed amount or charge the amount based on user input in other form fields." +#: assets/build/blocks.js:172 +msgid "Maximum Characters" msgstr "" -#: assets/build/blocks.js:112841 -#: assets/build/blocks.js:107109 -msgid "Set the exact amount you want to charge. Users wonโ€™t be able to change it" +#: assets/build/blocks.js:172 +msgid "Attributes" msgstr "" -#: assets/build/blocks.js:112847 -#: assets/build/blocks.js:107125 -msgid "Choose Amount Field" +#: assets/build/blocks.js:172 +msgid "Prefix Label" msgstr "" -#: assets/build/blocks.js:112863 -#: assets/build/blocks.js:107151 -msgid "Pick a field from your form like a number, dropdown, multichoice, or hidden whose value should decide the payment amount." +#: assets/build/blocks.js:172 +msgid "Suffix Label" msgstr "" -#: assets/build/blocks.js:112868 -#: assets/build/blocks.js:107162 -msgid "Minimum Amount" +#: assets/build/blocks.js:172 +msgid "Number Format" msgstr "" -#: assets/build/blocks.js:112880 -#: assets/build/blocks.js:107174 -msgid "Set the minimum amount users can enter (0 for no minimum)" +#: assets/build/blocks.js:172 +msgid "US Style (Eg: 9,999.99)" msgstr "" -#: assets/build/blocks.js:112893 -#: assets/build/blocks.js:107199 -msgid "Customer Name Field (Required)" +#: assets/build/blocks.js:172 +msgid "EU Style (Eg: 9.999,99)" msgstr "" -#: assets/build/blocks.js:112893 -#: assets/build/blocks.js:107203 -msgid "Customer Name Field (Optional)" +#: assets/build/blocks.js:172 +msgid "Minimum Value" msgstr "" -#: assets/build/blocks.js:112911 -#: assets/build/blocks.js:107228 -msgid "Select the input field that contains the customer name (Required for subscriptions)" +#: assets/build/blocks.js:172 +msgid "Maximum Value" msgstr "" -#: assets/build/blocks.js:112911 -#: assets/build/blocks.js:107232 -msgid "Select the input field that contains the customer name" +#: assets/build/blocks.js:172 +msgid "Please check the Minimum and Maximum value" msgstr "" -#: assets/build/blocks.js:112917 -#: assets/build/blocks.js:107245 -msgid "Customer Email Field (Required)" +#: assets/build/blocks.js:172 +msgid "Enable Email Confirmation" msgstr "" -#: assets/build/blocks.js:112933 -#: assets/build/blocks.js:107265 -msgid "Select the email field that contains the customer email" +#: assets/build/blocks.js:172 +msgid "Rich Text Editor" msgstr "" -#: assets/build/blocks.js:113265 -#: assets/build/blocks.js:107539 -msgid "Select Country" +#: assets/build/blocks.js:172 +msgid "Minimum Characters" msgstr "" -#: assets/build/blocks.js:113403 -#: assets/build/blocks.js:107689 -msgid "Enable Auto Country Detection" +#: assets/build/blocks.js:172 +msgid "Minimum characters cannot exceed Maximum characters." msgstr "" -#: assets/build/blocks.js:113411 -#: assets/build/blocks.js:107700 -msgid "Default Country" +#: assets/build/blocks.js:172 +msgid "Textarea Height" msgstr "" -#: assets/build/blocks.js:113419 -#: assets/build/blocks.js:107713 -msgid "Restrict Country Codes" +#: assets/build/blocks.js:172 +msgid "Checked by Default" msgstr "" -#: assets/build/blocks.js:113428 -#: assets/build/blocks.js:107728 -msgid "Restriction Type" +#: assets/build/blocks.js:172 +msgid "Checked by default" msgstr "" -#: assets/build/blocks.js:113435 -#: assets/build/blocks.js:107739 -msgid "Allow" +#: assets/build/blocks.js:172 +#: modules/gutenberg/build/blocks.js:4 +msgid "Icon Library" msgstr "" -#: assets/build/blocks.js:113438 -#: assets/build/blocks.js:107746 -msgid "Block" +#: assets/build/blocks.js:172 +#: modules/gutenberg/build/blocks.js:4 +msgid "Search" msgstr "" -#: assets/build/blocks.js:113443 -#: assets/build/blocks.js:107757 -msgid "Select Allowed Countries" +#: assets/build/blocks.js:172 +#: modules/gutenberg/build/blocks.js:4 +msgid "All Icons" msgstr "" -#: assets/build/blocks.js:113449 -#: assets/build/blocks.js:113468 -#: assets/build/blocks.js:107772 -#: assets/build/blocks.js:107814 -msgid "Choose countriesโ€ฆ" +#: assets/build/blocks.js:172 +#: assets/build/settings.js:172 +#: modules/gutenberg/build/blocks.js:4 +msgid "Other" msgstr "" -#: assets/build/blocks.js:113460 -#: assets/build/blocks.js:107789 -msgid "Choose which country codes users can select in the phone number field. Leave empty to allow all country codes." +#: assets/build/blocks.js:172 +#: modules/gutenberg/build/blocks.js:4 +msgid "No Icons Found" msgstr "" -#: assets/build/blocks.js:113462 -#: assets/build/blocks.js:107799 -msgid "Select Blocked Countries" +#: assets/build/blocks.js:172 +#: modules/gutenberg/build/blocks.js:4 +msgid "Insert Icon" msgstr "" -#: assets/build/blocks.js:113479 -#: assets/build/blocks.js:107831 -msgid "These countries will be hidden from the dropdown." +#: assets/build/blocks.js:172 +#: modules/gutenberg/build/blocks.js:4 +msgid "Change Icon" msgstr "" -#: assets/build/blocks.js:113918 -#: assets/build/blocks.js:113977 -#: assets/build/blocks.js:108264 -#: assets/build/blocks.js:108368 -msgid "Change Form" +#: assets/build/blocks.js:172 +#: modules/gutenberg/build/blocks.js:4 +msgid "Choose Icon" msgstr "" -#: assets/build/blocks.js:113928 -#: assets/build/formEditor.js:122342 -#: assets/build/blocks.js:108289 -#: assets/build/formEditor.js:111591 -msgid "Form Settings" +#: assets/build/blocks.js:172 +msgid "Bulk Add" msgstr "" -#: assets/build/blocks.js:113930 -#: assets/build/blocks.js:108292 -msgid "Show Form Title on this Page" +#: assets/build/blocks.js:172 +msgid "Bulk Add Options" msgstr "" -#: assets/build/blocks.js:113957 -#: assets/build/blocks.js:108333 -msgid "Custom (Premium)" +#: assets/build/blocks.js:172 +msgid "Enter each option on a new line." msgstr "" -#: assets/build/blocks.js:113970 -#: assets/build/blocks.js:108345 -msgid "Select a theme style for this form embed." +#: assets/build/blocks.js:172 +msgid "Insert Options" msgstr "" -#: assets/build/blocks.js:113973 -#: assets/build/blocks.js:108353 -msgid "Note: For editing SureForms, please refer to the SureForms Editor - " +#: assets/build/blocks.js:172 +msgid "Bulk Edit" msgstr "" -#: assets/build/blocks.js:113985 -#: assets/build/blocks.js:108382 -msgid "Colors" +#: assets/build/blocks.js:172 +msgid "Minimum Selections" msgstr "" -#: assets/build/blocks.js:114038 -#: assets/build/blocks.js:108487 -msgid "Advanced Styling" +#: assets/build/blocks.js:172 +msgid "Maximum Selections" msgstr "" -#: assets/build/blocks.js:114039 -#: assets/build/blocks.js:108488 -msgid "Unlock Custom Styling" +#: assets/build/blocks.js:172 +msgid "Preselect this option" msgstr "" -#: assets/build/blocks.js:114040 -#: assets/build/blocks.js:108489 -msgid "Switch to Custom Mode to take full control of your form's design and spacing." +#: assets/build/blocks.js:172 +msgid "Option Type" msgstr "" -#: assets/build/blocks.js:114041 -#: assets/build/blocks.js:108494 -msgid "Full color control (buttons, fields, text)" +#: assets/build/blocks.js:172 +msgid "Edit Options" msgstr "" -#: assets/build/blocks.js:114041 -#: assets/build/blocks.js:108498 -msgid "Row and column gap control" +#: assets/build/blocks.js:172 +msgid "Add New Option" msgstr "" -#: assets/build/blocks.js:114041 -#: assets/build/blocks.js:108499 -msgid "Field spacing and layout precision" +#: assets/build/blocks.js:172 +msgid "ADD" msgstr "" -#: assets/build/blocks.js:114041 -#: assets/build/blocks.js:108500 -msgid "Complete button styling" +#: assets/build/blocks.js:172 +msgid "Select Layout" msgstr "" -#: assets/build/blocks.js:114175 -#: assets/build/blocks.js:108613 -msgid "Choose" +#: assets/build/blocks.js:172 +#: modules/gutenberg/build/blocks.js:6 +#: modules/gutenberg/build/blocks.js:8 +#: modules/gutenberg/build/blocks.js:9 +msgid "Horizontal" msgstr "" -#: assets/build/blocks.js:114183 -#: assets/build/blocks.js:108620 -msgid "Create New" +#: assets/build/blocks.js:172 +#: modules/gutenberg/build/blocks.js:6 +#: modules/gutenberg/build/blocks.js:8 +#: modules/gutenberg/build/blocks.js:9 +msgid "Vertical" msgstr "" -#: assets/build/blocks.js:114268 -#: assets/build/forms.js:63699 -#: assets/build/forms.js:64754 -#: assets/build/settings.js:75593 -#: assets/build/blocks.js:108668 -#: assets/build/forms.js:54805 -#: assets/build/forms.js:55734 -#: assets/build/settings.js:68084 -msgid "(no title)" +#: assets/build/blocks.js:172 +msgid "Number of Columns" msgstr "" -#: assets/build/blocks.js:114367 -#: assets/build/blocks.js:108744 -msgid "Select a Form" +#: assets/build/blocks.js:172 +msgid "Add Numeric Values to Options" msgstr "" -#: assets/build/blocks.js:114375 -#: assets/build/blocks.js:108762 -msgid "No forms foundโ€ฆ" +#: assets/build/blocks.js:172 +msgid "Single Choice Only" msgstr "" -#: assets/build/blocks.js:114567 -#: assets/build/formEditor.js:128435 -#: modules/gutenberg/build/blocks.js:6 -#: modules/gutenberg/build/blocks.js:9 -#: assets/build/blocks.js:108972 -#: assets/build/formEditor.js:118630 -msgid "Padding" +#: assets/build/blocks.js:172 +msgid "Dynamic Default Value" msgstr "" -#: assets/build/blocks.js:114598 -#: assets/build/formEditor.js:128465 -#: assets/build/blocks.js:109006 -#: assets/build/formEditor.js:118663 -msgid "Border Radius" +#: assets/build/blocks.js:172 +msgid "Use a smart tag like {get_input:country}. The first option whose title matches the resolved value will be preselected." msgstr "" -#: assets/build/blocks.js:114688 -#: assets/build/formEditor.js:128534 -#: assets/build/blocks.js:109108 -#: assets/build/formEditor.js:118750 -msgid "Button Alignment" +#: assets/build/blocks.js:172 +msgid "Use a smart tag like {get_input:colors} and pass pipe separated values in the URL (for example ?colors=Red|Blue). Every option whose title matches a value will be checked. You can also chain multiple smart tags separated by pipes." msgstr "" -#: assets/build/blocks.js:115204 -#: assets/build/blocks.js:109521 -msgid "Rich Text Editor" +#: assets/build/blocks.js:172 +msgid "Select Country" msgstr "" -#: assets/build/blocks.js:115215 -#: assets/build/blocks.js:109534 -msgid "Minimum Characters" +#: assets/build/blocks.js:172 +msgid "Enable Auto Country Detection" msgstr "" -#: assets/build/blocks.js:115229 -#: assets/build/blocks.js:109552 -msgid "Minimum characters cannot exceed Maximum characters." +#: assets/build/blocks.js:172 +msgid "Default Country" msgstr "" -#: assets/build/blocks.js:115246 -#: assets/build/blocks.js:109576 -msgid "Textarea Height" +#: assets/build/blocks.js:172 +msgid "Restrict Country Codes" msgstr "" -#: assets/build/blocks.js:116090 -#: assets/build/blocks.js:110329 -msgid "Bulk Add" +#: assets/build/blocks.js:172 +msgid "Restriction Type" msgstr "" -#: assets/build/blocks.js:116102 -#: assets/build/blocks.js:110337 -msgid "Bulk Add Options" +#: assets/build/blocks.js:172 +msgid "Allow" msgstr "" -#: assets/build/blocks.js:116112 -#: assets/build/blocks.js:110350 -msgid "Enter each option on a new line." +#: assets/build/blocks.js:172 +msgid "Block" msgstr "" -#: assets/build/blocks.js:116127 -#: assets/build/blocks.js:118500 -#: assets/build/blocks.js:119876 -#: assets/build/dashboard.js:96058 -#: assets/build/entries.js:67365 -#: assets/build/formEditor.js:120084 -#: assets/build/formEditor.js:125749 -#: assets/build/formEditor.js:125753 -#: assets/build/formEditor.js:130685 -#: assets/build/formEditor.js:131518 -#: assets/build/formEditor.js:132810 -#: assets/build/forms.js:62220 -#: assets/build/forms.js:63857 -#: assets/build/forms.js:65265 -#: assets/build/payments.js:2 -#: assets/build/payments.js:172 -#: assets/build/settings.js:71487 -#: modules/gutenberg/build/blocks.js:6 -#: assets/build/blocks.js:110371 -#: assets/build/blocks.js:112899 -#: assets/build/blocks.js:114403 -#: assets/build/dashboard.js:82346 -#: assets/build/entries.js:58426 -#: assets/build/formEditor.js:109226 -#: assets/build/formEditor.js:115412 -#: assets/build/formEditor.js:115421 -#: assets/build/formEditor.js:121043 -#: assets/build/formEditor.js:121824 -#: assets/build/formEditor.js:123230 -#: assets/build/forms.js:53452 -#: assets/build/forms.js:55007 -#: assets/build/forms.js:56254 -#: assets/build/settings.js:63774 -msgid "Cancel" +#: assets/build/blocks.js:172 +msgid "Select Allowed Countries" msgstr "" -#: assets/build/blocks.js:116131 -#: assets/build/blocks.js:110378 -msgid "Insert Options" +#: assets/build/blocks.js:172 +msgid "Choose countriesโ€ฆ" msgstr "" -#: assets/build/blocks.js:116169 -#: assets/build/blocks.js:110418 -msgid "Bulk Edit" +#: assets/build/blocks.js:172 +msgid "Choose which country codes users can select in the phone number field. Leave empty to allow all country codes." msgstr "" -#: assets/build/blocks.js:116440 -#: assets/build/formEditor.js:129797 -#: assets/build/formEditor.js:130685 -#: modules/gutenberg/build/blocks.js:4 -#: assets/build/blocks.js:110718 -#: assets/build/formEditor.js:119968 -#: assets/build/formEditor.js:121042 -msgid "Clear" +#: assets/build/blocks.js:172 +msgid "Select Blocked Countries" msgstr "" -#: assets/build/blocks.js:116441 -#: assets/build/blocks.js:116456 -#: assets/build/formEditor.js:129798 -#: assets/build/formEditor.js:129813 -#: modules/gutenberg/build/blocks.js:4 -#: assets/build/blocks.js:110723 -#: assets/build/blocks.js:110750 -#: assets/build/formEditor.js:119973 -#: assets/build/formEditor.js:120000 -msgid "Select Color" +#: assets/build/blocks.js:172 +msgid "These countries will be hidden from the dropdown." msgstr "" -#: assets/build/blocks.js:116682 -#: assets/build/dashboard.js:96415 -#: assets/build/blocks.js:110933 -#: assets/build/dashboard.js:82741 -msgid "Conditional Logic" +#: assets/build/blocks.js:172 +msgid "Enable Dropdown Search" msgstr "" -#: assets/build/blocks.js:116683 -#: assets/build/blocks.js:110936 -msgid "Unlock Conditional Logic Editor" +#: assets/build/blocks.js:172 +msgid "Allow Multiple" msgstr "" -#: assets/build/blocks.js:116684 -#: assets/build/blocks.js:110940 -msgid "Upgrade to the SureForms Starter Plan to create dynamic forms that adapt based on user input, offering a personalised and efficient form experience." +#: assets/build/blocks.js:172 +msgid "Use a smart tag like {get_input:colors} and pass pipe separated values in the URL (for example ?colors=Red|Blue). Every option whose label matches a value will be preselected. You can also chain multiple smart tags separated by pipes." msgstr "" -#: assets/build/blocks.js:116690 -#: assets/build/blocks.js:110952 -msgid "Enable Conditional Logic" +#: assets/build/blocks.js:172 +msgid "Use a smart tag like {get_input:country}. The first option whose label matches the resolved value will be preselected." msgstr "" -#: assets/build/blocks.js:116706 -#: assets/build/blocks.js:110972 -msgid "this field if" +#: assets/build/blocks.js:172 +msgid "Location Services" msgstr "" -#: assets/build/blocks.js:116712 -#: assets/build/blocks.js:110981 -msgid "Configure Conditions" +#: assets/build/blocks.js:172 +msgid "Unlock Address Autocomplete" msgstr "" -#: assets/build/blocks.js:116929 -#: assets/build/formEditor.js:130193 -#: modules/gutenberg/build/blocks.js:6 -#: assets/build/blocks.js:111170 -#: assets/build/formEditor.js:120322 -msgid "Classic" +#: assets/build/blocks.js:172 +msgid "Upgrade to enable Google Address Autocomplete with interactive map preview, making address entry faster and more accurate for your users." msgstr "" -#: assets/build/blocks.js:116977 -#: assets/build/formEditor.js:130241 -#: modules/gutenberg/build/blocks.js:8 -#: assets/build/blocks.js:111235 -#: assets/build/formEditor.js:120387 -msgid "Overlay Opacity" +#: assets/build/blocks.js:172 +msgid "Enable Google Autocomplete" msgstr "" -#: assets/build/blocks.js:117010 -#: assets/build/blocks.js:117218 -#: assets/build/formEditor.js:130274 -#: assets/build/formEditor.js:130482 -#: assets/build/blocks.js:111275 -#: assets/build/blocks.js:111629 -#: assets/build/formEditor.js:120427 -#: assets/build/formEditor.js:120781 -msgid "Image Position" +#: assets/build/blocks.js:172 +msgid "Show Interactive Map" msgstr "" -#: assets/build/blocks.js:117036 -#: assets/build/formEditor.js:130300 -#: assets/build/blocks.js:111315 -#: assets/build/formEditor.js:120467 -msgid "Blend Mode" +#: assets/build/blocks.js:172 +#, js-format +msgid "%1$s fields are required. Please configure these fields in the block settings." msgstr "" -#: assets/build/blocks.js:117043 -#: assets/build/formEditor.js:130307 -#: modules/gutenberg/build/blocks.js:4 -#: modules/gutenberg/build/blocks.js:6 -#: modules/gutenberg/build/blocks.js:8 -#: modules/gutenberg/build/blocks.js:9 -#: assets/build/blocks.js:111325 -#: assets/build/formEditor.js:120477 -msgid "Normal" +#: assets/build/blocks.js:172 +#, js-format +msgid "%1$s field is required. Please configure this field in the block settings." msgstr "" -#: assets/build/blocks.js:117046 -#: assets/build/formEditor.js:130310 -#: assets/build/blocks.js:111329 -#: assets/build/formEditor.js:120481 -msgid "Multiply" +#: assets/build/blocks.js:172 +msgid "You need to configure a payment account to collect payments from this form. Please configure your payment provider to proceed." msgstr "" -#: assets/build/blocks.js:117049 -#: assets/build/formEditor.js:130313 -#: assets/build/blocks.js:111336 -#: assets/build/formEditor.js:120488 -msgid "Screen" +#: assets/build/blocks.js:172 +msgid "Configure Payment Account" msgstr "" -#: assets/build/blocks.js:117052 -#: assets/build/formEditor.js:130316 -#: modules/gutenberg/build/blocks.js:8 -#: assets/build/blocks.js:111340 -#: assets/build/formEditor.js:120492 -msgid "Overlay" +#: assets/build/blocks.js:172 +msgid "This is a placeholder for the Payment block. The actual payment fields for your configured payment provider(s) will only appear when you preview or publish the form." msgstr "" -#: assets/build/blocks.js:117055 -#: assets/build/formEditor.js:130319 -#: assets/build/blocks.js:111344 -#: assets/build/formEditor.js:120496 -msgid "Darken" +#: assets/build/blocks.js:172 +msgid "2 Payments" msgstr "" -#: assets/build/blocks.js:117058 -#: assets/build/formEditor.js:130322 -#: assets/build/blocks.js:111348 -#: assets/build/formEditor.js:120500 -msgid "Lighten" +#: assets/build/blocks.js:172 +msgid "3 Payments" msgstr "" -#: assets/build/blocks.js:117061 -#: assets/build/formEditor.js:130325 -#: assets/build/blocks.js:111352 -#: assets/build/formEditor.js:120504 -msgid "Color Dodge" +#: assets/build/blocks.js:172 +msgid "4 Payments" msgstr "" -#: assets/build/blocks.js:117064 -#: assets/build/formEditor.js:130328 -#: assets/build/blocks.js:111359 -#: assets/build/formEditor.js:120511 -msgid "Saturation" +#: assets/build/blocks.js:172 +msgid "5 Payments" msgstr "" -#: assets/build/blocks.js:117086 -#: assets/build/blocks.js:117257 -#: assets/build/formEditor.js:130350 -#: assets/build/formEditor.js:130521 -#: assets/build/blocks.js:111396 -#: assets/build/blocks.js:111690 -#: assets/build/formEditor.js:120548 -#: assets/build/formEditor.js:120842 -msgid "Repeat-x" +#: assets/build/blocks.js:172 +msgid "Never" msgstr "" -#: assets/build/blocks.js:117089 -#: assets/build/blocks.js:117260 -#: assets/build/formEditor.js:130353 -#: assets/build/formEditor.js:130524 -#: assets/build/blocks.js:111403 -#: assets/build/blocks.js:111697 -#: assets/build/formEditor.js:120555 -#: assets/build/formEditor.js:120849 -msgid "Repeat-y" +#: assets/build/blocks.js:172 +msgid "Stop Subscription After" msgstr "" -#: assets/build/blocks.js:117102 -#: assets/build/blocks.js:117273 -#: assets/build/formEditor.js:130366 -#: assets/build/formEditor.js:130537 -#: modules/gutenberg/build/blocks.js:6 -#: modules/gutenberg/build/blocks.js:8 -#: assets/build/blocks.js:111427 -#: assets/build/blocks.js:111720 -#: assets/build/formEditor.js:120579 -#: assets/build/formEditor.js:120872 -msgid "Width" +#: assets/build/blocks.js:172 +msgid "Choose when to automatically stop the subscription" msgstr "" -#: assets/build/blocks.js:117119 -#: assets/build/blocks.js:117290 -#: assets/build/formEditor.js:130383 -#: assets/build/formEditor.js:130554 -#: assets/build/blocks.js:111447 -#: assets/build/blocks.js:111740 -#: assets/build/formEditor.js:120599 -#: assets/build/formEditor.js:120892 -msgid "PX" +#: assets/build/blocks.js:172 +msgid "Number of Payments" msgstr "" -#: assets/build/blocks.js:117122 -#: assets/build/blocks.js:117293 -#: assets/build/blocks.js:121313 -#: assets/build/formEditor.js:130386 -#: assets/build/formEditor.js:130557 -#: assets/build/formEditor.js:133856 -#: modules/gutenberg/build/blocks.js:4 -#: modules/gutenberg/build/blocks.js:6 -#: modules/gutenberg/build/blocks.js:8 -#: assets/build/blocks.js:111454 -#: assets/build/blocks.js:111747 -#: assets/build/blocks.js:115796 -#: assets/build/formEditor.js:120606 -#: assets/build/formEditor.js:120899 -#: assets/build/formEditor.js:124281 -msgid "%" +#: assets/build/blocks.js:172 +msgid "Enter a number between 1 to 100" msgstr "" -#: assets/build/blocks.js:117125 -#: assets/build/blocks.js:117296 -#: assets/build/formEditor.js:130389 -#: assets/build/formEditor.js:130560 -#: modules/gutenberg/build/blocks.js:6 -#: assets/build/blocks.js:111461 -#: assets/build/blocks.js:111754 -#: assets/build/formEditor.js:120613 -#: assets/build/formEditor.js:120906 -msgid "EM" +#: assets/build/blocks.js:172 +msgid "Form Field" msgstr "" -#: assets/build/blocks.js:117138 -#: assets/build/formEditor.js:130402 -#: assets/build/blocks.js:111489 -#: assets/build/formEditor.js:120641 -msgid "Overlay Type" +#: assets/build/blocks.js:172 +msgid "Payment Description" msgstr "" -#: assets/build/blocks.js:117151 -#: assets/build/formEditor.js:130415 -#: assets/build/blocks.js:111512 -#: assets/build/formEditor.js:120664 -msgid "Image Overlay Color" +#: assets/build/blocks.js:172 +msgid "Shown on payment receipts and in your payment dashboard (Stripe and PayPal). Leave blank to use the default." msgstr "" -#: assets/build/blocks.js:117486 -#: assets/build/formEditor.js:131125 -#: assets/build/blocks.js:111933 -#: assets/build/formEditor.js:121410 -msgid "Select Gradient" +#: assets/build/blocks.js:172 +#: assets/build/payments.js:172 +msgid "Payment Type" msgstr "" -#: assets/build/blocks.js:117493 -#: assets/build/formEditor.js:131132 -#: modules/gutenberg/build/blocks.js:6 -#: assets/build/blocks.js:111941 -#: assets/build/formEditor.js:121418 -msgid "Basic" +#: assets/build/blocks.js:172 +msgid "Both" msgstr "" -#: assets/build/blocks.js:117496 -#: assets/build/blocks.js:118879 -#: assets/build/formEditor.js:128623 -#: assets/build/formEditor.js:131135 -#: assets/build/formEditor.js:131897 -#: modules/gutenberg/build/blocks.js:4 -#: modules/gutenberg/build/blocks.js:6 -#: assets/build/blocks.js:111945 -#: assets/build/blocks.js:113401 -#: assets/build/formEditor.js:118868 -#: assets/build/formEditor.js:121422 -#: assets/build/formEditor.js:122326 -msgid "Advanced" +#: assets/build/blocks.js:172 +msgid "Subscription Plan Name" msgstr "" -#: assets/build/blocks.js:117837 -#: modules/gutenberg/build/blocks.js:4 -#: assets/build/blocks.js:112260 -msgid "Icon Library" +#: assets/build/blocks.js:172 +msgid "Billing Interval" msgstr "" -#: assets/build/blocks.js:117843 -#: modules/gutenberg/build/blocks.js:4 -#: assets/build/blocks.js:112266 -msgid "Search" +#: assets/build/blocks.js:172 +msgid "Daily" msgstr "" -#: assets/build/blocks.js:117942 -#: modules/gutenberg/build/blocks.js:4 -#: assets/build/blocks.js:112334 -msgid "Change Icon" +#: assets/build/blocks.js:172 +msgid "Weekly" msgstr "" -#: assets/build/blocks.js:117942 -#: modules/gutenberg/build/blocks.js:4 -#: assets/build/blocks.js:112335 -msgid "Choose Icon" +#: assets/build/blocks.js:172 +msgid "Monthly" msgstr "" -#: assets/build/blocks.js:118120 -#: modules/gutenberg/build/blocks.js:4 -#: assets/build/blocks.js:112475 -msgid "No Icons Found" +#: assets/build/blocks.js:172 +msgid "Quarterly" msgstr "" -#: assets/build/blocks.js:118183 -#: modules/gutenberg/build/blocks.js:4 -#: assets/build/blocks.js:112559 -msgid "All Icons" +#: assets/build/blocks.js:172 +msgid "Yearly" msgstr "" -#: assets/build/blocks.js:118197 -#: assets/build/settings.js:77789 -#: modules/gutenberg/build/blocks.js:4 -#: assets/build/blocks.js:112579 -#: assets/build/settings.js:70330 -msgid "Other" +#: assets/build/blocks.js:172 +msgid "One-Time Label" msgstr "" -#: assets/build/blocks.js:118206 -#: assets/build/blocks.js:121959 -#: modules/gutenberg/build/blocks.js:4 -#: assets/build/blocks.js:112591 -#: assets/build/blocks.js:116496 -msgid "Close" +#: assets/build/blocks.js:172 +msgid "Label shown to users for the one-time payment option." msgstr "" -#: assets/build/blocks.js:118232 -#: modules/gutenberg/build/blocks.js:4 -#: assets/build/blocks.js:112628 -msgid "Insert Icon" +#: assets/build/blocks.js:172 +msgid "Subscription Label" msgstr "" -#: assets/build/blocks.js:118425 -#: assets/build/formEditor.js:131443 -#: modules/gutenberg/build/blocks.js:6 -#: assets/build/blocks.js:112784 -#: assets/build/formEditor.js:121709 -msgid "Select Video" +#: assets/build/blocks.js:172 +msgid "Label shown to users for the subscription option." msgstr "" -#: assets/build/blocks.js:118426 -#: assets/build/formEditor.js:131444 -#: modules/gutenberg/build/blocks.js:6 -#: assets/build/blocks.js:112785 -#: assets/build/formEditor.js:121710 -msgid "Change Video" +#: assets/build/blocks.js:172 +msgid "Default Selection" msgstr "" -#: assets/build/blocks.js:118430 -#: assets/build/formEditor.js:131448 -#: modules/gutenberg/build/blocks.js:6 -#: assets/build/blocks.js:112789 -#: assets/build/formEditor.js:121714 -msgid "Select Lottie Animation" +#: assets/build/blocks.js:172 +msgid "Which option is pre-selected when the form loads." msgstr "" -#: assets/build/blocks.js:118431 -#: assets/build/formEditor.js:131449 -#: modules/gutenberg/build/blocks.js:6 -#: assets/build/blocks.js:112790 -#: assets/build/formEditor.js:121715 -msgid "Change Lottie Animation" +#: assets/build/blocks.js:172 +msgid "One-Time Amount Type" msgstr "" -#: assets/build/blocks.js:118435 -#: assets/build/formEditor.js:131453 -#: modules/gutenberg/build/blocks.js:6 -#: assets/build/blocks.js:112794 -#: assets/build/formEditor.js:121719 -msgid "Upload SVG" +#: assets/build/blocks.js:172 +msgid "Fixed Amount" msgstr "" -#: assets/build/blocks.js:118436 -#: assets/build/formEditor.js:131454 -#: modules/gutenberg/build/blocks.js:6 -#: assets/build/blocks.js:112795 -#: assets/build/formEditor.js:121720 -msgid "Change SVG" +#: assets/build/blocks.js:172 +msgid "Dynamic Amount" msgstr "" -#: assets/build/blocks.js:118439 -#: assets/build/formEditor.js:131457 -#: modules/gutenberg/build/blocks.js:6 -#: assets/build/blocks.js:112798 -#: assets/build/formEditor.js:121723 -msgid "Select Image" +#: assets/build/blocks.js:172 +msgid "Set how the one-time payment amount is determined." msgstr "" -#: assets/build/blocks.js:118440 -#: assets/build/formEditor.js:131458 -#: modules/gutenberg/build/blocks.js:6 -#: assets/build/blocks.js:112799 -#: assets/build/formEditor.js:121724 -msgid "Change Image" +#: assets/build/blocks.js:172 +msgid "One-Time Fixed Amount" msgstr "" -#: assets/build/blocks.js:118497 -#: assets/build/formEditor.js:131515 -#: modules/gutenberg/build/blocks.js:6 -#: assets/build/blocks.js:112893 -#: assets/build/formEditor.js:121818 -msgid "Upload SVG?" +#: assets/build/blocks.js:172 +msgid "Amount charged for a one-time payment." msgstr "" -#: assets/build/blocks.js:118498 -#: assets/build/formEditor.js:131516 -#: modules/gutenberg/build/blocks.js:6 -#: assets/build/blocks.js:112894 -#: assets/build/formEditor.js:121819 -msgid "Upload SVG can be potentially risky. Are you sure?" +#: assets/build/blocks.js:172 +msgid "One-Time Amount Field" msgstr "" -#: assets/build/blocks.js:118499 -#: assets/build/formEditor.js:131517 -#: modules/gutenberg/build/blocks.js:6 -#: assets/build/blocks.js:112898 -#: assets/build/formEditor.js:121823 -msgid "Upload Anyway" +#: assets/build/blocks.js:172 +msgid "Select a fieldโ€ฆ" msgstr "" -#: assets/build/blocks.js:118850 -#: assets/build/formEditor.js:127550 -#: assets/build/formEditor.js:131868 -#: assets/build/settings.js:74923 -#: modules/gutenberg/build/blocks.js:4 -#: assets/build/blocks.js:113360 -#: assets/build/formEditor.js:117501 -#: assets/build/formEditor.js:122285 -#: assets/build/settings.js:67357 -msgid "General" +#: assets/build/blocks.js:172 +msgid "Pick a form field whose value determines the one-time payment amount." msgstr "" -#: assets/build/blocks.js:118865 -#: assets/build/formEditor.js:131883 -#: modules/gutenberg/build/blocks.js:4 -#: modules/gutenberg/build/blocks.js:6 -#: modules/gutenberg/build/blocks.js:8 -#: assets/build/blocks.js:113380 -#: assets/build/formEditor.js:122305 -msgid "Style" +#: assets/build/blocks.js:172 +msgid "One-Time Minimum Amount" msgstr "" -#: assets/build/blocks.js:119013 -#: assets/build/blocks.js:113495 -msgid "Location Services" +#: assets/build/blocks.js:172 +msgid "Minimum amount users can enter for one-time payment (0 for no minimum)." msgstr "" -#: assets/build/blocks.js:119014 -#: assets/build/blocks.js:113498 -msgid "Unlock Address Autocomplete" +#: assets/build/blocks.js:172 +msgid "Subscription Amount Type" msgstr "" -#: assets/build/blocks.js:119015 -#: assets/build/blocks.js:113502 -msgid "Upgrade to enable Google Address Autocomplete with interactive map preview, making address entry faster and more accurate for your users." +#: assets/build/blocks.js:172 +msgid "Set how the subscription amount is determined." msgstr "" -#: assets/build/blocks.js:119021 -#: assets/build/blocks.js:113514 -msgid "Enable Google Autocomplete" +#: assets/build/blocks.js:172 +msgid "Subscription Fixed Amount" msgstr "" -#: assets/build/blocks.js:119025 -#: assets/build/blocks.js:113522 -msgid "Show Interactive Map" +#: assets/build/blocks.js:172 +msgid "Recurring amount charged per billing interval." msgstr "" -#: assets/build/blocks.js:119077 -#: assets/build/formEditor.js:132231 -#: assets/build/blocks.js:113575 -#: assets/build/formEditor.js:122634 -msgid "Select Shortcodes" +#: assets/build/blocks.js:172 +msgid "Subscription Amount Field" msgstr "" -#: assets/build/blocks.js:119300 -#: assets/build/formEditor.js:132536 -#: modules/gutenberg/build/blocks.js:4 -#: assets/build/blocks.js:113727 -#: assets/build/formEditor.js:122886 -msgid "Please add a option props to MultiButtonsControl" +#: assets/build/blocks.js:172 +msgid "Pick a form field whose value determines the subscription amount." msgstr "" -#: assets/build/blocks.js:119632 -#: assets/build/blocks.js:120025 -#: assets/build/blocks.js:121307 -#: assets/build/formEditor.js:132959 -#: assets/build/formEditor.js:133850 -#: modules/gutenberg/build/blocks.js:2 -#: modules/gutenberg/build/blocks.js:4 -#: modules/gutenberg/build/blocks.js:6 -#: modules/gutenberg/build/blocks.js:8 -#: assets/build/blocks.js:114138 -#: assets/build/blocks.js:114556 -#: assets/build/blocks.js:115788 -#: assets/build/formEditor.js:123383 -#: assets/build/formEditor.js:124273 -msgid "Pixel" +#: assets/build/blocks.js:172 +msgid "Subscription Minimum Amount" msgstr "" -#: assets/build/blocks.js:119635 -#: assets/build/blocks.js:120028 -#: assets/build/blocks.js:121310 -#: assets/build/formEditor.js:132962 -#: assets/build/formEditor.js:133853 -#: modules/gutenberg/build/blocks.js:2 -#: modules/gutenberg/build/blocks.js:4 -#: modules/gutenberg/build/blocks.js:6 -#: modules/gutenberg/build/blocks.js:8 -#: assets/build/blocks.js:114142 -#: assets/build/blocks.js:114560 -#: assets/build/blocks.js:115792 -#: assets/build/formEditor.js:123387 -#: assets/build/formEditor.js:124277 -msgid "Em" +#: assets/build/blocks.js:172 +msgid "Minimum amount users can enter for subscription (0 for no minimum)." msgstr "" -#. translators: abbreviation for units -#: assets/build/blocks.js:119676 -#: assets/build/blocks.js:119686 -#: assets/build/blocks.js:120082 -#: assets/build/blocks.js:120092 -#: assets/build/blocks.js:121324 -#: assets/build/blocks.js:121333 -#: assets/build/formEditor.js:133016 -#: assets/build/formEditor.js:133026 -#: assets/build/formEditor.js:133867 -#: assets/build/formEditor.js:133876 -#: modules/gutenberg/build/blocks.js:3 -#: modules/gutenberg/build/blocks.js:4 -#: modules/gutenberg/build/blocks.js:5 -#: modules/gutenberg/build/blocks.js:6 -#: modules/gutenberg/build/blocks.js:7 -#: modules/gutenberg/build/blocks.js:8 -#: assets/build/blocks.js:114193 -#: assets/build/blocks.js:114207 -#: assets/build/blocks.js:114629 -#: assets/build/blocks.js:114643 -#: assets/build/blocks.js:115811 -#: assets/build/blocks.js:115824 -#: assets/build/formEditor.js:123456 -#: assets/build/formEditor.js:123470 -#: assets/build/formEditor.js:124296 -#: assets/build/formEditor.js:124309 -#, js-format -msgid "%s units" +#: assets/build/blocks.js:172 +msgid "Amount Type" msgstr "" -#: assets/build/blocks.js:119705 -#: assets/build/blocks.js:120134 -#: assets/build/blocks.js:121390 -#: assets/build/formEditor.js:133068 -#: assets/build/formEditor.js:133933 -#: modules/gutenberg/build/blocks.js:2 -#: modules/gutenberg/build/blocks.js:4 -#: modules/gutenberg/build/blocks.js:6 -#: assets/build/blocks.js:114236 -#: assets/build/blocks.js:114710 -#: assets/build/blocks.js:115916 -#: assets/build/formEditor.js:123537 -#: assets/build/formEditor.js:124401 -msgid "Select Units" +#: assets/build/blocks.js:172 +msgid "Choose whether to charge a fixed amount or charge the amount based on user input in other form fields." msgstr "" -#: assets/build/blocks.js:119743 -#: assets/build/blocks.js:120162 -#: assets/build/formEditor.js:133096 -#: modules/gutenberg/build/blocks.js:4 -#: modules/gutenberg/build/blocks.js:6 -#: modules/gutenberg/build/blocks.js:8 -#: modules/gutenberg/build/blocks.js:9 -#: assets/build/blocks.js:114319 -#: assets/build/blocks.js:114751 -#: assets/build/formEditor.js:123578 -msgid "Margin" +#: assets/build/blocks.js:172 +msgid "Set the exact amount you want to charge. Users wonโ€™t be able to change it" msgstr "" -#: assets/build/blocks.js:119874 -#: assets/build/entries.js:67363 -#: assets/build/formEditor.js:120082 -#: assets/build/formEditor.js:125757 -#: assets/build/formEditor.js:125761 -#: assets/build/formEditor.js:132808 -#: assets/build/forms.js:62218 -#: assets/build/forms.js:63856 -#: assets/build/payments.js:172 -#: assets/build/settings.js:71485 -#: modules/gutenberg/build/blocks.js:6 -#: assets/build/blocks.js:114402 -#: assets/build/entries.js:58425 -#: assets/build/formEditor.js:109225 -#: assets/build/formEditor.js:115429 -#: assets/build/formEditor.js:115438 -#: assets/build/formEditor.js:123229 -#: assets/build/forms.js:53451 -#: assets/build/forms.js:55005 -#: assets/build/settings.js:63773 -msgid "Confirm" +#: assets/build/blocks.js:172 +msgid "Choose Amount Field" msgstr "" -#: assets/build/blocks.js:119878 -#: assets/build/formEditor.js:132812 -#: assets/build/payments.js:172 -#: modules/gutenberg/build/blocks.js:6 -#: assets/build/blocks.js:114404 -#: assets/build/formEditor.js:123231 -msgid "Processingโ€ฆ" +#: assets/build/blocks.js:172 +msgid "Pick a field from your form like a number, dropdown, multichoice, or hidden whose value should decide the payment amount." msgstr "" -#. translators: abbreviation for units -#: assets/build/blocks.js:120386 -#: assets/build/formEditor.js:133320 -#: modules/gutenberg/build/blocks.js:2 -#: assets/build/blocks.js:114963 -#: assets/build/formEditor.js:123790 -msgid "Reset" +#: assets/build/blocks.js:172 +msgid "Minimum Amount" msgstr "" -#: assets/build/blocks.js:120593 -#: assets/build/formEditor.js:133527 -#: modules/gutenberg/build/blocks.js:1 -#: assets/build/blocks.js:115182 -#: assets/build/formEditor.js:124009 -msgid "Device" +#: assets/build/blocks.js:172 +msgid "Set the minimum amount users can enter (0 for no minimum)" msgstr "" -#: assets/build/blocks.js:121142 -#: assets/build/blocks.js:115649 -msgid "Slug" +#: assets/build/blocks.js:172 +msgid "Customer Name Field (Required)" msgstr "" -#: assets/build/blocks.js:121148 -#: assets/build/blocks.js:115653 -msgid "Auto-generated on save" +#: assets/build/blocks.js:172 +msgid "Customer Name Field (Optional)" msgstr "" -#: assets/build/blocks.js:121154 -#: assets/build/blocks.js:115663 -msgid "This slug is already used by another field. It will revert to the previous value." +#: assets/build/blocks.js:172 +msgid "Select the input field that contains the customer name (Required for subscriptions)" msgstr "" -#: assets/build/blocks.js:121154 -#: assets/build/blocks.js:115667 -msgid "Changing the slug may break form submissions, conditional logic, integrations, or any other feature currently referencing this slug. You will need to update all such references manually." +#: assets/build/blocks.js:172 +msgid "Select the input field that contains the customer name" msgstr "" -#: assets/build/blocks.js:121408 -#: assets/build/formEditor.js:133951 -#: modules/gutenberg/build/blocks.js:6 -#: assets/build/blocks.js:115948 -#: assets/build/formEditor.js:124433 -msgid "Top" +#: assets/build/blocks.js:172 +msgid "Customer Email Field (Required)" msgstr "" -#: assets/build/blocks.js:121412 -#: assets/build/formEditor.js:133955 -#: modules/gutenberg/build/blocks.js:6 -#: assets/build/blocks.js:115954 -#: assets/build/formEditor.js:124439 -msgid "Bottom" +#: assets/build/blocks.js:172 +msgid "Select the email field that contains the customer email" msgstr "" -#: assets/build/blocks.js:121661 -#: assets/build/formEditor.js:121295 -#: assets/build/formEditor.js:121483 -#: assets/build/formEditor.js:121487 -#: assets/build/formEditor.js:121503 -#: assets/build/formEditor.js:121510 -#: assets/build/formEditor.js:123405 -#: assets/build/formEditor.js:123411 -#: assets/build/formEditor.js:134752 -#: assets/build/settings.js:79268 -#: assets/build/settings.js:79456 -#: assets/build/settings.js:79460 -#: assets/build/settings.js:79476 -#: assets/build/settings.js:79483 -#: assets/build/settings.js:79949 -#: assets/build/settings.js:79955 -#: assets/build/blocks.js:116211 -#: assets/build/formEditor.js:110437 -#: assets/build/formEditor.js:110659 -#: assets/build/formEditor.js:110665 -#: assets/build/formEditor.js:110686 -#: assets/build/formEditor.js:110696 -#: assets/build/formEditor.js:112851 -#: assets/build/formEditor.js:112861 -#: assets/build/formEditor.js:125194 -#: assets/build/settings.js:72051 -#: assets/build/settings.js:72273 -#: assets/build/settings.js:72279 -#: assets/build/settings.js:72300 -#: assets/build/settings.js:72310 -#: assets/build/settings.js:72772 -#: assets/build/settings.js:72782 -msgid "Generic tags" +#: assets/build/blocks.js:172 +msgid "Payments Per Page" msgstr "" -#: assets/build/blocks.js:121931 -#: assets/build/blocks.js:116460 -msgid "Upgrade to Unlock" +#: assets/build/blocks.js:172 +msgid "Show Subscriptions Section" msgstr "" -#: assets/build/blocks.js:125114 -#: assets/build/dashboard.js:101011 -#: assets/build/entries.js:73534 -#: assets/build/formEditor.js:137870 -#: assets/build/forms.js:67568 -#: assets/build/settings.js:82809 -#: assets/build/templatePicker.js:172 -#: assets/build/blocks.js:119836 -#: assets/build/dashboard.js:87113 -#: assets/build/entries.js:64334 -#: assets/build/formEditor.js:128471 -#: assets/build/forms.js:58256 -#: assets/build/settings.js:75289 -msgid "You do not have permission to create forms." +#: assets/build/blocks.js:172 +msgid "Show a dedicated subscriptions section above payment history." msgstr "" -#: assets/build/blocks.js:125152 -#: assets/build/blocks.js:125161 -#: assets/build/dashboard.js:101049 -#: assets/build/dashboard.js:101058 -#: assets/build/entries.js:73572 -#: assets/build/entries.js:73581 -#: assets/build/formEditor.js:137908 -#: assets/build/formEditor.js:137917 -#: assets/build/forms.js:67606 -#: assets/build/forms.js:67615 -#: assets/build/settings.js:82847 -#: assets/build/settings.js:82856 -#: assets/build/templatePicker.js:172 -#: assets/build/blocks.js:119878 -#: assets/build/blocks.js:119885 -#: assets/build/dashboard.js:87155 -#: assets/build/dashboard.js:87162 -#: assets/build/entries.js:64376 -#: assets/build/entries.js:64383 -#: assets/build/formEditor.js:128513 -#: assets/build/formEditor.js:128520 -#: assets/build/forms.js:58298 -#: assets/build/forms.js:58305 -#: assets/build/settings.js:75331 -#: assets/build/settings.js:75338 -msgid "The form could not be saved. Please try again." +#: assets/build/blocks.js:172 +msgid "Payment Dashboard" msgstr "" -#: assets/build/blocks.js:125230 -#: assets/build/dashboard.js:101127 -#: assets/build/entries.js:73650 -#: assets/build/formEditor.js:137986 -#: assets/build/forms.js:67684 -#: assets/build/settings.js:82925 -#: assets/build/blocks.js:119934 -#: assets/build/dashboard.js:87211 -#: assets/build/entries.js:64432 -#: assets/build/formEditor.js:128569 -#: assets/build/forms.js:58354 -#: assets/build/settings.js:75387 -msgid "No tags available" +#: assets/build/blocks.js:172 +msgid "View your payments and manage subscriptions in a single dashboard." msgstr "" -#. translators: %s is replaced by the Payment block label. -#: assets/build/blocks.js:125318 -#: assets/build/dashboard.js:101215 -#: assets/build/entries.js:73738 -#: assets/build/formEditor.js:138074 -#: assets/build/forms.js:67772 -#: assets/build/settings.js:83013 -#: assets/build/blocks.js:120057 -#: assets/build/dashboard.js:87334 -#: assets/build/entries.js:64555 -#: assets/build/formEditor.js:128692 -#: assets/build/forms.js:58477 -#: assets/build/settings.js:75510 -#, js-format -msgid "%s - Order ID" +#: assets/build/blocks.js:172 +msgid "Slug" msgstr "" -#. translators: %s is replaced by the Payment block label. -#: assets/build/blocks.js:125321 -#: assets/build/dashboard.js:101218 -#: assets/build/entries.js:73741 -#: assets/build/formEditor.js:138077 -#: assets/build/forms.js:67775 -#: assets/build/settings.js:83016 -#: assets/build/blocks.js:120066 -#: assets/build/dashboard.js:87343 -#: assets/build/entries.js:64564 -#: assets/build/formEditor.js:128701 -#: assets/build/forms.js:58486 -#: assets/build/settings.js:75519 -#, js-format -msgid "%s - Amount" +#: assets/build/blocks.js:172 +msgid "Auto-generated on save" msgstr "" -#. translators: %s is replaced by the Payment block label. -#: assets/build/blocks.js:125324 -#: assets/build/dashboard.js:101221 -#: assets/build/entries.js:73744 -#: assets/build/formEditor.js:138080 -#: assets/build/forms.js:67778 -#: assets/build/settings.js:83019 -#: assets/build/blocks.js:120075 -#: assets/build/dashboard.js:87352 -#: assets/build/entries.js:64573 -#: assets/build/formEditor.js:128710 -#: assets/build/forms.js:58495 -#: assets/build/settings.js:75528 -#, js-format -msgid "%s - Customer Email" +#: assets/build/blocks.js:172 +msgid "This slug is already used by another field. It will revert to the previous value." msgstr "" -#. translators: %s is replaced by the Payment block label. -#: assets/build/blocks.js:125327 -#: assets/build/dashboard.js:101224 -#: assets/build/entries.js:73747 -#: assets/build/formEditor.js:138083 -#: assets/build/forms.js:67781 -#: assets/build/settings.js:83022 -#: assets/build/blocks.js:120084 -#: assets/build/dashboard.js:87361 -#: assets/build/entries.js:64582 -#: assets/build/formEditor.js:128719 -#: assets/build/forms.js:58504 -#: assets/build/settings.js:75537 -#, js-format -msgid "%s - Customer Name" +#: assets/build/blocks.js:172 +msgid "Changing the slug may break form submissions, conditional logic, integrations, or any other feature currently referencing this slug. You will need to update all such references manually." msgstr "" -#. translators: %s is replaced by the Payment block label. -#: assets/build/blocks.js:125330 -#: assets/build/dashboard.js:101227 -#: assets/build/entries.js:73750 -#: assets/build/formEditor.js:138086 -#: assets/build/forms.js:67784 -#: assets/build/settings.js:83025 -#: assets/build/blocks.js:120093 -#: assets/build/dashboard.js:87370 -#: assets/build/entries.js:64591 -#: assets/build/formEditor.js:128728 -#: assets/build/forms.js:58513 -#: assets/build/settings.js:75546 -#, js-format -msgid "%s - Status" +#: assets/build/blocks.js:172 +msgid "Click here to insert a form" msgstr "" -#. translators: %s is replaced by the Payment block label. -#: assets/build/blocks.js:125333 -#: assets/build/dashboard.js:101230 -#: assets/build/entries.js:73753 -#: assets/build/formEditor.js:138089 -#: assets/build/forms.js:67787 -#: assets/build/settings.js:83028 -#: assets/build/blocks.js:120102 -#: assets/build/dashboard.js:87379 -#: assets/build/entries.js:64600 -#: assets/build/formEditor.js:128737 -#: assets/build/forms.js:58522 -#: assets/build/settings.js:75555 +#: assets/build/blocks.js:172 #, js-format -msgid "%s - Description" +msgid "%s Width" msgstr "" -#: assets/build/blocks.js:125536 -#: assets/build/blocks.js:125587 -#: assets/build/dashboard.js:101433 -#: assets/build/dashboard.js:101484 -#: assets/build/entries.js:73956 -#: assets/build/entries.js:74007 -#: assets/build/formEditor.js:138292 -#: assets/build/formEditor.js:138343 -#: assets/build/forms.js:67990 -#: assets/build/forms.js:68041 -#: assets/build/settings.js:83231 -#: assets/build/settings.js:83282 -#: assets/build/blocks.js:120352 -#: assets/build/blocks.js:120409 -#: assets/build/dashboard.js:87629 -#: assets/build/dashboard.js:87686 -#: assets/build/entries.js:64850 -#: assets/build/entries.js:64907 -#: assets/build/formEditor.js:128987 -#: assets/build/formEditor.js:129044 -#: assets/build/forms.js:58772 -#: assets/build/forms.js:58829 -#: assets/build/settings.js:75805 -#: assets/build/settings.js:75862 -msgid "No Date" +#: assets/build/blocks.js:172 +msgid "Field Slug" msgstr "" -#: assets/build/blocks.js:125583 -#: assets/build/dashboard.js:101480 -#: assets/build/entries.js:74003 -#: assets/build/formEditor.js:138339 -#: assets/build/forms.js:68037 -#: assets/build/settings.js:83278 -#: assets/build/blocks.js:120405 -#: assets/build/dashboard.js:87682 -#: assets/build/entries.js:64903 -#: assets/build/formEditor.js:129040 -#: assets/build/forms.js:58825 -#: assets/build/settings.js:75858 -msgid "Invalid Date" +#: assets/build/dashboard.js:2 +msgid "Welcome to SureForms!" msgstr "" -#: assets/build/blocks.js:125832 -#: assets/build/dashboard.js:101729 -#: assets/build/entries.js:74252 -#: assets/build/formEditor.js:120745 -#: assets/build/formEditor.js:120760 -#: assets/build/formEditor.js:138588 -#: assets/build/forms.js:68286 -#: assets/build/settings.js:78356 -#: assets/build/settings.js:78371 -#: assets/build/settings.js:83527 -#: assets/build/blocks.js:120641 -#: assets/build/dashboard.js:87918 -#: assets/build/entries.js:65139 -#: assets/build/formEditor.js:109858 -#: assets/build/formEditor.js:109876 -#: assets/build/formEditor.js:129276 -#: assets/build/forms.js:59061 -#: assets/build/settings.js:71060 -#: assets/build/settings.js:71078 -#: assets/build/settings.js:76094 -msgid "Install & Activate" +#: assets/build/dashboard.js:2 +msgid "SureForms is a WordPress plugin that enables users to create beautiful looking forms through a drag-and-drop interface, without needing to code. It integrates with the WordPress block editor." +msgstr "" + +#: assets/build/dashboard.js:2 +msgid "Read Full Guide" +msgstr "" + +#: assets/build/dashboard.js:2 +msgid "SureForms Video Thumbnail" +msgstr "" + +#: assets/build/dashboard.js:2 +msgid "SureForms: Custom WordPress Forms MADE SIMPLE" +msgstr "" + +#: assets/build/dashboard.js:172 +#: assets/build/entries.js:172 +#: assets/build/forms.js:172 +msgid "No Date" +msgstr "" + +#: assets/build/dashboard.js:172 +#: assets/build/entries.js:172 +#: assets/build/forms.js:172 +msgid "Invalid Date" msgstr "" -#: assets/build/blocks.js:125871 -#: assets/build/dashboard.js:101768 -#: assets/build/entries.js:74291 -#: assets/build/formEditor.js:138627 -#: assets/build/forms.js:68325 -#: assets/build/settings.js:83566 -#: assets/build/blocks.js:120679 -#: assets/build/dashboard.js:87956 -#: assets/build/entries.js:65177 -#: assets/build/formEditor.js:129314 -#: assets/build/forms.js:59099 -#: assets/build/settings.js:76132 +#: assets/build/dashboard.js:172 msgid "Unable to complete action. Please try again." msgstr "" -#: assets/build/blocks.js:125911 -#: assets/build/dashboard.js:101808 -#: assets/build/entries.js:74331 -#: assets/build/formEditor.js:120719 -#: assets/build/formEditor.js:138667 -#: assets/build/forms.js:68365 -#: assets/build/settings.js:78330 -#: assets/build/settings.js:83606 -#: assets/build/blocks.js:120714 -#: assets/build/dashboard.js:87991 -#: assets/build/entries.js:65212 -#: assets/build/formEditor.js:109826 -#: assets/build/formEditor.js:129349 -#: assets/build/forms.js:59134 -#: assets/build/settings.js:71028 -#: assets/build/settings.js:76167 +#: assets/build/dashboard.js:172 +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 msgid "Plugin activation failed, Please try again later." msgstr "" -#: assets/build/blocks.js:125942 -#: assets/build/dashboard.js:101839 -#: assets/build/entries.js:74362 -#: assets/build/formEditor.js:120690 -#: assets/build/formEditor.js:120691 -#: assets/build/formEditor.js:138698 -#: assets/build/forms.js:68396 -#: assets/build/settings.js:78301 -#: assets/build/settings.js:78302 -#: assets/build/settings.js:83637 -#: assets/build/blocks.js:120750 -#: assets/build/dashboard.js:88027 -#: assets/build/entries.js:65248 -#: assets/build/formEditor.js:109782 -#: assets/build/formEditor.js:109783 -#: assets/build/formEditor.js:129385 -#: assets/build/forms.js:59170 -#: assets/build/settings.js:70984 -#: assets/build/settings.js:70985 -#: assets/build/settings.js:76203 +#: assets/build/dashboard.js:172 +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 msgid "Install" msgstr "" -#: assets/build/blocks.js:125943 -#: assets/build/dashboard.js:101840 -#: assets/build/entries.js:74363 -#: assets/build/formEditor.js:120692 -#: assets/build/formEditor.js:138699 -#: assets/build/forms.js:68397 -#: assets/build/settings.js:78303 -#: assets/build/settings.js:83638 -#: assets/build/blocks.js:120752 -#: assets/build/dashboard.js:88029 -#: assets/build/entries.js:65250 -#: assets/build/formEditor.js:109785 -#: assets/build/formEditor.js:129387 -#: assets/build/forms.js:59172 -#: assets/build/settings.js:70987 -#: assets/build/settings.js:76205 +#: assets/build/dashboard.js:172 +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 msgid "Plugin Installation failed, Please try again later." msgstr "" -#: assets/build/blocks.js:126684 -#: assets/build/blocks.js:121258 -msgid "Click here to insert a form" -msgstr "" - -#. translators: %s: Width of the block -#: assets/build/blocks.js:126738 -#: assets/build/blocks.js:121348 -#, js-format -msgid "%s Width" +#: assets/build/dashboard.js:172 +msgid "Supercharge Your Workflow" msgstr "" -#: assets/build/blocks.js:126818 -#: assets/build/blocks.js:121474 -msgid "Field Slug" +#: assets/build/dashboard.js:172 +#: assets/build/formEditor.js:2 +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:2 +#: assets/build/settings.js:172 +msgid "Install & Activate" msgstr "" -#: assets/build/dashboard.js:94097 -#: assets/build/entries.js:67865 -#: assets/build/forms.js:62720 +#: assets/build/dashboard.js:172 +#: assets/build/entries.js:172 +#: assets/build/forms.js:172 #: assets/build/learn.js:172 #: assets/build/page_header.js:172 #: assets/build/partialEntriesEmptyState.js:172 #: assets/build/payments.js:172 #: assets/build/quizEmptyState.js:172 -#: assets/build/settings.js:71816 +#: assets/build/settings.js:172 #: assets/build/surveyEmptyState.js:172 -#: assets/build/dashboard.js:80061 -#: assets/build/entries.js:58858 -#: assets/build/forms.js:53884 -#: assets/build/settings.js:64075 -msgid "What's New?" +msgid "Ready to go beyond free plan?" msgstr "" -#: assets/build/dashboard.js:94139 -#: assets/build/dashboard.js:94168 -#: assets/build/entries.js:67907 -#: assets/build/entries.js:67936 -#: assets/build/forms.js:62762 -#: assets/build/forms.js:62791 +#: assets/build/dashboard.js:172 +#: assets/build/entries.js:172 +#: assets/build/forms.js:172 #: assets/build/learn.js:172 #: assets/build/page_header.js:172 #: assets/build/partialEntriesEmptyState.js:172 #: assets/build/payments.js:172 #: assets/build/quizEmptyState.js:172 -#: assets/build/settings.js:71858 -#: assets/build/settings.js:71887 +#: assets/build/settings.js:172 #: assets/build/surveyEmptyState.js:172 -#: assets/build/dashboard.js:80115 -#: assets/build/dashboard.js:80174 -#: assets/build/entries.js:58912 -#: assets/build/entries.js:58971 -#: assets/build/forms.js:53938 -#: assets/build/forms.js:53997 -#: assets/build/settings.js:64129 -#: assets/build/settings.js:64188 -msgid "Upgrade SureForms" +msgid "Upgrade now" msgstr "" -#: assets/build/dashboard.js:94175 -#: assets/build/entries.js:67943 -#: assets/build/forms.js:62798 +#: assets/build/dashboard.js:172 +#: assets/build/entries.js:172 +#: assets/build/forms.js:172 #: assets/build/learn.js:172 #: assets/build/page_header.js:172 #: assets/build/partialEntriesEmptyState.js:172 #: assets/build/payments.js:172 #: assets/build/quizEmptyState.js:172 -#: assets/build/settings.js:71894 +#: assets/build/settings.js:172 #: assets/build/surveyEmptyState.js:172 -#: assets/build/dashboard.js:80189 -#: assets/build/entries.js:58986 -#: assets/build/forms.js:54012 -#: assets/build/settings.js:64203 -msgid "Core" +msgid "and unlock the full power of SureForms!" msgstr "" -#: assets/build/dashboard.js:94201 -#: assets/build/entries.js:67969 -#: assets/build/forms.js:62824 +#: assets/build/dashboard.js:172 +#: assets/build/entries.js:172 +#: assets/build/forms.js:172 #: assets/build/learn.js:172 #: assets/build/page_header.js:172 #: assets/build/partialEntriesEmptyState.js:172 #: assets/build/payments.js:172 #: assets/build/quizEmptyState.js:172 -#: assets/build/settings.js:71920 +#: assets/build/settings.js:172 #: assets/build/surveyEmptyState.js:172 -#: assets/build/dashboard.js:80238 -#: assets/build/entries.js:59035 -#: assets/build/forms.js:54061 -#: assets/build/settings.js:64252 -msgid "Unlicensed" +msgid "What's New?" msgstr "" -#: assets/build/dashboard.js:94206 -#: assets/build/entries.js:67974 -#: assets/build/forms.js:62829 +#: assets/build/dashboard.js:172 +#: assets/build/entries.js:172 +#: assets/build/forms.js:172 #: assets/build/learn.js:172 #: assets/build/page_header.js:172 #: assets/build/partialEntriesEmptyState.js:172 #: assets/build/payments.js:172 #: assets/build/quizEmptyState.js:172 -#: assets/build/settings.js:71925 +#: assets/build/settings.js:172 #: assets/build/surveyEmptyState.js:172 -#: assets/build/dashboard.js:80253 -#: assets/build/entries.js:59050 -#: assets/build/forms.js:54076 -#: assets/build/settings.js:64267 -msgid "Knowledge Base" +msgid "Upgrade SureForms" msgstr "" -#: assets/build/dashboard.js:94214 -#: assets/build/entries.js:67982 -#: assets/build/forms.js:62837 +#: assets/build/dashboard.js:172 +#: assets/build/entries.js:172 +#: assets/build/forms.js:172 #: assets/build/learn.js:172 #: assets/build/page_header.js:172 #: assets/build/partialEntriesEmptyState.js:172 #: assets/build/payments.js:172 #: assets/build/quizEmptyState.js:172 -#: assets/build/settings.js:71933 +#: assets/build/settings.js:172 #: assets/build/surveyEmptyState.js:172 -#: assets/build/dashboard.js:80264 -#: assets/build/entries.js:59061 -#: assets/build/forms.js:54087 -#: assets/build/settings.js:64278 -msgid "Whatโ€™s New" +msgid "Core" msgstr "" -#: assets/build/dashboard.js:94336 -#: assets/build/entries.js:68104 -#: assets/build/forms.js:62959 +#: assets/build/dashboard.js:172 +#: assets/build/entries.js:172 +#: assets/build/forms.js:172 #: assets/build/learn.js:172 #: assets/build/page_header.js:172 #: assets/build/partialEntriesEmptyState.js:172 #: assets/build/payments.js:172 #: assets/build/quizEmptyState.js:172 -#: assets/build/settings.js:72379 +#: assets/build/settings.js:172 #: assets/build/surveyEmptyState.js:172 -#: assets/build/dashboard.js:80355 -#: assets/build/entries.js:59152 -#: assets/build/forms.js:54178 -#: assets/build/settings.js:64660 -msgid "Ready to go beyond free plan?" +msgid "Unlicensed" msgstr "" -#: assets/build/dashboard.js:94345 -#: assets/build/entries.js:68113 -#: assets/build/forms.js:62968 +#: assets/build/dashboard.js:172 +#: assets/build/entries.js:172 +#: assets/build/forms.js:172 #: assets/build/learn.js:172 #: assets/build/page_header.js:172 #: assets/build/partialEntriesEmptyState.js:172 #: assets/build/payments.js:172 #: assets/build/quizEmptyState.js:172 -#: assets/build/settings.js:72388 +#: assets/build/settings.js:172 #: assets/build/surveyEmptyState.js:172 -#: assets/build/dashboard.js:80374 -#: assets/build/entries.js:59171 -#: assets/build/forms.js:54197 -#: assets/build/settings.js:64679 -msgid "Upgrade now" +msgid "Knowledge Base" msgstr "" -#: assets/build/dashboard.js:94347 -#: assets/build/entries.js:68115 -#: assets/build/forms.js:62970 +#: assets/build/dashboard.js:172 +#: assets/build/entries.js:172 +#: assets/build/forms.js:172 #: assets/build/learn.js:172 #: assets/build/page_header.js:172 #: assets/build/partialEntriesEmptyState.js:172 #: assets/build/payments.js:172 #: assets/build/quizEmptyState.js:172 -#: assets/build/settings.js:72390 +#: assets/build/settings.js:172 #: assets/build/surveyEmptyState.js:172 -#: assets/build/dashboard.js:80377 -#: assets/build/entries.js:59174 -#: assets/build/forms.js:54200 -#: assets/build/settings.js:64682 -msgid "and unlock the full power of SureForms!" -msgstr "" - -#: assets/build/dashboard.js:95661 -#: assets/build/dashboard.js:81961 -msgid "Supercharge Your Workflow" -msgstr "" - -#: assets/build/dashboard.js:95764 -#: assets/build/dashboard.js:82058 -msgid "This is where your form views will appear" -msgstr "" - -#: assets/build/dashboard.js:95778 -#: assets/build/entries.js:68766 -#: assets/build/forms.js:64420 -#: assets/build/payments.js:2 -#: assets/build/payments.js:172 -#: assets/build/dashboard.js:82072 -#: assets/build/entries.js:59793 -#: assets/build/forms.js:55451 -msgid "Clear Filters" -msgstr "" - -#: assets/build/dashboard.js:95816 -#: assets/build/dashboard.js:96028 -#: assets/build/dashboard.js:82099 -#: assets/build/dashboard.js:82295 -msgid "Unnamed Form" -msgstr "" - -#: assets/build/dashboard.js:95999 -#: assets/build/dashboard.js:82254 -msgid "Forms Overview" -msgstr "" - -#: assets/build/dashboard.js:96011 -#: assets/build/dashboard.js:82265 -msgid "Clear Form Filters" -msgstr "" - -#: assets/build/dashboard.js:96034 -#: assets/build/dashboard.js:82311 -msgid "Clear Date Filters" -msgstr "" - -#: assets/build/dashboard.js:96053 -#: assets/build/entries.js:67690 -#: assets/build/forms.js:62545 -#: assets/build/dashboard.js:82334 -#: assets/build/entries.js:58709 -#: assets/build/forms.js:53735 -msgid "Select Date Range" -msgstr "" - -#: assets/build/dashboard.js:96057 -#: assets/build/payments.js:2 -#: assets/build/dashboard.js:82342 -msgid "Apply" -msgstr "" - -#: assets/build/dashboard.js:96071 -#: assets/build/entries.js:68792 -#: assets/build/entries.js:70231 -#: assets/build/forms.js:64308 -#: assets/build/forms.js:64323 -#: assets/build/forms.js:64526 -#: assets/build/dashboard.js:82374 -#: assets/build/entries.js:59838 -#: assets/build/entries.js:61276 -#: assets/build/forms.js:55323 -#: assets/build/forms.js:55341 -#: assets/build/forms.js:55571 -msgid "All Forms" -msgstr "" - -#: assets/build/dashboard.js:96095 -#: assets/build/dashboard.js:82407 -msgid "Please wait for the data to load" -msgstr "" - -#: assets/build/dashboard.js:96131 -#: assets/build/dashboard.js:82458 -msgid "No entries to display" -msgstr "" - -#: assets/build/dashboard.js:96136 -#: assets/build/dashboard.js:82467 -msgid "Once you create a form and start receiving submissions, the data will appear here." -msgstr "" - -#: assets/build/dashboard.js:96205 -#: assets/build/dashboard.js:82515 -msgid "Welcome to SureForms!" -msgstr "" - -#: assets/build/dashboard.js:96210 -#: assets/build/dashboard.js:82522 -msgid "SureForms is a WordPress plugin that enables users to create beautiful looking forms through a drag-and-drop interface, without needing to code. It integrates with the WordPress block editor." -msgstr "" - -#: assets/build/dashboard.js:96226 -#: assets/build/dashboard.js:96234 -#: assets/build/dashboard.js:82553 -#: assets/build/dashboard.js:82569 -msgid "Read Full Guide" -msgstr "" - -#: assets/build/dashboard.js:96243 -#: assets/build/dashboard.js:82583 -msgid "SureForms Video Thumbnail" -msgstr "" - -#: assets/build/dashboard.js:96276 -#: assets/build/dashboard.js:82624 -msgid "SureForms: Custom WordPress Forms MADE SIMPLE" +msgid "Whatโ€™s New" msgstr "" -#: assets/build/dashboard.js:96309 -#: assets/build/dashboard.js:82652 +#: assets/build/dashboard.js:172 msgid "Guided Setup" msgstr "" -#: assets/build/dashboard.js:96316 -#: assets/build/dashboard.js:82658 +#: assets/build/dashboard.js:172 msgid "Open Support Ticket" msgstr "" -#: assets/build/dashboard.js:96323 -#: assets/build/dashboard.js:82664 +#: assets/build/dashboard.js:172 msgid "Help Center" msgstr "" -#: assets/build/dashboard.js:96330 -#: assets/build/dashboard.js:82670 +#: assets/build/dashboard.js:172 msgid "Join our Community on Facebook" msgstr "" -#: assets/build/dashboard.js:96337 -#: assets/build/dashboard.js:82676 +#: assets/build/dashboard.js:172 msgid "Leave Us a Review" msgstr "" -#: assets/build/dashboard.js:96380 -#: assets/build/dashboard.js:82716 +#: assets/build/dashboard.js:172 msgid "Quick Access" msgstr "" -#: assets/build/dashboard.js:96415 -#: assets/build/dashboard.js:98942 -#: assets/build/dashboard.js:82737 -#: assets/build/dashboard.js:85158 +#: assets/build/dashboard.js:172 msgid "Conversational Forms" msgstr "" -#: assets/build/dashboard.js:96415 -#: assets/build/dashboard.js:82738 +#: assets/build/dashboard.js:172 msgid "File Uploads" msgstr "" -#: assets/build/dashboard.js:96415 -#: assets/build/dashboard.js:82742 +#: assets/build/dashboard.js:172 msgid "Signature & Rating" msgstr "" -#: assets/build/dashboard.js:96415 -#: assets/build/dashboard.js:82745 +#: assets/build/dashboard.js:172 msgid "Calculation Forms" msgstr "" -#: assets/build/dashboard.js:96415 -#: assets/build/dashboard.js:82746 +#: assets/build/dashboard.js:172 msgid "And Much Moreโ€ฆ" msgstr "" -#: assets/build/dashboard.js:96423 +#: assets/build/dashboard.js:172 #: assets/build/learn.js:172 -#: assets/build/dashboard.js:82759 msgid "Upgrade to Pro" msgstr "" -#: assets/build/dashboard.js:96430 -#: assets/build/dashboard.js:82768 +#: assets/build/dashboard.js:172 msgid "Unlock Premium Features" msgstr "" -#: assets/build/dashboard.js:96434 -#: assets/build/dashboard.js:82777 +#: assets/build/dashboard.js:172 msgid "Build Better Forms with SureForms" msgstr "" -#: assets/build/dashboard.js:96437 -#: assets/build/dashboard.js:82785 +#: assets/build/dashboard.js:172 msgid "Add advanced fields, conversational layouts, and smart logic to create forms that engage users and capture better data." msgstr "" -#: assets/build/dashboard.js:96460 -#: assets/build/formEditor.js:123003 -#: assets/build/formEditor.js:124081 -#: assets/build/settings.js:77628 -#: assets/build/settings.js:77672 +#: assets/build/dashboard.js:172 +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 #: assets/build/templatePicker.js:172 -#: assets/build/dashboard.js:82828 -#: assets/build/formEditor.js:112481 -#: assets/build/formEditor.js:113510 -#: assets/build/settings.js:70159 -#: assets/build/settings.js:70220 msgid "Upgrade Now" msgstr "" -#: assets/build/dashboard.js:96759 -#: assets/build/dashboard.js:97999 -#: assets/build/dashboard.js:98474 -#: assets/build/dashboard.js:99345 -#: assets/build/dashboard.js:99665 -#: assets/build/settings.js:75943 -#: assets/build/dashboard.js:83036 -#: assets/build/dashboard.js:84240 -#: assets/build/dashboard.js:84669 -#: assets/build/dashboard.js:85658 -#: assets/build/dashboard.js:86010 -#: assets/build/settings.js:68388 -msgid "Skip" -msgstr "" - -#. translators: %d: number of source forms still pending import. -#: assets/build/dashboard.js:96968 -#: assets/build/dashboard.js:83219 -#, js-format -msgid "%d form ready" -msgid_plural "%d forms ready" -msgstr[0] "" -msgstr[1] "" - -#. translators: %d: number of source forms already imported into SureForms. -#: assets/build/dashboard.js:96970 -#: assets/build/dashboard.js:83227 -#, js-format -msgid "%d already imported" -msgid_plural "%d already imported" -msgstr[0] "" -msgstr[1] "" - -#: assets/build/dashboard.js:96999 -#: assets/build/dashboard.js:83296 -msgid "(unnamed source)" -msgstr "" - -#: assets/build/dashboard.js:97004 -#: assets/build/dashboard.js:83302 -msgid "All forms already imported" -msgstr "" - -#: assets/build/dashboard.js:97429 -#: assets/build/dashboard.js:83706 -msgid "Exit Guided Setup" -msgstr "" - -#: assets/build/dashboard.js:97896 -#: assets/build/dashboard.js:84141 -msgid "Build up to 10 forms using AI" -msgstr "" - -#: assets/build/dashboard.js:97896 -#: assets/build/dashboard.js:84142 -msgid "A secure and private connection" -msgstr "" - -#: assets/build/dashboard.js:97896 -#: assets/build/dashboard.js:84143 -msgid "Smart form drafts based on your input" +#: assets/build/dashboard.js:172 +msgid "This is where your form views will appear" msgstr "" -#: assets/build/dashboard.js:97960 -#: assets/build/dashboard.js:84179 -msgid "Starting from a blank form isn't always easy. Our AI can help by creating a draft form based on what you're trying to do โ€” saving you time and giving you a clear direction." +#: assets/build/dashboard.js:172 +#: assets/build/entries.js:172 +#: assets/build/forms.js:172 +#: assets/build/payments.js:2 +#: assets/build/payments.js:172 +msgid "Clear Filters" msgstr "" -#: assets/build/dashboard.js:97960 -#: assets/build/dashboard.js:84185 -msgid "To do this, you'll need to connect your account." +#: assets/build/dashboard.js:172 +msgid "Unnamed Form" msgstr "" -#: assets/build/dashboard.js:97967 -#: assets/build/dashboard.js:84200 -msgid "Let AI Help You Build Smarter, Faster Forms" +#: assets/build/dashboard.js:172 +msgid "Forms Overview" msgstr "" -#: assets/build/dashboard.js:97978 -#: assets/build/dashboard.js:84211 -msgid "Here's what that gives you:" +#: assets/build/dashboard.js:172 +msgid "Clear Form Filters" msgstr "" -#: assets/build/dashboard.js:97995 -#: assets/build/dashboard.js:98470 -#: assets/build/dashboard.js:98733 -#: assets/build/dashboard.js:98786 -#: assets/build/settings.js:77782 -#: assets/build/dashboard.js:84235 -#: assets/build/dashboard.js:84664 -#: assets/build/dashboard.js:84898 -#: assets/build/dashboard.js:84986 -#: assets/build/settings.js:70322 -msgid "Continue" +#: assets/build/dashboard.js:172 +msgid "Clear Date Filters" msgstr "" -#: assets/build/dashboard.js:97995 -#: assets/build/dashboard.js:84236 -msgid "Connect" +#: assets/build/dashboard.js:172 +#: assets/build/entries.js:172 +#: assets/build/forms.js:172 +msgid "Select Date Range" msgstr "" -#: assets/build/dashboard.js:98052 -#: assets/build/dashboard.js:84260 -msgid "Style your form to better match your site's design" +#: assets/build/dashboard.js:172 +#: assets/build/payments.js:2 +msgid "Apply" msgstr "" -#: assets/build/dashboard.js:98052 -#: assets/build/dashboard.js:84261 -msgid "Set up confirmation messages and email notifications for each entry" +#: assets/build/dashboard.js:172 +#: assets/build/entries.js:172 +#: assets/build/forms.js:172 +msgid "All Forms" msgstr "" -#: assets/build/dashboard.js:98052 -#: assets/build/dashboard.js:84265 -msgid "Add spam protection to block common bot submissions" +#: assets/build/dashboard.js:172 +msgid "Please wait for the data to load" msgstr "" -#: assets/build/dashboard.js:98052 -#: assets/build/dashboard.js:84266 -msgid "Get weekly email reports with a summary of form activity" +#: assets/build/dashboard.js:172 +msgid "No entries to display" msgstr "" -#: assets/build/dashboard.js:98118 -#: assets/build/dashboard.js:84330 -msgid "You're All Set! ๐Ÿš€" +#: assets/build/dashboard.js:172 +msgid "Once you create a form and start receiving submissions, the data will appear here." msgstr "" -#: assets/build/dashboard.js:98124 -#: assets/build/dashboard.js:84334 -msgid "Use our AI form builder to get started quickly, or build your form from scratch if you already know what you need. Your forms are ready to create, share, and connect with your site visitors." +#: assets/build/dashboard.js:172 +msgid "Exit Guided Setup" msgstr "" -#: assets/build/dashboard.js:98130 -#: assets/build/dashboard.js:84343 -msgid "Final Touches That Make a Difference:" +#: assets/build/dashboard.js:172 +#: assets/build/settings.js:172 +msgid "Skip" msgstr "" -#: assets/build/dashboard.js:98147 -#: assets/build/dashboard.js:84369 -msgid "Build Your First Form" +#: assets/build/dashboard.js:172 +msgid "Build beautiful forms visually" msgstr "" -#: assets/build/dashboard.js:98203 -#: assets/build/dashboard.js:84392 -msgid "Works smoothly with forms made using SureForms" +#: assets/build/dashboard.js:172 +msgid "Works perfectly on mobile" msgstr "" -#: assets/build/dashboard.js:98203 -#: assets/build/dashboard.js:84393 -msgid "Helps your emails reach the inbox instead of spam" +#: assets/build/dashboard.js:172 +msgid "Spam protection included" msgstr "" -#: assets/build/dashboard.js:98203 -#: assets/build/dashboard.js:84394 -msgid "Setup is straightforward, even if you're not technical" +#: assets/build/dashboard.js:172 +msgid "Easy to connect with automation tools" msgstr "" -#: assets/build/dashboard.js:98203 -#: assets/build/dashboard.js:84395 -msgid "Lightweight and easy to use without adding clutter" +#: assets/build/dashboard.js:172 +msgid "Welcome to SureForms" msgstr "" -#: assets/build/dashboard.js:98435 -#: assets/build/dashboard.js:84614 -msgid "Make Sure Your Emails Get Delivered" +#: assets/build/dashboard.js:172 +msgid "Smart, Quick and Powerful Forms." msgstr "" -#: assets/build/dashboard.js:98441 -#: assets/build/dashboard.js:84621 -msgid "Most WordPress sites struggle to send emails reliably, which means form submissions from your site might not reach your inbox โ€” or end up in spam." +#: assets/build/dashboard.js:172 +msgid "Let's Get Started" msgstr "" -#: assets/build/dashboard.js:98445 -#: assets/build/dashboard.js:84627 -msgid "SureMail is a simple SMTP plugin that helps make sure your emails actually get delivered." +#: assets/build/dashboard.js:172 +msgid "Build up to 10 forms using AI" msgstr "" -#: assets/build/dashboard.js:98453 -#: assets/build/dashboard.js:84640 -msgid "What you will get:" +#: assets/build/dashboard.js:172 +msgid "A secure and private connection" msgstr "" -#: assets/build/dashboard.js:98470 -#: assets/build/dashboard.js:84665 -msgid "Install SureMail" +#: assets/build/dashboard.js:172 +msgid "Smart form drafts based on your input" msgstr "" -#: assets/build/dashboard.js:98637 -#: assets/build/dashboard.js:84792 -msgid "Import forms" +#: assets/build/dashboard.js:172 +msgid "Starting from a blank form isn't always easy. Our AI can help by creating a draft form based on what you're trying to do โ€” saving you time and giving you a clear direction." msgstr "" -#. translators: %d: number of forms that will be imported. -#: assets/build/dashboard.js:98640 -#: assets/build/dashboard.js:84796 -#, js-format -msgid "Import %d form" -msgid_plural "Import %d forms" -msgstr[0] "" -msgstr[1] "" - -#: assets/build/dashboard.js:98673 -#: assets/build/dashboard.js:84839 -msgid "Something went wrong while importing. You can retry, skip, or open Settings โ†’ Migration." +#: assets/build/dashboard.js:172 +msgid "To do this, you'll need to connect your account." msgstr "" -#: assets/build/dashboard.js:98727 -#: assets/build/dashboard.js:84887 -msgid "No other form plugins detected. You can import any time from Settings โ†’ Migration." +#: assets/build/dashboard.js:172 +msgid "Let AI Help You Build Smarter, Faster Forms" msgstr "" -#: assets/build/dashboard.js:98751 -#: assets/build/dashboard.js:84915 -msgid "Forms imported" +#: assets/build/dashboard.js:172 +msgid "Here's what that gives you:" msgstr "" -#. translators: 1: imported count, 2: source plugin title. -#: assets/build/dashboard.js:98758 -#: assets/build/dashboard.js:84921 -#, js-format -msgid "%1$d form from %2$s is now in SureForms, ready to publish, style, and connect." -msgid_plural "%1$d forms from %2$s are now in SureForms, ready to publish, style, and connect." -msgstr[0] "" -msgstr[1] "" - -#. translators: %d: imported form count. -#: assets/build/dashboard.js:98769 -#: assets/build/dashboard.js:84939 -#, js-format -msgid "%d form imported" -msgid_plural "%d forms imported" -msgstr[0] "" -msgstr[1] "" - -#. translators: %d: failed form count. -#: assets/build/dashboard.js:98776 -#: assets/build/dashboard.js:84954 -#, js-format -msgid "%d form could not be imported" -msgid_plural "%d forms could not be imported" -msgstr[0] "" -msgstr[1] "" +#: assets/build/dashboard.js:172 +#: assets/build/settings.js:172 +msgid "Continue" +msgstr "" -#. translators: %d: count of unsupported fields. -#: assets/build/dashboard.js:98783 -#: assets/build/dashboard.js:84970 -#, js-format -msgid "%d field type was unsupported. You can rebuild it manually inside SureForms." -msgid_plural "%d field types were unsupported. You can rebuild them manually inside SureForms." -msgstr[0] "" -msgstr[1] "" +#: assets/build/dashboard.js:172 +msgid "Connect" +msgstr "" -#: assets/build/dashboard.js:98800 -#: assets/build/dashboard.js:84999 -msgid "Bring your existing forms with you" +#: assets/build/dashboard.js:172 +msgid "Works smoothly with forms made using SureForms" msgstr "" -#: assets/build/dashboard.js:98806 -#: assets/build/dashboard.js:85006 -msgid "We detected forms in another plugin. Pick one to import into SureForms." +#: assets/build/dashboard.js:172 +msgid "Helps your emails reach the inbox instead of spam" msgstr "" -#: assets/build/dashboard.js:98808 -#: assets/build/dashboard.js:85016 -msgid "Choose a form plugin to import from" +#: assets/build/dashboard.js:172 +msgid "Setup is straightforward, even if you're not technical" msgstr "" -#: assets/build/dashboard.js:98823 -#: assets/build/dashboard.js:85034 -msgid "Importing more than one plugin? You can import additional sources later from Settings โ†’ Migration." +#: assets/build/dashboard.js:172 +msgid "Lightweight and easy to use without adding clutter" msgstr "" -#: assets/build/dashboard.js:98825 -#: assets/build/dashboard.js:85043 -msgid "Import did not complete" +#: assets/build/dashboard.js:172 +msgid "Make Sure Your Emails Get Delivered" msgstr "" -#: assets/build/dashboard.js:98833 -#: assets/build/dashboard.js:85057 -msgid "I'll do this later" +#: assets/build/dashboard.js:172 +msgid "Most WordPress sites struggle to send emails reliably, which means form submissions from your site might not reach your inbox โ€” or end up in spam." msgstr "" -#: assets/build/dashboard.js:98837 -#: assets/build/forms.js:65269 -#: assets/build/dashboard.js:85066 -#: assets/build/forms.js:56262 -msgid "Importingโ€ฆ" +#: assets/build/dashboard.js:172 +msgid "SureMail is a simple SMTP plugin that helps make sure your emails actually get delivered." msgstr "" -#: assets/build/dashboard.js:98837 -#: assets/build/dashboard.js:85068 -msgid "Retry" +#: assets/build/dashboard.js:172 +msgid "What you will get:" msgstr "" -#: assets/build/dashboard.js:98906 -#: assets/build/dashboard.js:85098 +#: assets/build/dashboard.js:172 +msgid "Install SureMail" +msgstr "" + +#: assets/build/dashboard.js:172 msgid "AI Form Generation" msgstr "" -#: assets/build/dashboard.js:98907 -#: assets/build/dashboard.js:85099 +#: assets/build/dashboard.js:172 msgid "Tired of building forms manually? Let AI do the work for you. Just describe and our AI will create your perfect form in seconds." msgstr "" -#: assets/build/dashboard.js:98912 -#: assets/build/dashboard.js:85108 +#: assets/build/dashboard.js:172 msgid "Payment Forms" msgstr "" -#: assets/build/dashboard.js:98913 -#: assets/build/dashboard.js:85109 +#: assets/build/dashboard.js:172 msgid "Collect payments directly through your forms. Accept one-time and recurring payments seamlessly." msgstr "" -#: assets/build/dashboard.js:98920 -#: assets/build/dashboard.js:85120 +#: assets/build/dashboard.js:172 msgid "Multistep Forms" msgstr "" -#: assets/build/dashboard.js:98921 -#: assets/build/dashboard.js:85121 +#: assets/build/dashboard.js:172 msgid "Break complex forms into simple steps, reducing overwhelm and boosting completion rates. Guide users smoothly through the process" msgstr "" -#: assets/build/dashboard.js:98925 -#: assets/build/dashboard.js:85129 +#: assets/build/dashboard.js:172 msgid "Conditional Fields" msgstr "" -#: assets/build/dashboard.js:98926 -#: assets/build/dashboard.js:85130 +#: assets/build/dashboard.js:172 msgid "Show or hide fields based on user answers. Ask the right questions and display only what's needed to keep forms clean and relevant." msgstr "" -#: assets/build/dashboard.js:98930 -#: assets/build/dashboard.js:85138 +#: assets/build/dashboard.js:172 msgid "Webhooks" msgstr "" -#: assets/build/dashboard.js:98931 -#: assets/build/dashboard.js:85139 +#: assets/build/dashboard.js:172 msgid "Send form entries instantly to any external system or endpoint to power advanced workflows." msgstr "" -#: assets/build/dashboard.js:98936 -#: assets/build/dashboard.js:85148 +#: assets/build/dashboard.js:172 msgid "Enhance your forms with advanced fields like multi-file upload, rating fields, and date & time pickers to collect richer, flexible data." msgstr "" -#: assets/build/dashboard.js:98943 -#: assets/build/dashboard.js:85159 +#: assets/build/dashboard.js:172 msgid "Create forms that feel like a conversation. One question at a time keeps users engaged and makes form completion easy." msgstr "" -#: assets/build/dashboard.js:98947 -#: assets/build/dashboard.js:85167 +#: assets/build/dashboard.js:172 msgid "Digital Signatures" msgstr "" -#: assets/build/dashboard.js:98948 -#: assets/build/dashboard.js:85168 +#: assets/build/dashboard.js:172 msgid "Collect legally binding digital signatures directly in your forms for agreements, approvals, and contracts." msgstr "" -#: assets/build/dashboard.js:98954 -#: assets/build/dashboard.js:85178 +#: assets/build/dashboard.js:172 msgid "Calculators" msgstr "" -#: assets/build/dashboard.js:98955 -#: assets/build/dashboard.js:85179 +#: assets/build/dashboard.js:172 msgid "Add interactive calculators to your forms for instant estimates, quotes, and calculations for your users." msgstr "" -#: assets/build/dashboard.js:98959 -#: assets/build/dashboard.js:85187 +#: assets/build/dashboard.js:172 msgid "User Registration and Login" msgstr "" -#: assets/build/dashboard.js:98960 -#: assets/build/dashboard.js:85188 +#: assets/build/dashboard.js:172 msgid "Allow visitors to register and log in to your site. Useful for membership, community, or any site that needs user access." msgstr "" -#: assets/build/dashboard.js:98964 -#: assets/build/dashboard.js:85196 +#: assets/build/dashboard.js:172 msgid "PDF Generation Made Simple" msgstr "" -#: assets/build/dashboard.js:98965 -#: assets/build/dashboard.js:85197 +#: assets/build/dashboard.js:172 msgid "Automatically turn form entries into clean, ready-to-download PDFs. Perfect for records, sharing, archiving, or keeping things organized." msgstr "" -#: assets/build/dashboard.js:98969 -#: assets/build/dashboard.js:85205 +#: assets/build/dashboard.js:172 msgid "Custom App" msgstr "" -#: assets/build/dashboard.js:98970 -#: assets/build/dashboard.js:85206 +#: assets/build/dashboard.js:172 msgid "Collect data, send it to external applications for processing, and display results instantly โ€” all seamlessly integrated to create dynamic, interactive user experiences." msgstr "" -#: assets/build/dashboard.js:99265 -#: assets/build/dashboard.js:85531 -msgid "Free" +#: assets/build/dashboard.js:172 +msgid "Select Your Features" msgstr "" -#. translators: %s: plan name -#: assets/build/dashboard.js:99296 -#: assets/build/dashboard.js:85571 -#, js-format -msgid "SureForms %s" +#: assets/build/dashboard.js:172 +msgid "Get more control, faster workflows, and deeper customization โ€” all designed to help you build better websites with less effort." msgstr "" -#: assets/build/dashboard.js:99301 -#: assets/build/dashboard.js:85579 -msgid "Select Your Features" +#: assets/build/dashboard.js:172 +msgid "Free" msgstr "" -#: assets/build/dashboard.js:99302 -#: assets/build/dashboard.js:85580 -msgid "Get more control, faster workflows, and deeper customization โ€” all designed to help you build better websites with less effort." +#: assets/build/dashboard.js:172 +#, js-format +msgid "Selected features require %1$s - use code %2$s to get 10% off on any plan." msgstr "" -#. translators: 1: Plan name (Starter, Pro, or Business), 2: Coupon code -#: assets/build/dashboard.js:99355 -#: assets/build/dashboard.js:85669 +#: assets/build/dashboard.js:172 #, js-format -msgid "Selected features require %1$s - use code %2$s to get 10% off on any plan." +msgid "SureForms %s" msgstr "" -#: assets/build/dashboard.js:99428 -#: assets/build/dashboard.js:85771 +#: assets/build/dashboard.js:172 msgid "Copied" msgstr "" -#: assets/build/dashboard.js:99521 -#: assets/build/dashboard.js:85833 +#: assets/build/dashboard.js:172 msgid "First name is required." msgstr "" -#: assets/build/dashboard.js:99524 -#: assets/build/dashboard.js:85840 -msgid "Email address is required." +#: assets/build/dashboard.js:172 +msgid "Please enter a valid email address." msgstr "" -#: assets/build/dashboard.js:99526 -#: assets/build/dashboard.js:85845 -msgid "Please enter a valid email address." +#: assets/build/dashboard.js:172 +msgid "Email address is required." msgstr "" -#: assets/build/dashboard.js:99529 -#: assets/build/dashboard.js:85852 +#: assets/build/dashboard.js:172 msgid "This is required." msgstr "" -#: assets/build/dashboard.js:99590 -#: assets/build/dashboard.js:85897 +#: assets/build/dashboard.js:172 msgid "Okay, just one last stepโ€ฆ" msgstr "" -#: assets/build/dashboard.js:99596 -#: assets/build/dashboard.js:85901 +#: assets/build/dashboard.js:172 msgid "Help us tailor your SureForms experience by sharing a bit about yourself." msgstr "" -#: assets/build/dashboard.js:99605 -#: assets/build/dashboard.js:85914 +#: assets/build/dashboard.js:172 msgid "First Name" msgstr "" -#: assets/build/dashboard.js:99606 -#: assets/build/dashboard.js:85915 +#: assets/build/dashboard.js:172 msgid "Enter your first name" msgstr "" -#: assets/build/dashboard.js:99618 -#: assets/build/dashboard.js:85931 +#: assets/build/dashboard.js:172 msgid "Last Name" msgstr "" -#: assets/build/dashboard.js:99619 -#: assets/build/dashboard.js:85932 +#: assets/build/dashboard.js:172 msgid "Enter your last name" msgstr "" -#: assets/build/dashboard.js:99628 -#: assets/build/dashboard.js:85944 +#: assets/build/dashboard.js:172 msgid "Email Address" msgstr "" -#: assets/build/dashboard.js:99629 -#: assets/build/dashboard.js:85945 +#: assets/build/dashboard.js:172 msgid "Enter your email address" msgstr "" -#: assets/build/dashboard.js:99643 -#: assets/build/dashboard.js:85966 +#: assets/build/dashboard.js:172 msgid "Stay in the loop and help shape SureForms! Get feature updates, and help us in betterment of SureForms by sharing how you use the plugin. Privacy Policy." msgstr "" -#: assets/build/dashboard.js:99649 -#: assets/build/dashboard.js:85978 +#: assets/build/dashboard.js:172 msgid "Privacy Policy" msgstr "" -#: assets/build/dashboard.js:99661 -#: assets/build/dashboard.js:86006 +#: assets/build/dashboard.js:172 msgid "Finish" msgstr "" -#: assets/build/dashboard.js:99698 -#: assets/build/dashboard.js:86028 -msgid "Build beautiful forms visually" -msgstr "" - -#: assets/build/dashboard.js:99698 -#: assets/build/dashboard.js:86029 -msgid "Works perfectly on mobile" -msgstr "" - -#: assets/build/dashboard.js:99698 -#: assets/build/dashboard.js:86030 -msgid "Spam protection included" -msgstr "" - -#: assets/build/dashboard.js:99698 -#: assets/build/dashboard.js:86031 -msgid "Easy to connect with automation tools" -msgstr "" - -#: assets/build/dashboard.js:99711 -#: assets/build/dashboard.js:86041 -msgid "Welcome to SureForms" -msgstr "" +#: assets/build/dashboard.js:172 +#, js-format +msgid "%d form ready" +msgid_plural "%d forms ready" +msgstr[0] "" +msgstr[1] "" -#: assets/build/dashboard.js:99714 -#: assets/build/dashboard.js:86044 -msgid "Smart, Quick and Powerful Forms." -msgstr "" +#: assets/build/dashboard.js:172 +#, js-format +msgid "%d already imported" +msgid_plural "%d already imported" +msgstr[0] "" +msgstr[1] "" -#: assets/build/dashboard.js:99728 -#: assets/build/dashboard.js:86066 -msgid "Let's Get Started" +#: assets/build/dashboard.js:172 +msgid "(unnamed source)" msgstr "" -#: assets/build/entries.js:66717 -#: assets/build/forms.js:61572 -#: assets/build/entries.js:57753 -#: assets/build/forms.js:52779 -msgid "No results found" +#: assets/build/dashboard.js:172 +msgid "All forms already imported" msgstr "" -#: assets/build/entries.js:66723 -#: assets/build/forms.js:61578 -#: assets/build/entries.js:57762 -#: assets/build/forms.js:52788 -msgid "We couldn't find any records matching your filters. Try adjusting the filters or resetting them to see all results." -msgstr "" +#: assets/build/dashboard.js:172 +#, js-format +msgid "Import %d form" +msgid_plural "Import %d forms" +msgstr[0] "" +msgstr[1] "" -#: assets/build/entries.js:66727 -#: assets/build/forms.js:61582 -#: assets/build/entries.js:57772 -#: assets/build/forms.js:52798 -msgid "Clear Filter" +#: assets/build/dashboard.js:172 +msgid "Import forms" msgstr "" -#: assets/build/entries.js:66861 -#: assets/build/formEditor.js:126090 -#: assets/build/forms.js:61716 -#: assets/build/payments.js:172 -#: assets/build/settings.js:71179 -#: assets/build/settings.js:79725 -#: assets/build/entries.js:57898 -#: assets/build/formEditor.js:115749 -#: assets/build/forms.js:52924 -#: assets/build/settings.js:63429 -#: assets/build/settings.js:72586 -msgid "Page" +#: assets/build/dashboard.js:172 +msgid "Something went wrong while importing. You can retry, skip, or open Settings โ†’ Migration." msgstr "" -#: assets/build/entries.js:66861 -#: assets/build/forms.js:61716 -#: assets/build/payments.js:172 -#: assets/build/settings.js:71179 -#: assets/build/entries.js:57899 -#: assets/build/forms.js:52925 -#: assets/build/settings.js:63430 -msgid "out of" +#: assets/build/dashboard.js:172 +msgid "No other form plugins detected. You can import any time from Settings โ†’ Migration." msgstr "" -#: assets/build/entries.js:66979 -#: assets/build/entries.js:68970 -#: assets/build/forms.js:61834 -#: assets/build/settings.js:71297 -#: assets/build/entries.js:58014 -#: assets/build/entries.js:60043 -#: assets/build/forms.js:53040 -#: assets/build/settings.js:63545 -msgid "No entries found" +#: assets/build/dashboard.js:172 +msgid "Forms imported" msgstr "" -#: assets/build/entries.js:67371 -#: assets/build/entries.js:67377 -#: assets/build/formEditor.js:120090 -#: assets/build/formEditor.js:120096 -#: assets/build/forms.js:62226 -#: assets/build/forms.js:62232 -#: assets/build/payments.js:172 -#: assets/build/settings.js:71493 -#: assets/build/settings.js:71499 -#: assets/build/entries.js:58429 -#: assets/build/entries.js:58434 -#: assets/build/formEditor.js:109229 -#: assets/build/formEditor.js:109234 -#: assets/build/forms.js:53455 -#: assets/build/forms.js:53460 -#: assets/build/settings.js:63777 -#: assets/build/settings.js:63782 -msgid "delete" -msgstr "" +#: assets/build/dashboard.js:172 +#, js-format +msgid "%1$d form from %2$s is now in SureForms, ready to publish, style, and connect." +msgid_plural "%1$d forms from %2$s are now in SureForms, ready to publish, style, and connect." +msgstr[0] "" +msgstr[1] "" -#. translators: %s is the confirmation text -#: assets/build/entries.js:67461 -#: assets/build/formEditor.js:120180 -#: assets/build/forms.js:62316 -#: assets/build/payments.js:172 -#: assets/build/settings.js:71583 -#: assets/build/entries.js:58491 -#: assets/build/formEditor.js:109291 -#: assets/build/forms.js:53517 -#: assets/build/settings.js:63839 +#: assets/build/dashboard.js:172 #, js-format -msgid "Please type \"%s\" in the input box" -msgstr "" +msgid "%d form imported" +msgid_plural "%d forms imported" +msgstr[0] "" +msgstr[1] "" -#. translators: %s is the confirmation text -#: assets/build/entries.js:67500 -#: assets/build/formEditor.js:120219 -#: assets/build/forms.js:62355 -#: assets/build/payments.js:172 -#: assets/build/settings.js:71622 -#: assets/build/entries.js:58543 -#: assets/build/formEditor.js:109343 -#: assets/build/forms.js:53569 -#: assets/build/settings.js:63891 +#: assets/build/dashboard.js:172 #, js-format -msgid "To confirm, type \"%s\" in the box below:" -msgstr "" +msgid "%d form could not be imported" +msgid_plural "%d forms could not be imported" +msgstr[0] "" +msgstr[1] "" -#. translators: %s is the confirmation text -#: assets/build/entries.js:67511 -#: assets/build/formEditor.js:120230 -#: assets/build/forms.js:62366 -#: assets/build/payments.js:172 -#: assets/build/settings.js:71633 -#: assets/build/entries.js:58562 -#: assets/build/formEditor.js:109362 -#: assets/build/forms.js:53588 -#: assets/build/settings.js:63910 +#: assets/build/dashboard.js:172 #, js-format -msgid "Type \"%s\"" -msgstr "" +msgid "%d field type was unsupported. You can rebuild it manually inside SureForms." +msgid_plural "%d field types were unsupported. You can rebuild them manually inside SureForms." +msgstr[0] "" +msgstr[1] "" -#: assets/build/entries.js:67611 -#: assets/build/forms.js:62466 -#: assets/build/payments.js:2 -#: assets/build/entries.js:58643 -#: assets/build/forms.js:53669 -msgid "mm/dd/yyyy - mm/dd/yyyy" +#: assets/build/dashboard.js:172 +msgid "Bring your existing forms with you" msgstr "" -#: assets/build/entries.js:68542 -#: assets/build/entries.js:59542 -msgid "Track submission for all your forms" +#: assets/build/dashboard.js:172 +msgid "We detected forms in another plugin. Pick one to import into SureForms." msgstr "" -#: assets/build/entries.js:68542 -#: assets/build/entries.js:59543 -msgid "View, filter, and analyze submissions in real time" +#: assets/build/dashboard.js:172 +msgid "Choose a form plugin to import from" msgstr "" -#: assets/build/entries.js:68542 -#: assets/build/entries.js:59544 -msgid "Export data for further processing" +#: assets/build/dashboard.js:172 +msgid "Importing more than one plugin? You can import additional sources later from Settings โ†’ Migration." msgstr "" -#: assets/build/entries.js:68542 -#: assets/build/entries.js:59545 -msgid "Edit and manage your entries with ease" +#: assets/build/dashboard.js:172 +msgid "Import did not complete" msgstr "" -#: assets/build/entries.js:68555 -#: assets/build/entries.js:59563 -msgid "No entries yet" +#: assets/build/dashboard.js:172 +msgid "I'll do this later" msgstr "" -#: assets/build/entries.js:68565 -#: assets/build/entries.js:59578 -msgid "No entries? No worries! This page will be flooded soon!" +#: assets/build/dashboard.js:172 +#: assets/build/forms.js:172 +msgid "Importingโ€ฆ" msgstr "" -#: assets/build/entries.js:68572 -#: assets/build/entries.js:59592 -msgid "Once you publish and share your form, this space will turn into a powerful insights hub where you can:" +#: assets/build/dashboard.js:172 +msgid "Retry" msgstr "" -#: assets/build/entries.js:68590 -#: assets/build/entries.js:59622 -msgid "Go to Forms" +#: assets/build/dashboard.js:172 +msgid "Style your form to better match your site's design" msgstr "" -#: assets/build/entries.js:68709 -#: assets/build/entries.js:59718 -msgid "Export Selected" +#: assets/build/dashboard.js:172 +msgid "Set up confirmation messages and email notifications for each entry" msgstr "" -#: assets/build/entries.js:68709 -#: assets/build/entries.js:59719 -msgid "Export All" +#: assets/build/dashboard.js:172 +msgid "Add spam protection to block common bot submissions" msgstr "" -#: assets/build/entries.js:68715 -#: assets/build/entries.js:59727 -msgid "Mark as Read" +#: assets/build/dashboard.js:172 +msgid "Get weekly email reports with a summary of form activity" msgstr "" -#: assets/build/entries.js:68722 -#: assets/build/entries.js:70118 -#: assets/build/entries.js:59735 -#: assets/build/entries.js:61187 -msgid "Mark as Unread" +#: assets/build/dashboard.js:172 +msgid "You're All Set! ๐Ÿš€" msgstr "" -#: assets/build/entries.js:68795 -#: assets/build/entries.js:68801 -#: assets/build/entries.js:59847 -#: assets/build/entries.js:59856 -msgid "Untitled" +#: assets/build/dashboard.js:172 +msgid "Use our AI form builder to get started quickly, or build your form from scratch if you already know what you need. Your forms are ready to create, share, and connect with your site visitors." msgstr "" -#: assets/build/entries.js:68811 -#: assets/build/entries.js:59876 -msgid "Search entriesโ€ฆ" +#: assets/build/dashboard.js:172 +msgid "Final Touches That Make a Difference:" msgstr "" -#: assets/build/entries.js:68827 -#: assets/build/entries.js:59906 -msgid "Resend Notifications" +#: assets/build/dashboard.js:172 +msgid "Build Your First Form" msgstr "" -#: assets/build/entries.js:68836 -#: assets/build/entries.js:69097 -#: assets/build/entries.js:69098 -#: assets/build/entries.js:71570 -#: assets/build/forms.js:63494 -#: assets/build/forms.js:64368 -#: assets/build/forms.js:64904 -#: assets/build/entries.js:59922 -#: assets/build/entries.js:60199 -#: assets/build/entries.js:60200 -#: assets/build/entries.js:62592 -#: assets/build/forms.js:54653 -#: assets/build/forms.js:55377 -#: assets/build/forms.js:55884 -msgid "Restore" +#: assets/build/entries.js:2 +msgid "All Form Entries" msgstr "" -#: assets/build/entries.js:68846 -#: assets/build/formEditor.js:125737 -#: assets/build/formEditor.js:125777 +#: assets/build/entries.js:172 +#: assets/build/forms.js:172 #: assets/build/payments.js:2 -#: assets/build/entries.js:59935 -#: assets/build/formEditor.js:115390 -#: assets/build/formEditor.js:115464 -msgid "Delete" +msgid "mm/dd/yyyy - mm/dd/yyyy" msgstr "" -#: assets/build/entries.js:68897 -#: assets/build/entries.js:59997 -msgid "All Form Entries" +#: assets/build/entries.js:172 +msgid "All Statuses" msgstr "" -#: assets/build/entries.js:69027 -#: assets/build/entries.js:70257 -#: assets/build/entries.js:60112 -#: assets/build/entries.js:61306 -msgid "First Field" +#: assets/build/entries.js:172 +msgid "Read" msgstr "" -#: assets/build/entries.js:69043 -#: assets/build/formEditor.js:126980 -#: assets/build/entries.js:60138 -#: assets/build/formEditor.js:116877 -msgid "Repeater" +#: assets/build/entries.js:172 +msgid "Unread" msgstr "" -#: assets/build/entries.js:69046 -#: assets/build/forms.js:64797 -#: assets/build/entries.js:60144 -#: assets/build/forms.js:55795 -msgid "Date & Time" +#: assets/build/entries.js:172 +msgid "First Field" msgstr "" -#: assets/build/entries.js:69078 -#: assets/build/entries.js:70264 -#: assets/build/formEditor.js:125635 -#: assets/build/forms.js:64818 +#: assets/build/entries.js:172 +msgid "Date and Time" +msgstr "" + +#: assets/build/entries.js:172 +#: assets/build/formEditor.js:172 +#: assets/build/forms.js:172 #: assets/build/payments.js:172 -#: assets/build/entries.js:60182 -#: assets/build/entries.js:61315 -#: assets/build/formEditor.js:115241 -#: assets/build/forms.js:55821 msgid "Actions" msgstr "" -#: assets/build/entries.js:69086 -#: assets/build/entries.js:69087 -#: assets/build/entries.js:60190 -#: assets/build/entries.js:60191 -msgid "Preview" +#: assets/build/entries.js:172 +msgid "Export Selected" msgstr "" -#: assets/build/entries.js:69105 -#: assets/build/entries.js:69106 -#: assets/build/entries.js:71396 -#: assets/build/entries.js:71470 -#: assets/build/forms.js:63532 -#: assets/build/forms.js:63689 -#: assets/build/forms.js:64385 -#: assets/build/forms.js:64916 -#: assets/build/payments.js:172 -#: assets/build/entries.js:60205 -#: assets/build/entries.js:60206 -#: assets/build/entries.js:62359 -#: assets/build/entries.js:62457 -#: assets/build/forms.js:54685 -#: assets/build/forms.js:54789 -#: assets/build/forms.js:55404 -#: assets/build/forms.js:55892 -msgid "Delete Permanently" +#: assets/build/entries.js:172 +msgid "Export All" msgstr "" -#: assets/build/entries.js:69114 -#: assets/build/entries.js:69115 -#: assets/build/entries.js:71411 -#: assets/build/entries.js:71470 -#: assets/build/forms.js:63456 -#: assets/build/forms.js:63612 -#: assets/build/forms.js:64892 -#: assets/build/entries.js:60212 -#: assets/build/entries.js:60213 -#: assets/build/entries.js:62375 -#: assets/build/entries.js:62458 -#: assets/build/forms.js:54621 -#: assets/build/forms.js:54743 -#: assets/build/forms.js:55876 -msgid "Move to Trash" +#: assets/build/entries.js:172 +msgid "Mark as Read" msgstr "" -#. translators: %d: number of items -#: assets/build/entries.js:69228 -#: assets/build/entries.js:60314 -#, js-format -msgid "%d item" -msgid_plural "%d items" -msgstr[0] "" -msgstr[1] "" +#: assets/build/entries.js:172 +msgid "Mark as Unread" +msgstr "" -#: assets/build/entries.js:69316 -#: assets/build/entries.js:60421 -msgid "Entry Data" +#: assets/build/entries.js:172 +msgid "Untitled" msgstr "" -#: assets/build/entries.js:69509 -#: assets/build/entries.js:60587 -msgid "Edit Entry" +#: assets/build/entries.js:172 +msgid "Search entriesโ€ฆ" msgstr "" -#: assets/build/entries.js:69514 -#: assets/build/entries.js:60597 -msgid "Unlock Edit Form Entires" +#: assets/build/entries.js:172 +msgid "Resend Notifications" msgstr "" -#: assets/build/entries.js:69515 -#: assets/build/entries.js:60598 -msgid "With the SureForms Starter plan, you can easily edit your entries to suit your needs." +#: assets/build/entries.js:172 +#: assets/build/forms.js:172 +msgid "Restore" msgstr "" -#: assets/build/entries.js:69682 -#: assets/build/entries.js:60737 -msgid "Entry Logs" +#: assets/build/entries.js:172 +#: assets/build/formEditor.js:172 +#: assets/build/payments.js:2 +msgid "Delete" msgstr "" -#: assets/build/entries.js:69686 -#: assets/build/entries.js:60743 -msgid "Loading logsโ€ฆ" +#: assets/build/entries.js:172 +#: assets/build/formEditor.js:172 +#: assets/build/forms.js:172 +#: assets/build/payments.js:172 +#: assets/build/settings.js:172 +msgid "Page" msgstr "" -#: assets/build/entries.js:69688 +#: assets/build/entries.js:172 +#: assets/build/forms.js:172 #: assets/build/payments.js:172 -#: assets/build/entries.js:60747 -msgid "No logs available." +#: assets/build/settings.js:172 +msgid "out of" msgstr "" -#: assets/build/entries.js:69823 -#: assets/build/entries.js:60890 -msgid "Previous entry" +#: assets/build/entries.js:172 +#: assets/build/forms.js:172 +#: assets/build/settings.js:172 +msgid "No entries found" msgstr "" -#: assets/build/entries.js:69838 -#: assets/build/entries.js:60904 -msgid "Next entry" +#: assets/build/entries.js:172 +#: assets/build/formEditor.js:172 +msgid "Repeater" msgstr "" -#: assets/build/entries.js:69873 -#: assets/build/entries.js:60925 -msgid "Unlock Add Note" +#: assets/build/entries.js:172 +#: assets/build/forms.js:172 +msgid "Date & Time" msgstr "" -#: assets/build/entries.js:69874 -#: assets/build/entries.js:60926 -msgid "With the SureForms Starter plan, enhance your submitted form entries by adding personalized notes for better clarity and tracking." +#: assets/build/entries.js:172 +msgid "Preview" msgstr "" -#: assets/build/entries.js:69886 +#: assets/build/entries.js:172 +#: assets/build/forms.js:172 #: assets/build/payments.js:172 -#: assets/build/entries.js:60941 -msgid "Add Note" +msgid "Delete Permanently" msgstr "" -#: assets/build/entries.js:69916 -#: assets/build/payments.js:172 -#: assets/build/entries.js:60975 -msgid "Notes" +#: assets/build/entries.js:172 +#: assets/build/forms.js:172 +msgid "Move to Trash" msgstr "" -#: assets/build/entries.js:69926 -#: assets/build/payments.js:172 -#: assets/build/entries.js:60985 -msgid "Add an internal note." +#: assets/build/entries.js:172 +msgid "Track submission for all your forms" msgstr "" -#: assets/build/entries.js:70006 -#: assets/build/entries.js:61040 -msgid "Entry:" +#: assets/build/entries.js:172 +msgid "View, filter, and analyze submissions in real time" msgstr "" -#: assets/build/entries.js:70010 -#: assets/build/entries.js:61045 -msgid "Form name:" +#: assets/build/entries.js:172 +msgid "Export data for further processing" msgstr "" -#: assets/build/entries.js:70014 -#: assets/build/entries.js:61050 -msgid "User IP:" +#: assets/build/entries.js:172 +msgid "Edit and manage your entries with ease" msgstr "" -#: assets/build/entries.js:70021 -#: assets/build/entries.js:61058 -msgid "URL:" +#: assets/build/entries.js:172 +msgid "No entries yet" msgstr "" -#: assets/build/entries.js:70038 -#: assets/build/entries.js:61084 -msgid "Browser:" +#: assets/build/entries.js:172 +msgid "No entries? No worries! This page will be flooded soon!" msgstr "" -#: assets/build/entries.js:70042 -#: assets/build/entries.js:61089 -msgid "Device:" +#: assets/build/entries.js:172 +msgid "Once you publish and share your form, this space will turn into a powerful insights hub where you can:" msgstr "" -#: assets/build/entries.js:70046 -#: assets/build/entries.js:61094 -msgid "Language:" +#: assets/build/entries.js:172 +msgid "Go to Forms" msgstr "" -#: assets/build/entries.js:70050 -#: assets/build/entries.js:61099 -msgid "User:" +#: assets/build/entries.js:172 +#: assets/build/formEditor.js:172 +#: assets/build/forms.js:172 +#: assets/build/payments.js:172 +#: assets/build/settings.js:172 +msgid "delete" msgstr "" -#: assets/build/entries.js:70065 -#: assets/build/entries.js:61119 -msgid "Status:" +#: assets/build/entries.js:172 +#: assets/build/formEditor.js:172 +#: assets/build/forms.js:172 +#: assets/build/payments.js:172 +#: assets/build/settings.js:172 +#, js-format +msgid "Please type \"%s\" in the input box" msgstr "" -#: assets/build/entries.js:70072 -#: assets/build/entries.js:61125 -msgid "Submitted on:" +#: assets/build/entries.js:172 +#: assets/build/formEditor.js:172 +#: assets/build/forms.js:172 +#: assets/build/payments.js:172 +#: assets/build/settings.js:172 +#, js-format +msgid "To confirm, type \"%s\" in the box below:" msgstr "" -#: assets/build/entries.js:70098 -#: assets/build/entries.js:61154 -msgid "Entry info" +#: assets/build/entries.js:172 +#: assets/build/formEditor.js:172 +#: assets/build/forms.js:172 +#: assets/build/payments.js:172 +#: assets/build/settings.js:172 +#, js-format +msgid "Type \"%s\"" msgstr "" -#: assets/build/entries.js:70118 -#: assets/build/entries.js:61186 -msgid "Updatingโ€ฆ" +#: assets/build/entries.js:172 +#, js-format +msgid "Entry #%1$s marked as %2$s." msgstr "" -#: assets/build/entries.js:70209 -#: assets/build/entries.js:61263 -msgid "All Statuses" +#: assets/build/entries.js:172 +#, js-format +msgid "%1$s entry marked as %2$s." +msgid_plural "%1$s entries marked as %2$s." +msgstr[0] "" +msgstr[1] "" + +#: assets/build/entries.js:172 +msgid "An error occurred while updating read status. Please try again." msgstr "" -#: assets/build/entries.js:70212 -#: assets/build/entries.js:72240 -#: assets/build/entries.js:61264 -#: assets/build/entries.js:63216 -msgid "Read" +#: assets/build/entries.js:172 +#: assets/build/forms.js:172 +msgid "No results found" +msgstr "" + +#: assets/build/entries.js:172 +#: assets/build/forms.js:172 +msgid "We couldn't find any records matching your filters. Try adjusting the filters or resetting them to see all results." msgstr "" -#: assets/build/entries.js:70215 -#: assets/build/entries.js:72238 -#: assets/build/entries.js:61265 -#: assets/build/entries.js:63214 -msgid "Unread" +#: assets/build/entries.js:172 +#: assets/build/forms.js:172 +msgid "Clear Filter" msgstr "" -#: assets/build/entries.js:70260 -#: assets/build/entries.js:61310 -msgid "Date and Time" +#: assets/build/entries.js:172 +msgid "Entry" msgstr "" -#. translators: %1$s is the entry ID, %2$s is the action (read/unread). -#: assets/build/entries.js:70593 -#: assets/build/entries.js:61586 +#: assets/build/entries.js:172 #, js-format -msgid "Entry #%1$s marked as %2$s." +msgid "Entry #%s deleted permanently." msgstr "" -#. translators: %1$s is the number of entries marked as read, %2$s is the action. -#: assets/build/entries.js:70597 -#: assets/build/entries.js:61593 +#: assets/build/entries.js:172 #, js-format -msgid "%1$s entry marked as %2$s." -msgid_plural "%1$s entries marked as %2$s." +msgid "%s entry deleted permanently." +msgid_plural "%s entries deleted permanently." msgstr[0] "" msgstr[1] "" -#: assets/build/entries.js:70607 -#: assets/build/entries.js:61613 -msgid "An error occurred while updating read status. Please try again." +#: assets/build/entries.js:172 +msgid "An error occurred. Please try again." msgstr "" -#. translators: %s is the entry ID. -#: assets/build/entries.js:70643 -#: assets/build/entries.js:61652 +#: assets/build/entries.js:172 #, js-format msgid "Entry #%s moved to trash." msgstr "" -#. translators: %s is the entry ID. -#: assets/build/entries.js:70645 -#: assets/build/entries.js:61657 +#: assets/build/entries.js:172 #, js-format msgid "Entry #%s restored successfully." msgstr "" -#. translators: %s is the number of entries moved to trash. -#: assets/build/entries.js:70649 -#: assets/build/entries.js:61668 +#: assets/build/entries.js:172 #, js-format msgid "%1$s entry moved to trash." msgid_plural "%1$s entries moved to trash." msgstr[0] "" msgstr[1] "" -#. translators: %s is the number of entries restored. -#: assets/build/entries.js:70651 -#: assets/build/entries.js:61678 +#: assets/build/entries.js:172 #, js-format msgid "%1$s entry restored successfully." msgid_plural "%1$s entries restored successfully." msgstr[0] "" msgstr[1] "" -#: assets/build/entries.js:70656 -#: assets/build/entries.js:70698 -#: assets/build/entries.js:61692 -#: assets/build/entries.js:61744 -msgid "An error occurred. Please try again." -msgstr "" - -#. translators: %s is the entry ID. -#: assets/build/entries.js:70689 -#: assets/build/entries.js:61724 -#, js-format -msgid "Entry #%s deleted permanently." -msgstr "" - -#. translators: %s is the number of entries deleted. -#: assets/build/entries.js:70693 -#: assets/build/entries.js:61730 -#, js-format -msgid "%s entry deleted permanently." -msgid_plural "%s entries deleted permanently." -msgstr[0] "" -msgstr[1] "" - -#: assets/build/entries.js:70721 -#: assets/build/entries.js:61769 +#: assets/build/entries.js:172 msgid "An error occurred during export. Please try again." msgstr "" -#: assets/build/entries.js:71377 -#: assets/build/entries.js:62335 +#: assets/build/entries.js:172 msgid "An error occurred while fetching entries." msgstr "" -#: assets/build/entries.js:71394 -#: assets/build/entries.js:71464 -#: assets/build/entries.js:62354 -#: assets/build/entries.js:62423 +#: assets/build/entries.js:172 msgid "Delete entry permanently?" msgid_plural "Delete entries permanently?" msgstr[0] "" msgstr[1] "" -#: assets/build/entries.js:71395 -#: assets/build/entries.js:62355 -msgid "Are you sure you want to permanently delete this entry? This action cannot be undone." -msgstr "" - -#: assets/build/entries.js:71409 -#: assets/build/entries.js:71464 -#: assets/build/entries.js:62370 -#: assets/build/entries.js:62429 +#: assets/build/entries.js:172 msgid "Move entry to trash?" msgid_plural "Move entries to trash?" msgstr[0] "" msgstr[1] "" -#: assets/build/entries.js:71410 -#: assets/build/entries.js:62371 -msgid "This entry will be moved to trash and can be restored later." -msgstr "" - -#. translators: %s is the number of entries to be deleted. -#: assets/build/entries.js:71467 -#: assets/build/entries.js:62438 +#: assets/build/entries.js:172 #, js-format msgid "Are you sure you want to permanently delete %s entry? This action cannot be undone." msgid_plural "Are you sure you want to permanently delete %s entries? This action cannot be undone." msgstr[0] "" msgstr[1] "" -#. translators: %s is the number of entries to be moved to trash. -#: assets/build/entries.js:71469 -#: assets/build/entries.js:62448 +#: assets/build/entries.js:172 #, js-format msgid "%s entry will be moved to trash and can be restored later." msgid_plural "%s entries will be moved to trash and can be restored later." msgstr[0] "" msgstr[1] "" -#: assets/build/entries.js:71528 -#: assets/build/entries.js:62524 +#: assets/build/entries.js:172 msgid "Entries exported successfully!" msgstr "" -#: assets/build/entries.js:71566 -#: assets/build/entries.js:62576 +#: assets/build/entries.js:172 msgid "Restore Entry" msgid_plural "Restore Entries" msgstr[0] "" msgstr[1] "" -#. translators: %s is the number of entries to be restored. -#: assets/build/entries.js:71569 -#: assets/build/entries.js:62584 +#: assets/build/entries.js:172 #, js-format msgid "%s entry will be restored from trash." msgid_plural "%s entries will be restored from trash." msgstr[0] "" msgstr[1] "" -#: assets/build/entries.js:71774 -#: assets/build/entries.js:71788 -#: assets/build/entries.js:62776 -#: assets/build/entries.js:62798 -msgid "Resend Email Notification" +#: assets/build/entries.js:172 +msgid "Are you sure you want to permanently delete this entry? This action cannot be undone." msgstr "" -#: assets/build/entries.js:71779 -#: assets/build/entries.js:62784 -msgid "Unlock Resend Email Notification" +#: assets/build/entries.js:172 +msgid "This entry will be moved to trash and can be restored later." msgstr "" -#: assets/build/entries.js:71780 -#: assets/build/entries.js:62785 -msgid "With the SureForms Starter plan, you can effortlessly resend email notifications, ensuring your important updates reach their recipients with ease." +#: assets/build/entries.js:172 +msgid "Edit Entry" msgstr "" -#. translators: %s is the entry ID -#. translators: %s: Entry ID -#: assets/build/entries.js:71971 -#: assets/build/entries.js:72078 -#: assets/build/entries.js:62968 -#: assets/build/entries.js:63086 -#, js-format -msgid "Entry #%s" +#: assets/build/entries.js:172 +msgid "Unlock Edit Form Entires" msgstr "" -#: assets/build/entries.js:72306 -#: assets/build/entries.js:63284 -msgid "Entry" +#: assets/build/entries.js:172 +msgid "With the SureForms Starter plan, you can easily edit your entries to suit your needs." msgstr "" -#. translators: abbreviation for units -#: assets/build/formEditor.js:329 -#: modules/quick-action-sidebar/components/Modal.js:42 -#: assets/build/formEditor.js:68 +#: assets/build/entries.js:172 #, js-format -msgid "%s Added to Quick Action Bar." +msgid "%d item" +msgid_plural "%d items" +msgstr[0] "" +msgstr[1] "" + +#: assets/build/entries.js:172 +msgid "Entry Data" msgstr "" -#: assets/build/formEditor.js:422 -#: modules/quick-action-sidebar/components/Modal.js:145 -#: assets/build/formEditor.js:171 -msgid "Add to Quick Action Bar" +#: assets/build/entries.js:172 +msgid "Entry:" msgstr "" -#: assets/build/formEditor.js:428 -#: modules/quick-action-sidebar/components/Modal.js:155 -#: assets/build/formEditor.js:181 -msgid "Already Present in Quick Action Bar" +#: assets/build/entries.js:172 +msgid "Form name:" msgstr "" -#: assets/build/formEditor.js:434 -#: modules/quick-action-sidebar/components/Modal.js:174 -#: assets/build/formEditor.js:200 -msgid "No results found." +#: assets/build/entries.js:172 +msgid "User IP:" msgstr "" -#: assets/build/formEditor.js:629 -#: modules/quick-action-sidebar/components/Sidebar.js:181 -#: assets/build/formEditor.js:390 -msgid "Add blocks to Quick Action Bar" +#: assets/build/entries.js:172 +msgid "URL:" msgstr "" -#: assets/build/formEditor.js:661 -#: modules/quick-action-sidebar/components/Sidebar.js:231 -#: assets/build/formEditor.js:440 -msgid "Re-arrange block inside Quick Action Bar" +#: assets/build/entries.js:172 +msgid "Browser:" msgstr "" -#. translators: abbreviation for units -#: assets/build/formEditor.js:855 -#: modules/quick-action-sidebar/components/draggable-block.js:83 -#: assets/build/formEditor.js:632 -#, js-format -msgid "%s Removed from Quick Action Bar." +#: assets/build/entries.js:172 +msgid "Device:" msgstr "" -#: assets/build/formEditor.js:120540 -#: assets/build/settings.js:78151 -#: assets/build/formEditor.js:109616 -#: assets/build/settings.js:70818 -msgid "Send entries to 100+ popular apps." +#: assets/build/entries.js:172 +msgid "User:" msgstr "" -#: assets/build/formEditor.js:120540 -#: assets/build/settings.js:78151 -#: assets/build/formEditor.js:109617 -#: assets/build/settings.js:70819 -msgid "Build automated workflows that run instantly." +#: assets/build/entries.js:172 +msgid "Status:" msgstr "" -#: assets/build/formEditor.js:120540 -#: assets/build/settings.js:78151 -#: assets/build/formEditor.js:109618 -#: assets/build/settings.js:70820 -msgid "Create custom app integrations using our Custom App feature." +#: assets/build/entries.js:172 +msgid "Submitted on:" msgstr "" -#: assets/build/formEditor.js:120540 -#: assets/build/settings.js:78151 -#: assets/build/formEditor.js:109622 -#: assets/build/settings.js:70824 -msgid "Keep your tools in sync automatically." +#: assets/build/entries.js:172 +msgid "Entry info" msgstr "" -#: assets/build/formEditor.js:120596 -#: assets/build/formEditor.js:120597 -#: assets/build/settings.js:73732 -#: assets/build/settings.js:78207 -#: assets/build/settings.js:78208 -#: assets/build/formEditor.js:109668 -#: assets/build/formEditor.js:109669 -#: assets/build/settings.js:66115 -#: assets/build/settings.js:70870 -#: assets/build/settings.js:70871 -msgid "Connectingโ€ฆ" +#: assets/build/entries.js:172 +msgid "Updatingโ€ฆ" msgstr "" -#: assets/build/formEditor.js:120737 -#: assets/build/formEditor.js:120753 -#: assets/build/settings.js:78348 -#: assets/build/settings.js:78364 -#: assets/build/formEditor.js:109850 -#: assets/build/formEditor.js:109866 -#: assets/build/settings.js:71052 -#: assets/build/settings.js:71068 -msgid "Get Started" +#: assets/build/entries.js:172 +msgid "Unlock Add Note" msgstr "" -#: assets/build/formEditor.js:120739 -#: assets/build/formEditor.js:120753 -#: assets/build/settings.js:78350 -#: assets/build/settings.js:78364 -#: assets/build/formEditor.js:109852 -#: assets/build/formEditor.js:109867 -#: assets/build/settings.js:71054 -#: assets/build/settings.js:71069 -msgid "Connect with OttoKit" +#: assets/build/entries.js:172 +msgid "With the SureForms Starter plan, enhance your submitted form entries by adding personalized notes for better clarity and tracking." msgstr "" -#: assets/build/formEditor.js:120741 -#: assets/build/settings.js:78352 -#: assets/build/formEditor.js:109854 -#: assets/build/settings.js:71056 -msgid "Go to OttoKit Settings" +#: assets/build/entries.js:172 +#: assets/build/payments.js:172 +msgid "Add Note" msgstr "" -#: assets/build/formEditor.js:120799 -#: assets/build/settings.js:78410 -#: assets/build/formEditor.js:109935 -#: assets/build/settings.js:71137 -msgid "This will install and activate OttoKit on your WordPress site to enable automation features." +#: assets/build/entries.js:172 +#: assets/build/payments.js:172 +msgid "Notes" msgstr "" -#: assets/build/formEditor.js:120823 -#: assets/build/settings.js:78434 -#: assets/build/formEditor.js:109968 -#: assets/build/settings.js:71170 -msgid "Automate Your Forms with OttoKit" +#: assets/build/entries.js:172 +#: assets/build/payments.js:172 +msgid "Add an internal note." msgstr "" -#: assets/build/formEditor.js:120829 -#: assets/build/settings.js:78440 -#: assets/build/formEditor.js:109979 -#: assets/build/settings.js:71181 -msgid "Every form submission should trigger something โ€” a Slack alert, a CRM lead, a follow-up email, or a new row in Google Sheets." +#: assets/build/entries.js:172 +msgid "Entry Logs" msgstr "" -#: assets/build/formEditor.js:120945 -#: assets/build/settings.js:78918 -#: assets/build/formEditor.js:110079 -#: assets/build/settings.js:71693 -msgid "Enable GDPR Compliance" +#: assets/build/entries.js:172 +msgid "Loading logsโ€ฆ" msgstr "" -#: assets/build/formEditor.js:120946 -#: assets/build/settings.js:78919 -#: assets/build/formEditor.js:110080 -#: assets/build/settings.js:71694 -msgid "When enabled this form will not store User IP, Browser Name and the Device Name in the Entries." +#: assets/build/entries.js:172 +#: assets/build/payments.js:172 +msgid "No logs available." msgstr "" -#: assets/build/formEditor.js:120951 -#: assets/build/settings.js:78924 -#: assets/build/formEditor.js:110089 -#: assets/build/settings.js:71703 -msgid "Never store entry data after form submission" +#: assets/build/entries.js:172 +msgid "Previous entry" msgstr "" -#: assets/build/formEditor.js:120952 -#: assets/build/settings.js:78925 -#: assets/build/formEditor.js:110093 -#: assets/build/settings.js:71707 -msgid "When enabled this form will never store Entries." +#: assets/build/entries.js:172 +msgid "Next entry" msgstr "" -#: assets/build/formEditor.js:120958 -#: assets/build/settings.js:78931 -#: assets/build/formEditor.js:110103 -#: assets/build/settings.js:71717 -msgid "Automatically delete entries" +#: assets/build/entries.js:172 +msgid "Unlock Resend Email Notification" msgstr "" -#: assets/build/formEditor.js:120959 -#: assets/build/settings.js:78932 -#: assets/build/formEditor.js:110104 -#: assets/build/settings.js:71718 -msgid "When enabled this form will automatically delete entries after a certain period of time." +#: assets/build/entries.js:172 +msgid "With the SureForms Starter plan, you can effortlessly resend email notifications, ensuring your important updates reach their recipients with ease." msgstr "" -#: assets/build/formEditor.js:120987 -#: assets/build/settings.js:78960 -#: assets/build/formEditor.js:110135 -#: assets/build/settings.js:71749 -msgid "Entries older than the selected days will be deleted." +#: assets/build/entries.js:172 +msgid "Resend Email Notification" msgstr "" -#: assets/build/formEditor.js:120990 -#: assets/build/settings.js:78963 -#: assets/build/formEditor.js:110144 -#: assets/build/settings.js:71758 -msgid "Entries Time Period" +#: assets/build/entries.js:172 +#, js-format +msgid "Entry #%s" msgstr "" -#: assets/build/formEditor.js:121002 -#: assets/build/settings.js:78975 -#: assets/build/formEditor.js:110152 -#: assets/build/settings.js:71766 -msgid "Entries older than the days set will be deleted automatically." +#. translators: abbreviation for units +#: assets/build/formEditor.js:172 +#: modules/quick-action-sidebar/components/draggable-block.js:83 +#, js-format +msgid "%s Removed from Quick Action Bar." msgstr "" -#: assets/build/formEditor.js:121142 -#: assets/build/settings.js:79115 -#: assets/build/formEditor.js:110258 -#: assets/build/settings.js:71872 -msgid "Comma separated values are also accepted." +#: assets/build/formEditor.js:172 +#: modules/quick-action-sidebar/components/Modal.js:145 +msgid "Add to Quick Action Bar" msgstr "" -#: assets/build/formEditor.js:121143 -#: assets/build/settings.js:79116 -#: assets/build/formEditor.js:110263 -#: assets/build/settings.js:71877 -msgid "Notifications can use only one From Email so please enter a single address." +#. translators: abbreviation for units +#: assets/build/formEditor.js:172 +#: modules/quick-action-sidebar/components/Modal.js:42 +#, js-format +msgid "%s Added to Quick Action Bar." msgstr "" -#: assets/build/formEditor.js:121192 -#: assets/build/formEditor.js:121194 -#: assets/build/formEditor.js:125631 -#: assets/build/settings.js:79165 -#: assets/build/settings.js:79167 -#: assets/build/formEditor.js:110311 -#: assets/build/formEditor.js:110314 -#: assets/build/formEditor.js:115235 -#: assets/build/settings.js:71925 -#: assets/build/settings.js:71928 -msgid "Name" +#: assets/build/formEditor.js:172 +#: modules/quick-action-sidebar/components/Modal.js:155 +msgid "Already Present in Quick Action Bar" msgstr "" -#: assets/build/formEditor.js:121211 -#: assets/build/formEditor.js:121215 -#: assets/build/settings.js:76912 -#: assets/build/settings.js:79184 -#: assets/build/settings.js:79188 -#: assets/build/formEditor.js:110330 -#: assets/build/formEditor.js:110334 -#: assets/build/settings.js:69285 -#: assets/build/settings.js:71944 -#: assets/build/settings.js:71948 -msgid "Send Email To" +#: assets/build/formEditor.js:172 +#: modules/quick-action-sidebar/components/Modal.js:174 +msgid "No results found." msgstr "" -#: assets/build/formEditor.js:121252 -#: assets/build/formEditor.js:123419 -#: assets/build/settings.js:79225 -#: assets/build/settings.js:79963 -#: assets/build/formEditor.js:110384 -#: assets/build/formEditor.js:112871 -#: assets/build/settings.js:71998 -#: assets/build/settings.js:72792 -msgid "Confirmation Message" +#: assets/build/formEditor.js:172 +#: modules/gutenberg/build/blocks.js:6 +msgid "data object is empty" msgstr "" -#: assets/build/formEditor.js:121279 -#: assets/build/formEditor.js:121283 -#: assets/build/settings.js:79252 -#: assets/build/settings.js:79256 -#: assets/build/formEditor.js:110414 -#: assets/build/formEditor.js:110418 -#: assets/build/settings.js:72028 -#: assets/build/settings.js:72032 -msgid "From Name" +#: assets/build/formEditor.js:172 +#: modules/quick-action-sidebar/components/Sidebar.js:181 +msgid "Add blocks to Quick Action Bar" msgstr "" -#: assets/build/formEditor.js:121292 -#: assets/build/formEditor.js:121500 -#: assets/build/formEditor.js:121507 -#: assets/build/formEditor.js:123408 -#: assets/build/formEditor.js:132174 -#: assets/build/settings.js:79265 -#: assets/build/settings.js:79473 -#: assets/build/settings.js:79480 -#: assets/build/settings.js:79952 -#: assets/build/settings.js:80514 -#: assets/build/formEditor.js:110428 -#: assets/build/formEditor.js:110682 -#: assets/build/formEditor.js:110692 -#: assets/build/formEditor.js:112857 -#: assets/build/formEditor.js:122578 -#: assets/build/settings.js:72042 -#: assets/build/settings.js:72296 -#: assets/build/settings.js:72306 -#: assets/build/settings.js:72778 -#: assets/build/settings.js:73305 -msgid "Form input tags" +#: assets/build/formEditor.js:172 +#: modules/quick-action-sidebar/components/Sidebar.js:231 +msgid "Re-arrange block inside Quick Action Bar" msgstr "" -#: assets/build/formEditor.js:121305 -#: assets/build/formEditor.js:121309 -#: assets/build/settings.js:79278 -#: assets/build/settings.js:79282 -#: assets/build/formEditor.js:110462 -#: assets/build/formEditor.js:110466 -#: assets/build/settings.js:72076 -#: assets/build/settings.js:72080 -msgid "From Email" +#: assets/build/formEditor.js:172 +msgid "OttoKit Settings" msgstr "" -#: assets/build/formEditor.js:121328 -#: assets/build/formEditor.js:121332 -#: assets/build/settings.js:79301 -#: assets/build/settings.js:79305 -#: assets/build/formEditor.js:110493 -#: assets/build/formEditor.js:110497 -#: assets/build/settings.js:72107 -#: assets/build/settings.js:72111 -msgid "CC" +#: assets/build/formEditor.js:172 +msgid "All changes will be saved automatically when you press back." msgstr "" -#: assets/build/formEditor.js:121350 -#: assets/build/formEditor.js:121354 -#: assets/build/settings.js:79323 -#: assets/build/settings.js:79327 -#: assets/build/formEditor.js:110522 -#: assets/build/formEditor.js:110526 -#: assets/build/settings.js:72136 -#: assets/build/settings.js:72140 -msgid "BCC" +#: assets/build/formEditor.js:172 +msgid "Settings saved, but post attributes (password / title / content) failed to update. Retry to persist them." msgstr "" -#: assets/build/formEditor.js:121372 -#: assets/build/formEditor.js:121376 -#: assets/build/settings.js:79345 -#: assets/build/settings.js:79349 -#: assets/build/formEditor.js:110551 -#: assets/build/formEditor.js:110555 -#: assets/build/settings.js:72165 -#: assets/build/settings.js:72169 -msgid "Reply To" +#: assets/build/formEditor.js:172 +msgid "Failed to save form settings." msgstr "" -#: assets/build/formEditor.js:121556 -#: assets/build/settings.js:79529 -#: assets/build/formEditor.js:110716 -#: assets/build/settings.js:72330 -msgid "Hide Form" +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Savingโ€ฆ" msgstr "" -#: assets/build/formEditor.js:121559 -#: assets/build/settings.js:79532 -#: assets/build/formEditor.js:110720 -#: assets/build/settings.js:72334 -msgid "Reset Form" +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Save" msgstr "" -#: assets/build/formEditor.js:121628 -#: assets/build/formEditor.js:121657 -#: assets/build/settings.js:79601 -#: assets/build/settings.js:79630 -#: assets/build/formEditor.js:110780 -#: assets/build/formEditor.js:110822 -#: assets/build/settings.js:72394 -#: assets/build/settings.js:72436 -msgid "Search for a page" +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Enable GDPR Compliance" msgstr "" -#: assets/build/formEditor.js:121631 -#: assets/build/formEditor.js:121660 -#: assets/build/settings.js:79604 -#: assets/build/settings.js:79633 -#: assets/build/formEditor.js:110784 -#: assets/build/formEditor.js:110826 -#: assets/build/settings.js:72398 -#: assets/build/settings.js:72440 -msgid "Select a page" +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "When enabled this form will not store User IP, Browser Name and the Device Name in the Entries." msgstr "" -#: assets/build/formEditor.js:121679 -#: assets/build/settings.js:79652 -#: assets/build/formEditor.js:110865 -#: assets/build/settings.js:72479 -msgid "After Form Submission" +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Never store entry data after form submission" msgstr "" -#: assets/build/formEditor.js:121697 -#: assets/build/settings.js:79670 -#: assets/build/formEditor.js:110898 -#: assets/build/settings.js:72512 -msgid "Select Page to redirect" +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "When enabled this form will never store Entries." msgstr "" -#: assets/build/formEditor.js:121702 -#: assets/build/formEditor.js:126093 -#: assets/build/settings.js:79675 -#: assets/build/settings.js:79728 -#: assets/build/formEditor.js:110914 -#: assets/build/formEditor.js:115753 -#: assets/build/settings.js:72528 -#: assets/build/settings.js:72590 -msgid "Custom URL" +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Automatically delete entries" msgstr "" -#: assets/build/formEditor.js:121774 -#: assets/build/formEditor.js:110964 -msgid "Add Block" +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "When enabled this form will automatically delete entries after a certain period of time." msgstr "" -#: assets/build/formEditor.js:122113 -#: assets/build/formEditor.js:111274 -msgid "Publish Your Form" +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Entries older than the selected days will be deleted." msgstr "" -#: assets/build/formEditor.js:122382 -#: assets/build/formEditor.js:111647 -msgid "Enable Instant Form" +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Entries Time Period" msgstr "" -#: assets/build/formEditor.js:122416 -#: assets/build/formEditor.js:111693 -msgid "Enable This to Instantly Publish the Form" +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Entries older than the days set will be deleted automatically." msgstr "" -#: assets/build/formEditor.js:122417 -#: assets/build/formEditor.js:111703 -msgid "Enable Preview" +#: assets/build/formEditor.js:172 +msgid "Failed to save. Please try again." msgstr "" -#: assets/build/formEditor.js:122425 -#: assets/build/formEditor.js:111714 -msgid "Show Title" +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Compliance Settings" msgstr "" -#: assets/build/formEditor.js:122440 -#: assets/build/formEditor.js:111738 -msgid "Site Logo" +#: assets/build/formEditor.js:172 +msgid "Custom CSS" msgstr "" -#: assets/build/formEditor.js:122455 -#: assets/build/formEditor.js:111764 -msgid "Banner Background" +#: assets/build/formEditor.js:172 +msgid "Add custom CSS rules to style this specific form independently of global styles." msgstr "" -#: assets/build/formEditor.js:122473 -#: assets/build/formEditor.js:111803 -msgid "Upload Image" +#: assets/build/formEditor.js:172 +msgid "The following CSS styles added below will only apply to this form container." msgstr "" -#: assets/build/formEditor.js:122518 -#: assets/build/formEditor.js:111872 -msgid "Style Your Instant Form Page Here" +#: assets/build/formEditor.js:172 +msgid "Custom CSS Panel" msgstr "" -#: assets/build/formEditor.js:122536 -#: assets/build/formEditor.js:111915 -msgid "Use banner as page background" +#: assets/build/formEditor.js:172 +msgid "CloudFlare Turnstile" msgstr "" -#: assets/build/formEditor.js:122544 -#: assets/build/formEditor.js:111933 -msgid "Form Width" +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "reCAPTCHA v2" msgstr "" -#: assets/build/formEditor.js:122561 -#: assets/build/formEditor.js:111957 -msgid "Instant Form Padding" +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "reCAPTCHA v2 Invisible" msgstr "" -#: assets/build/formEditor.js:122590 -#: assets/build/formEditor.js:111992 -msgid "Instant Form Border Radius" +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "reCAPTCHA v3" msgstr "" -#: assets/build/formEditor.js:122652 -#: assets/build/formEditor.js:112073 -msgid "URL Slug" +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Spam Protection" msgstr "" -#: assets/build/formEditor.js:122680 -#: assets/build/formEditor.js:112133 -msgid "The last part of the URL." +#: assets/build/formEditor.js:172 +msgid "reCAPTCHA API keys for the selected version are not configured. Set them in Global Settings." msgstr "" -#: assets/build/formEditor.js:122682 -#: assets/build/formEditor.js:112142 -msgid "Learn more." +#: assets/build/formEditor.js:172 +msgid "Please select a reCAPTCHA version." msgstr "" -#: assets/build/formEditor.js:122844 -#: assets/build/settings.js:74861 -#: assets/build/formEditor.js:112299 -#: assets/build/settings.js:67257 -msgid "Compliance Settings" +#: assets/build/formEditor.js:172 +msgid "hCaptcha API keys are not configured. Set them in Global Settings." msgstr "" -#: assets/build/formEditor.js:122889 -#: assets/build/formEditor.js:112336 -msgid "Conversational Layout" +#: assets/build/formEditor.js:172 +msgid "Cloudflare Turnstile API keys are not configured. Set them in Global Settings." msgstr "" -#: assets/build/formEditor.js:122890 -#: assets/build/templatePicker.js:172 -#: assets/build/formEditor.js:112339 -msgid "Unlock Conversational Forms" +#: assets/build/formEditor.js:172 +msgid "Spam Protection Type" msgstr "" -#: assets/build/formEditor.js:122891 -#: assets/build/formEditor.js:112343 -msgid "With the SureForms Pro Plan, you can transform your forms into engaging conversational layouts for a seamless user experience." +#: assets/build/formEditor.js:172 +msgid "Select Security Type" msgstr "" -#: assets/build/formEditor.js:123174 -#: assets/build/formEditor.js:124607 -#: assets/build/formEditor.js:128816 -#: assets/build/formEditor.js:112633 -#: assets/build/formEditor.js:114205 -#: assets/build/formEditor.js:119038 -msgid "Custom CSS" +#: assets/build/formEditor.js:172 +msgid "Select a spam protection service. Configure API keys in Global Settings before enabling." msgstr "" -#: assets/build/formEditor.js:123176 -#: assets/build/formEditor.js:112635 -msgid "Add custom CSS rules to style this specific form independently of global styles." +#: assets/build/formEditor.js:172 +msgid "Note: Using different reCAPTCHA versions (V2 checkbox and V3) on the same page will create conflicts between the versions. Kindly avoid using different versions on the same page." msgstr "" -#: assets/build/formEditor.js:123191 -#: assets/build/formEditor.js:112653 -msgid "The following CSS styles added below will only apply to this form container." +#: assets/build/formEditor.js:172 +msgid "Select Version" msgstr "" -#: assets/build/formEditor.js:123194 -#: assets/build/formEditor.js:112660 -msgid "Custom CSS Panel" +#: assets/build/formEditor.js:172 +msgid "Please configure the API keys correctly from the settings" msgstr "" -#: assets/build/formEditor.js:123275 -#: assets/build/settings.js:79819 -#: assets/build/formEditor.js:112700 -#: assets/build/settings.js:72621 +#: assets/build/formEditor.js:172 +msgid "Global Settings" +msgstr "" + +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Expected format for emails - email@sureforms.com or John Doe " +msgstr "" + +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 msgid "Visual" msgstr "" -#: assets/build/formEditor.js:123280 -#: assets/build/formEditor.js:126974 -#: assets/build/settings.js:79824 -#: assets/build/formEditor.js:112706 -#: assets/build/formEditor.js:116873 -#: assets/build/settings.js:72627 +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 msgid "HTML" msgstr "" -#: assets/build/formEditor.js:123352 -#: assets/build/formEditor.js:123401 -#: assets/build/settings.js:79896 -#: assets/build/settings.js:79945 -#: assets/build/formEditor.js:112793 -#: assets/build/formEditor.js:112842 -#: assets/build/settings.js:72714 -#: assets/build/settings.js:72763 +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 msgid "All Data" msgstr "" -#: assets/build/formEditor.js:123402 -#: assets/build/settings.js:79946 -#: assets/build/formEditor.js:112845 -#: assets/build/settings.js:72766 +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 msgid "Form data" msgstr "" -#: assets/build/formEditor.js:123442 -#: assets/build/settings.js:79986 -#: assets/build/formEditor.js:112895 -#: assets/build/settings.js:72816 +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Form input tags" +msgstr "" + +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Confirmation Message" +msgstr "" + +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 msgid "Add Shortcode" msgstr "" -#: assets/build/formEditor.js:123834 -#: assets/build/formEditor.js:113202 -msgid "Cloudflare Turnstile API keys are not configured. Set them in Global Settings." +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +#, js-format +msgid "The current 'From Email' address may not match your website domain name (%1$s). This can cause your notification emails to be blocked or marked as spam. Alternately, try using a From Address that matches your website domain (admin@%2$s)." msgstr "" -#: assets/build/formEditor.js:123836 -#: assets/build/formEditor.js:113207 -msgid "hCaptcha API keys are not configured. Set them in Global Settings." +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +#, js-format +msgid "The current 'From Email' address does not match your website domain name (%1$s). This can cause your notification emails to be blocked or marked as spam. Alternately, try using a From Address that matches your website domain (admin@%2$s)." msgstr "" -#: assets/build/formEditor.js:123845 -#: assets/build/formEditor.js:113219 -msgid "Please select a reCAPTCHA version." +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Please enter a valid email address. Your notifications won't be sent if the field is not filled in correctly." msgstr "" -#: assets/build/formEditor.js:123847 -#: assets/build/formEditor.js:113224 -msgid "reCAPTCHA API keys for the selected version are not configured. Set them in Global Settings." +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +#, js-format +msgid "The current 'From Email' address may not match your website domain name (%s). This can cause your notification emails to be blocked or marked as spam. " msgstr "" -#: assets/build/formEditor.js:123887 -#: assets/build/formEditor.js:113273 -msgid "CloudFlare Turnstile" +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +#, js-format +msgid "The current 'From Email' address does not match your website domain name (%s). This can cause your notification emails to be blocked or marked as spam. " msgstr "" -#: assets/build/formEditor.js:123894 -#: assets/build/settings.js:75333 -#: assets/build/formEditor.js:113279 -#: assets/build/settings.js:67796 -msgid "reCAPTCHA v2" +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +#, js-format +msgid " Alternately, try using a From Address that matches your website domain (admin@%s)." +msgstr "" + +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "We strongly recommend that you install the free " +msgstr "" + +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid " plugin! The Setup Wizard makes it easy to fix your emails. " +msgstr "" + +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Comma separated values are also accepted." +msgstr "" + +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Notifications can use only one From Email so please enter a single address." msgstr "" -#: assets/build/formEditor.js:123897 -#: assets/build/settings.js:75338 -#: assets/build/formEditor.js:113282 -#: assets/build/settings.js:67802 -msgid "reCAPTCHA v2 Invisible" +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Name" msgstr "" -#: assets/build/formEditor.js:123900 -#: assets/build/settings.js:75343 -#: assets/build/formEditor.js:113284 -#: assets/build/settings.js:67808 -msgid "reCAPTCHA v3" +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Send Email To" msgstr "" -#: assets/build/formEditor.js:123903 -#: assets/build/formEditor.js:124474 -#: assets/build/formEditor.js:128767 -#: assets/build/settings.js:74871 -#: assets/build/formEditor.js:113289 -#: assets/build/formEditor.js:113909 -#: assets/build/formEditor.js:118993 -#: assets/build/settings.js:67276 -msgid "Spam Protection" +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "From Name" msgstr "" -#: assets/build/formEditor.js:123919 -#: assets/build/formEditor.js:113303 -msgid "Spam Protection Type" +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "From Email" msgstr "" -#: assets/build/formEditor.js:123925 -#: assets/build/formEditor.js:113312 -msgid "Select Security Type" +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "CC" msgstr "" -#: assets/build/formEditor.js:123938 -#: assets/build/formEditor.js:113340 -msgid "Select a spam protection service. Configure API keys in Global Settings before enabling." +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "BCC" msgstr "" -#: assets/build/formEditor.js:123944 -#: assets/build/formEditor.js:113356 -msgid "Note: Using different reCAPTCHA versions (V2 checkbox and V3) on the same page will create conflicts between the versions. Kindly avoid using different versions on the same page." +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Reply To" msgstr "" -#: assets/build/formEditor.js:123946 -#: assets/build/formEditor.js:113365 -msgid "Select Version" +#: assets/build/formEditor.js:172 +msgid "Send as Raw HTML" msgstr "" -#: assets/build/formEditor.js:123966 -#: assets/build/formEditor.js:113395 -msgid "Please configure the API keys correctly from the settings" +#: assets/build/formEditor.js:172 +msgid "When enabled, the email body HTML will be preserved exactly as written and wrapped in a professional email template." msgstr "" -#: assets/build/formEditor.js:123971 -#: assets/build/formEditor.js:113407 -msgid "Global Settings" +#: assets/build/formEditor.js:172 +msgid "Smart tags that reference user-submitted fields will not be escaped in raw HTML mode. Avoid inserting untrusted field values directly into the email body." msgstr "" -#: assets/build/formEditor.js:124037 -#: assets/build/formEditor.js:113469 -msgid "Customize with SureForms" +#: assets/build/formEditor.js:172 +msgid "Some fields need attention" msgstr "" -#: assets/build/formEditor.js:124074 -#: assets/build/formEditor.js:113492 -msgid "Unlock Advanced Styling" +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Unsaved changes" msgstr "" -#: assets/build/formEditor.js:124076 -#: assets/build/formEditor.js:113495 -msgid "Get full control over your form's look with custom colors, fonts, and layouts." +#: assets/build/formEditor.js:172 +msgid "A recipient email address and subject line are required before this notification can be saved. Fix the highlighted fields, or discard your changes to go back." msgstr "" -#: assets/build/formEditor.js:124441 -#: assets/build/formEditor.js:127483 -#: assets/build/formEditor.js:128749 -#: assets/build/settings.js:74852 -#: assets/build/formEditor.js:113844 -#: assets/build/formEditor.js:117417 -#: assets/build/formEditor.js:118978 -#: assets/build/settings.js:67245 -msgid "Email Notification" +#: assets/build/formEditor.js:172 +msgid "You have unsaved changes for this notification. Discard them to go back, or stay to save them." msgstr "" -#: assets/build/formEditor.js:124449 -#: assets/build/formEditor.js:126137 -#: assets/build/formEditor.js:127480 -#: assets/build/formEditor.js:128755 -#: assets/build/settings.js:74855 -#: assets/build/formEditor.js:113854 -#: assets/build/formEditor.js:115806 -#: assets/build/formEditor.js:117413 -#: assets/build/formEditor.js:118983 -#: assets/build/settings.js:67249 -msgid "Form Confirmation" +#: assets/build/formEditor.js:172 +msgid "Discard & go back" msgstr "" -#: assets/build/formEditor.js:124457 -#: assets/build/formEditor.js:124460 -#: assets/build/formEditor.js:124467 -#: assets/build/formEditor.js:128761 -#: assets/build/formEditor.js:113865 -#: assets/build/formEditor.js:113869 -#: assets/build/formEditor.js:113884 -#: assets/build/formEditor.js:118988 -msgid "Conditional Confirmations" +#: assets/build/formEditor.js:172 +msgid "Stay & fix" msgstr "" -#: assets/build/formEditor.js:124461 -#: assets/build/formEditor.js:113873 -msgid "Set up the message or redirect users will see after submitting the form." +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Keep editing" msgstr "" -#: assets/build/formEditor.js:124468 -#: assets/build/formEditor.js:113885 -msgid "Show the right message to the right user based on how they respond. Personalize confirmations with smart conditions and guide users to the next best step automatically." +#: assets/build/formEditor.js:172 +msgid "Please provide a recipient email address and subject line." msgstr "" -#: assets/build/formEditor.js:124469 -#: assets/build/formEditor.js:113890 -msgid "Display different confirmation messages based on form responses." +#: assets/build/formEditor.js:172 +msgid "Please provide a recipient email address." msgstr "" -#: assets/build/formEditor.js:124469 -#: assets/build/formEditor.js:113894 -msgid "Redirect users to specific pages or URLs conditionally." +#: assets/build/formEditor.js:172 +msgid "Please provide a subject line." msgstr "" -#: assets/build/formEditor.js:124469 -#: assets/build/formEditor.js:113898 -msgid "Create personalized thank-you messages without extra forms." +#: assets/build/formEditor.js:172 +msgid "Add Notification" msgstr "" -#: assets/build/formEditor.js:124479 -#: assets/build/formEditor.js:124482 -#: assets/build/formEditor.js:128773 -#: assets/build/settings.js:74898 -#: assets/build/formEditor.js:113915 -#: assets/build/formEditor.js:113919 -#: assets/build/formEditor.js:118998 -#: assets/build/settings.js:67315 -msgid "Integrations" +#: assets/build/formEditor.js:172 +msgid "Control email alerts sent to admins or users after a form submission." msgstr "" -#: assets/build/formEditor.js:124483 -#: assets/build/formEditor.js:113920 -msgid "Connect SureForms with your favorite apps to automate tasks and sync data seamlessly." +#: assets/build/formEditor.js:172 +#: assets/build/forms.js:172 +msgid "Duplicate" msgstr "" -#: assets/build/formEditor.js:124489 -#: assets/build/settings.js:77669 -#: assets/build/formEditor.js:113931 -#: assets/build/settings.js:70198 -msgid "Connect Native Integrations with SureForms" +#: assets/build/formEditor.js:172 +msgid "Email notification duplicated!" msgstr "" -#: assets/build/formEditor.js:124490 -#: assets/build/formEditor.js:113935 -msgid "Unlock powerful integrations in the Premimum plan to automate your workflows and connect SureForms directly with your favorite tools." +#: assets/build/formEditor.js:172 +msgid "Are you sure you want to delete this email notification?" msgstr "" -#: assets/build/formEditor.js:124491 -#: assets/build/formEditor.js:113940 -msgid "Send form submissions straight to CRMs, email, and marketing platforms." +#: assets/build/formEditor.js:172 +msgid "Email notification deleted!" msgstr "" -#: assets/build/formEditor.js:124491 -#: assets/build/formEditor.js:113944 -msgid "Automate repetitive tasks with seamless data syncing." +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Add Key" msgstr "" -#: assets/build/formEditor.js:124491 -#: assets/build/formEditor.js:113948 -msgid "Access exclusive native integrations for faster workflows." +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Add Value" msgstr "" -#: assets/build/formEditor.js:124496 -#: assets/build/formEditor.js:128779 -#: assets/build/formEditor.js:113959 -#: assets/build/formEditor.js:119003 -msgid "Automations" +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Add" msgstr "" -#: assets/build/formEditor.js:124511 -#: assets/build/formEditor.js:124514 -#: assets/build/formEditor.js:128786 -#: assets/build/formEditor.js:113981 -#: assets/build/formEditor.js:113985 -#: assets/build/formEditor.js:119013 -msgid "PDF Generation" +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Hide Form" msgstr "" -#: assets/build/formEditor.js:124515 -#: assets/build/formEditor.js:113986 -msgid "Generate and customize PDF copies of form submissions." +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Reset Form" msgstr "" -#: assets/build/formEditor.js:124521 -#: assets/build/formEditor.js:113997 -msgid "Generate Submission PDFs" +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "After Form Submission" msgstr "" -#: assets/build/formEditor.js:124522 -#: assets/build/formEditor.js:113998 -msgid "Turn every form entry into a polished PDF file, making it perfect for reports, records, or sharing." +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Select Page to redirect" msgstr "" -#: assets/build/formEditor.js:124523 -#: assets/build/formEditor.js:114003 -msgid "Automatically generate PDFs from your form submissions." +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Search for a page" msgstr "" -#: assets/build/formEditor.js:124523 -#: assets/build/formEditor.js:114007 -msgid "Customize PDF templates with your branding." +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Select a page" msgstr "" -#: assets/build/formEditor.js:124523 -#: assets/build/formEditor.js:114011 -msgid "Download or email PDFs instantly." +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Custom URL" msgstr "" -#: assets/build/formEditor.js:124528 -#: assets/build/formEditor.js:124531 -#: assets/build/formEditor.js:128792 -#: assets/build/formEditor.js:114022 -#: assets/build/formEditor.js:114026 -#: assets/build/formEditor.js:119018 -msgid "Save & Progress" +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Add Query Parameters" msgstr "" -#: assets/build/formEditor.js:124532 -#: assets/build/formEditor.js:114027 -msgid "Allow users to save their progress and continue form completion later." +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Select if you want to add key-value pairs for form fields to include in query parameters" msgstr "" -#: assets/build/formEditor.js:124538 -#: assets/build/formEditor.js:114038 -msgid "Save & Progress in SureForms" +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Query Parameters" msgstr "" -#: assets/build/formEditor.js:124539 -#: assets/build/formEditor.js:114042 -msgid "Give your users the flexibility to complete forms at their own pace by allowing them to save progress and return anytime." +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Success Message" msgstr "" -#: assets/build/formEditor.js:124540 -#: assets/build/formEditor.js:114047 -msgid "Let users pause long or multi-step forms and continue later." +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Redirect" msgstr "" -#: assets/build/formEditor.js:124540 -#: assets/build/formEditor.js:114051 -msgid "Reduce form abandonment with convenient resume links and access their progress from anywhere." +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Redirect to" msgstr "" -#: assets/build/formEditor.js:124540 -#: assets/build/formEditor.js:114055 -msgid "Improve user experience for lengthy, complex, or multi-page forms." +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Form Confirmation" msgstr "" -#: assets/build/formEditor.js:124545 -#: assets/build/formEditor.js:124548 -#: assets/build/formEditor.js:128798 -#: assets/build/formEditor.js:114066 -#: assets/build/formEditor.js:114070 -#: assets/build/formEditor.js:119023 -msgid "User Registration" +#: assets/build/formEditor.js:172 +msgid "Customize the confirmation message or redirect the users after submitting the form." msgstr "" -#: assets/build/formEditor.js:124549 -#: assets/build/formEditor.js:114071 -msgid "Onboard new users or update existing accounts through beautiful looking forms." +#: assets/build/formEditor.js:172 +msgid "Please select a page." msgstr "" -#: assets/build/formEditor.js:124555 -#: assets/build/formEditor.js:114082 -msgid "Register Users with SureForms" +#: assets/build/formEditor.js:172 +msgid "Suggestion: URL should use HTTPS" msgstr "" -#: assets/build/formEditor.js:124556 -#: assets/build/formEditor.js:114086 -msgid "Streamline the entire user onboarding process for your sites with seamless form-powered logins and registrations." +#: assets/build/formEditor.js:172 +msgid "URL is missing Top Level Domain (TLD)." msgstr "" -#: assets/build/formEditor.js:124557 -#: assets/build/formEditor.js:114091 -msgid "Register new users directly via your form submissions." +#: assets/build/formEditor.js:172 +msgid "Please enter a valid URL." msgstr "" -#: assets/build/formEditor.js:124557 -#: assets/build/formEditor.js:114095 -msgid "Create or update existing accounts by mapping form data to user fields." +#: assets/build/formEditor.js:172 +msgid "Please provide a custom URL." msgstr "" -#: assets/build/formEditor.js:124557 -#: assets/build/formEditor.js:114099 -msgid "Assign roles and control access automatically." +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Confirmation Type" msgstr "" -#: assets/build/formEditor.js:124562 -#: assets/build/formEditor.js:124565 -#: assets/build/formEditor.js:124572 -#: assets/build/formEditor.js:128804 -#: assets/build/formEditor.js:114110 -#: assets/build/formEditor.js:114114 -#: assets/build/formEditor.js:114126 -#: assets/build/formEditor.js:119028 -msgid "Post Feed" +#: assets/build/formEditor.js:172 +msgid "The start date and time must be before the end date and time." msgstr "" -#: assets/build/formEditor.js:124566 -#: assets/build/formEditor.js:114115 -msgid "Transform your form submission into WordPress posts." +#: assets/build/formEditor.js:172 +msgid "Advanced Settings" msgstr "" -#: assets/build/formEditor.js:124573 -#: assets/build/formEditor.js:114127 -msgid "Automatically turn form submissions into WordPress posts, pages, or custom post types. Save big on time and let your forms publish content directly." +#: assets/build/formEditor.js:172 +msgid "Set limits on how many times a form can be submitted and manage compliance options, including GDPR and data retention." msgstr "" -#: assets/build/formEditor.js:124574 -#: assets/build/formEditor.js:114132 -msgid "Create posts, pages, or CPTs from your form entries." +#: assets/build/formEditor.js:172 +msgid "Form Restriction" msgstr "" -#: assets/build/formEditor.js:124574 -#: assets/build/formEditor.js:114136 -msgid "Map form fields to your post fields easily." +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Maximum Number of Entries" msgstr "" -#: assets/build/formEditor.js:124574 -#: assets/build/formEditor.js:114140 -msgid "Automate the content publishing flow with few simple steps." +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Set the total number of submissions allowed for this form." msgstr "" -#: assets/build/formEditor.js:124579 -#: assets/build/formEditor.js:126466 -#: assets/build/formEditor.js:127486 -#: assets/build/formEditor.js:128810 -#: assets/build/formEditor.js:114151 -#: assets/build/formEditor.js:116180 -#: assets/build/formEditor.js:117421 -#: assets/build/formEditor.js:119033 -msgid "Advanced Settings" +#: assets/build/formEditor.js:172 +msgid "The entry cap relies on stored entries to count submissions. While Compliance Settings has \"Never store entry data after form submission\" enabled, this limit will not be enforced. Disable that option, or remove the entry limit, to use this feature." msgstr "" -#: assets/build/formEditor.js:124594 -#: assets/build/formEditor.js:114169 -msgid "Create interactive quizzes to engage your audience and gather insights." +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Maximum Entries" msgstr "" -#: assets/build/formEditor.js:124601 -#: assets/build/formEditor.js:114181 -msgid "Design engaging quizzes with various question types, personalized feedback, and automated scoring to captivate your audience and gain valuable insights." +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Response Description After Maximum Entries" msgstr "" -#: assets/build/formEditor.js:124602 -#: assets/build/formEditor.js:114186 -msgid "Create interactive quizzes with multiple question types." +#: assets/build/formEditor.js:172 +msgid "This form is now closed as the maximum number of entries has been received." msgstr "" -#: assets/build/formEditor.js:124602 -#: assets/build/formEditor.js:114190 -msgid "Provide personalized feedback based on user responses." +#: assets/build/formEditor.js:172 +msgid "Form Scheduling" msgstr "" -#: assets/build/formEditor.js:124602 -#: assets/build/formEditor.js:114194 -msgid "Automate scoring and lead segmentation for better insights." +#: assets/build/formEditor.js:172 +msgid "Enable Form Scheduling" msgstr "" -#: assets/build/formEditor.js:124615 -#: assets/build/formEditor.js:114212 -msgid "SureTriggers" +#: assets/build/formEditor.js:172 +msgid "Set a time period during which this form will be available for submissions." msgstr "" -#: assets/build/formEditor.js:124673 -#: assets/build/formEditor.js:114289 -msgid "Form Behavior" +#: assets/build/formEditor.js:172 +msgid "Start Date & Time" msgstr "" -#: assets/build/formEditor.js:124697 -#: assets/build/formEditor.js:125280 -#: assets/build/settings.js:75142 -#: assets/build/formEditor.js:114322 -#: assets/build/formEditor.js:114867 -#: assets/build/settings.js:67620 -msgid "Unsaved changes" +#: assets/build/formEditor.js:172 +msgid "The Time Period setting works according to your WordPress site's time zone. Click here to open your WordPress General Settings, where you can check and update it." msgstr "" -#: assets/build/formEditor.js:124698 -#: assets/build/formEditor.js:114323 -msgid "You have unsaved changes. Discard them to continue, or stay to save your changes." +#: assets/build/formEditor.js:172 +msgid "Click here" msgstr "" -#: assets/build/formEditor.js:124699 -#: assets/build/formEditor.js:114327 -msgid "Discard & continue" +#: assets/build/formEditor.js:172 +msgid "End Date & Time" msgstr "" -#: assets/build/formEditor.js:124700 -#: assets/build/formEditor.js:124709 -#: assets/build/formEditor.js:125283 -#: assets/build/settings.js:75145 -#: assets/build/formEditor.js:114331 -#: assets/build/formEditor.js:114354 -#: assets/build/formEditor.js:114882 -#: assets/build/settings.js:67626 -msgid "Keep editing" +#: assets/build/formEditor.js:172 +msgid "Response Description Before Start Date" msgstr "" -#: assets/build/formEditor.js:124708 -#: assets/build/formEditor.js:125282 -#: assets/build/formEditor.js:114350 -#: assets/build/formEditor.js:114878 -msgid "Discard & go back" +#: assets/build/formEditor.js:172 +msgid "Response Description After End Date" msgstr "" -#: assets/build/formEditor.js:125280 -#: assets/build/formEditor.js:114866 -msgid "Some fields need attention" +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Send entries to 100+ popular apps." msgstr "" -#: assets/build/formEditor.js:125281 -#: assets/build/formEditor.js:114870 -msgid "A recipient email address and subject line are required before this notification can be saved. Fix the highlighted fields, or discard your changes to go back." +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Build automated workflows that run instantly." msgstr "" -#: assets/build/formEditor.js:125281 -#: assets/build/formEditor.js:114874 -msgid "You have unsaved changes for this notification. Discard them to go back, or stay to save them." +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Create custom app integrations using our Custom App feature." msgstr "" -#: assets/build/formEditor.js:125283 -#: assets/build/formEditor.js:114881 -msgid "Stay & fix" +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Keep your tools in sync automatically." msgstr "" -#: assets/build/formEditor.js:125300 -#: assets/build/formEditor.js:125578 -#: assets/build/formEditor.js:114898 -#: assets/build/formEditor.js:115173 -msgid "Please provide a recipient email address and subject line." +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Connectingโ€ฆ" msgstr "" -#: assets/build/formEditor.js:125303 -#: assets/build/formEditor.js:125580 -#: assets/build/formEditor.js:114904 -#: assets/build/formEditor.js:115178 -msgid "Please provide a recipient email address." +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Get Started" msgstr "" -#: assets/build/formEditor.js:125305 -#: assets/build/formEditor.js:125582 -#: assets/build/formEditor.js:114909 -#: assets/build/formEditor.js:115183 -msgid "Please provide a subject line." +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Connect with OttoKit" msgstr "" -#: assets/build/formEditor.js:125338 -#: assets/build/formEditor.js:114943 -msgid "Send as Raw HTML" +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Go to OttoKit Settings" msgstr "" -#: assets/build/formEditor.js:125339 -#: assets/build/formEditor.js:114947 -msgid "When enabled, the email body HTML will be preserved exactly as written and wrapped in a professional email template." +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "This will install and activate OttoKit on your WordPress site to enable automation features." msgstr "" -#: assets/build/formEditor.js:125350 -#: assets/build/formEditor.js:114962 -msgid "Smart tags that reference user-submitted fields will not be escaped in raw HTML mode. Avoid inserting untrusted field values directly into the email body." +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Automate Your Forms with OttoKit" msgstr "" -#: assets/build/formEditor.js:125529 -#: assets/build/formEditor.js:115119 -msgid "Email notification deleted!" +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Every form submission should trigger something โ€” a Slack alert, a CRM lead, a follow-up email, or a new row in Google Sheets." msgstr "" -#: assets/build/formEditor.js:125541 -#: assets/build/formEditor.js:115133 -msgid "Email notification duplicated!" +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Email Notification" msgstr "" -#: assets/build/formEditor.js:125668 -#: assets/build/formEditor.js:115285 -msgid "Add Notification" +#: assets/build/formEditor.js:172 +msgid "Conditional Confirmations" msgstr "" -#: assets/build/formEditor.js:125672 -#: assets/build/formEditor.js:115289 -msgid "Control email alerts sent to admins or users after a form submission." +#: assets/build/formEditor.js:172 +msgid "Set up the message or redirect users will see after submitting the form." msgstr "" -#: assets/build/formEditor.js:125713 -#: assets/build/formEditor.js:125715 -#: assets/build/forms.js:63735 -#: assets/build/forms.js:64866 -#: assets/build/formEditor.js:115348 -#: assets/build/formEditor.js:115354 -#: assets/build/forms.js:54821 -#: assets/build/forms.js:55858 -msgid "Duplicate" +#: assets/build/formEditor.js:172 +msgid "Show the right message to the right user based on how they respond. Personalize confirmations with smart conditions and guide users to the next best step automatically." msgstr "" -#: assets/build/formEditor.js:125746 -#: assets/build/formEditor.js:115405 -msgid "Are you sure you want to delete this email notification?" +#: assets/build/formEditor.js:172 +msgid "Display different confirmation messages based on form responses." msgstr "" -#: assets/build/formEditor.js:126007 -#: assets/build/settings.js:77472 -#: assets/build/formEditor.js:115636 -#: assets/build/settings.js:69926 -msgid "Add Query Parameters" +#: assets/build/formEditor.js:172 +msgid "Redirect users to specific pages or URLs conditionally." msgstr "" -#: assets/build/formEditor.js:126008 -#: assets/build/settings.js:77473 -#: assets/build/formEditor.js:115637 -#: assets/build/settings.js:69927 -msgid "Select if you want to add key-value pairs for form fields to include in query parameters" +#: assets/build/formEditor.js:172 +msgid "Create personalized thank-you messages without extra forms." msgstr "" -#: assets/build/formEditor.js:126010 -#: assets/build/settings.js:77475 -#: assets/build/formEditor.js:115642 -#: assets/build/settings.js:69932 -msgid "Query Parameters" +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Integrations" msgstr "" -#: assets/build/formEditor.js:126017 -#: assets/build/formEditor.js:115654 -msgid "Please select a page." +#: assets/build/formEditor.js:172 +msgid "Connect SureForms with your favorite apps to automate tasks and sync data seamlessly." msgstr "" -#: assets/build/formEditor.js:126021 -#: assets/build/formEditor.js:115658 -msgid "Please provide a custom URL." +#: assets/build/formEditor.js:172 +#: assets/build/settings.js:172 +msgid "Connect Native Integrations with SureForms" msgstr "" -#: assets/build/formEditor.js:126026 -#: assets/build/formEditor.js:115666 -msgid "Suggestion: URL should use HTTPS" +#: assets/build/formEditor.js:172 +msgid "Unlock powerful integrations in the Premimum plan to automate your workflows and connect SureForms directly with your favorite tools." msgstr "" -#: assets/build/formEditor.js:126028 -#: assets/build/formEditor.js:115677 -msgid "URL is missing Top Level Domain (TLD)." +#: assets/build/formEditor.js:172 +msgid "Send form submissions straight to CRMs, email, and marketing platforms." msgstr "" -#: assets/build/formEditor.js:126033 -#: assets/build/formEditor.js:115685 -msgid "Please enter a valid URL." +#: assets/build/formEditor.js:172 +msgid "Automate repetitive tasks with seamless data syncing." msgstr "" -#: assets/build/formEditor.js:126074 -#: assets/build/settings.js:79713 -#: assets/build/formEditor.js:115729 -#: assets/build/settings.js:72571 -msgid "Success Message" +#: assets/build/formEditor.js:172 +msgid "Access exclusive native integrations for faster workflows." msgstr "" -#: assets/build/formEditor.js:126086 -#: assets/build/settings.js:79716 -#: assets/build/formEditor.js:115744 -#: assets/build/settings.js:72575 -msgid "Redirect" +#: assets/build/formEditor.js:172 +msgid "Automations" msgstr "" -#: assets/build/formEditor.js:126088 -#: assets/build/settings.js:77565 -#: assets/build/formEditor.js:115746 -#: assets/build/settings.js:70071 -msgid "Redirect to" +#: assets/build/formEditor.js:172 +msgid "PDF Generation" msgstr "" -#: assets/build/formEditor.js:126138 -#: assets/build/formEditor.js:115807 -msgid "Customize the confirmation message or redirect the users after submitting the form." +#: assets/build/formEditor.js:172 +msgid "Generate and customize PDF copies of form submissions." msgstr "" -#: assets/build/formEditor.js:126151 -#: assets/build/settings.js:77552 -#: assets/build/formEditor.js:115822 -#: assets/build/settings.js:70040 -msgid "Confirmation Type" +#: assets/build/formEditor.js:172 +msgid "Generate Submission PDFs" msgstr "" -#: assets/build/formEditor.js:126398 -#: assets/build/formEditor.js:116082 -msgid "The start date and time must be before the end date and time." +#: assets/build/formEditor.js:172 +msgid "Turn every form entry into a polished PDF file, making it perfect for reports, records, or sharing." msgstr "" -#: assets/build/formEditor.js:126468 -#: assets/build/formEditor.js:116182 -msgid "Set limits on how many times a form can be submitted and manage compliance options, including GDPR and data retention." +#: assets/build/formEditor.js:172 +msgid "Automatically generate PDFs from your form submissions." msgstr "" -#: assets/build/formEditor.js:126491 -#: assets/build/formEditor.js:116207 -msgid "Form Restriction" +#: assets/build/formEditor.js:172 +msgid "Customize PDF templates with your branding." msgstr "" -#: assets/build/formEditor.js:126498 -#: assets/build/settings.js:77299 -#: assets/build/formEditor.js:116214 -#: assets/build/settings.js:69697 -msgid "Maximum Number of Entries" +#: assets/build/formEditor.js:172 +msgid "Download or email PDFs instantly." msgstr "" -#: assets/build/formEditor.js:126499 -#: assets/build/settings.js:77300 -#: assets/build/formEditor.js:116218 -#: assets/build/settings.js:69698 -msgid "Set the total number of submissions allowed for this form." +#: assets/build/formEditor.js:172 +msgid "Save & Progress" msgstr "" -#: assets/build/formEditor.js:126514 -#: assets/build/formEditor.js:116240 -msgid "The entry cap relies on stored entries to count submissions. While Compliance Settings has \"Never store entry data after form submission\" enabled, this limit will not be enforced. Disable that option, or remove the entry limit, to use this feature." +#: assets/build/formEditor.js:172 +msgid "Allow users to save their progress and continue form completion later." msgstr "" -#: assets/build/formEditor.js:126523 -#: assets/build/settings.js:77314 -#: assets/build/formEditor.js:116256 -#: assets/build/settings.js:69721 -msgid "Maximum Entries" +#: assets/build/formEditor.js:172 +msgid "Save & Progress in SureForms" msgstr "" -#: assets/build/formEditor.js:126533 -#: assets/build/settings.js:77321 -#: assets/build/formEditor.js:116309 -#: assets/build/settings.js:69739 -msgid "Response Description After Maximum Entries" +#: assets/build/formEditor.js:172 +msgid "Give your users the flexibility to complete forms at their own pace by allowing them to save progress and return anytime." msgstr "" -#: assets/build/formEditor.js:126536 -#: assets/build/formEditor.js:116319 -msgid "This form is now closed as the maximum number of entries has been received." +#: assets/build/formEditor.js:172 +msgid "Let users pause long or multi-step forms and continue later." msgstr "" -#: assets/build/formEditor.js:126561 -#: assets/build/formEditor.js:116370 -msgid "Form Scheduling" +#: assets/build/formEditor.js:172 +msgid "Reduce form abandonment with convenient resume links and access their progress from anywhere." msgstr "" -#: assets/build/formEditor.js:126568 -#: assets/build/formEditor.js:116377 -msgid "Enable Form Scheduling" +#: assets/build/formEditor.js:172 +msgid "Improve user experience for lengthy, complex, or multi-page forms." msgstr "" -#: assets/build/formEditor.js:126569 -#: assets/build/formEditor.js:116381 -msgid "Set a time period during which this form will be available for submissions." +#: assets/build/formEditor.js:172 +msgid "User Registration" msgstr "" -#: assets/build/formEditor.js:126591 -#: assets/build/formEditor.js:116413 -msgid "Start Date & Time" +#: assets/build/formEditor.js:172 +msgid "Onboard new users or update existing accounts through beautiful looking forms." msgstr "" -#: assets/build/formEditor.js:126595 -#: assets/build/formEditor.js:126639 -#: assets/build/formEditor.js:116424 -#: assets/build/formEditor.js:116528 -msgid "The Time Period setting works according to your WordPress site's time zone. Click here to open your WordPress General Settings, where you can check and update it." +#: assets/build/formEditor.js:172 +msgid "Register Users with SureForms" msgstr "" -#: assets/build/formEditor.js:126601 -#: assets/build/formEditor.js:126645 -#: assets/build/formEditor.js:116439 -#: assets/build/formEditor.js:116543 -msgid "Click here" +#: assets/build/formEditor.js:172 +msgid "Streamline the entire user onboarding process for your sites with seamless form-powered logins and registrations." msgstr "" -#: assets/build/formEditor.js:126635 -#: assets/build/formEditor.js:116517 -msgid "End Date & Time" +#: assets/build/formEditor.js:172 +msgid "Register new users directly via your form submissions." msgstr "" -#: assets/build/formEditor.js:126666 -#: assets/build/formEditor.js:116593 -msgid "Response Description Before Start Date" +#: assets/build/formEditor.js:172 +msgid "Create or update existing accounts by mapping form data to user fields." msgstr "" -#: assets/build/formEditor.js:126675 -#: assets/build/formEditor.js:116619 -msgid "Response Description After End Date" +#: assets/build/formEditor.js:172 +msgid "Assign roles and control access automatically." msgstr "" -#: assets/build/formEditor.js:126848 -#: assets/build/formEditor.js:116772 -msgid "OttoKit Settings" +#: assets/build/formEditor.js:172 +msgid "Post Feed" msgstr "" -#: assets/build/formEditor.js:126932 -#: assets/build/formEditor.js:116845 -msgid "Date Picker" +#: assets/build/formEditor.js:172 +msgid "Transform your form submission into WordPress posts." msgstr "" -#: assets/build/formEditor.js:126938 -#: assets/build/formEditor.js:116849 -msgid "Time Picker" +#: assets/build/formEditor.js:172 +msgid "Automatically turn form submissions into WordPress posts, pages, or custom post types. Save big on time and let your forms publish content directly." msgstr "" -#: assets/build/formEditor.js:126944 -#: assets/build/formEditor.js:116853 -msgid "Hidden" +#: assets/build/formEditor.js:172 +msgid "Create posts, pages, or CPTs from your form entries." msgstr "" -#: assets/build/formEditor.js:126950 -#: assets/build/formEditor.js:116857 -msgid "Slider" +#: assets/build/formEditor.js:172 +msgid "Map form fields to your post fields easily." msgstr "" -#: assets/build/formEditor.js:126956 -#: assets/build/formEditor.js:127561 -#: assets/build/formEditor.js:116861 -#: assets/build/formEditor.js:117520 -msgid "Page Break" +#: assets/build/formEditor.js:172 +msgid "Automate the content publishing flow with few simple steps." msgstr "" -#: assets/build/formEditor.js:126962 -#: assets/build/formEditor.js:116865 -msgid "Rating" +#: assets/build/formEditor.js:172 +msgid "Create interactive quizzes to engage your audience and gather insights." msgstr "" -#: assets/build/formEditor.js:126994 -#: assets/build/formEditor.js:116889 -msgid "Login" +#: assets/build/formEditor.js:172 +msgid "Design engaging quizzes with various question types, personalized feedback, and automated scoring to captivate your audience and gain valuable insights." msgstr "" -#: assets/build/formEditor.js:127004 -#: assets/build/formEditor.js:116900 -msgid "Register" +#: assets/build/formEditor.js:172 +msgid "Create interactive quizzes with multiple question types." msgstr "" -#: assets/build/formEditor.js:127014 -#: assets/build/formEditor.js:116911 -msgid "Lost Password" +#: assets/build/formEditor.js:172 +msgid "Provide personalized feedback based on user responses." msgstr "" -#: assets/build/formEditor.js:127018 -#: assets/build/formEditor.js:116916 -msgid "Reset Password" +#: assets/build/formEditor.js:172 +msgid "Automate scoring and lead segmentation for better insights." msgstr "" -#: assets/build/formEditor.js:127074 -#: assets/build/formEditor.js:116982 -msgid "SUREFORMS PREMIUM FIELDS" +#: assets/build/formEditor.js:172 +msgid "SureTriggers" msgstr "" -#: assets/build/formEditor.js:127083 -#: assets/build/formEditor.js:116999 -msgid "Upgrade to Unlock These Fields" +#: assets/build/formEditor.js:172 +msgid "Form Behavior" msgstr "" -#: assets/build/formEditor.js:127392 -#: assets/build/formEditor.js:117286 -msgid "Are you sure you want to close? Your unsaved changes will be lost as you have some validation errors." +#: assets/build/formEditor.js:172 +msgid "You have unsaved changes. Discard them to continue, or stay to save your changes." msgstr "" -#: assets/build/formEditor.js:127397 -#: assets/build/formEditor.js:117300 -msgid "There are few unsaved changes. Please save your changes to reflect the updates." +#: assets/build/formEditor.js:172 +msgid "Discard & continue" msgstr "" -#: assets/build/formEditor.js:127553 -#: assets/build/formEditor.js:117505 +#: assets/build/formEditor.js:172 msgid "Use Labels as Placeholders" msgstr "" -#: assets/build/formEditor.js:127560 -#: assets/build/formEditor.js:117512 +#: assets/build/formEditor.js:172 msgid "Above setting will place the labels inside the fields as placeholders (where possible). This setting takes effect only on the live page, not in the editor preview." msgstr "" -#: assets/build/formEditor.js:127564 -#: assets/build/formEditor.js:117526 +#: assets/build/formEditor.js:172 +msgid "Page Break" +msgstr "" + +#: assets/build/formEditor.js:172 msgid "Show Labels" msgstr "" -#: assets/build/formEditor.js:127570 -#: assets/build/formEditor.js:117536 +#: assets/build/formEditor.js:172 msgid "First Page Label" msgstr "" -#: assets/build/formEditor.js:127582 -#: assets/build/formEditor.js:117554 +#: assets/build/formEditor.js:172 msgid "Progress Indicator" msgstr "" -#: assets/build/formEditor.js:127589 -#: assets/build/formEditor.js:117560 +#: assets/build/formEditor.js:172 msgid "Progress Bar" msgstr "" -#: assets/build/formEditor.js:127592 -#: assets/build/formEditor.js:117564 +#: assets/build/formEditor.js:172 msgid "Connector" msgstr "" -#: assets/build/formEditor.js:127595 -#: assets/build/formEditor.js:117568 +#: assets/build/formEditor.js:172 msgid "Steps" msgstr "" -#: assets/build/formEditor.js:127607 -#: assets/build/formEditor.js:117585 +#: assets/build/formEditor.js:172 msgid "Next Button Text" msgstr "" -#: assets/build/formEditor.js:127618 -#: assets/build/formEditor.js:117600 +#: assets/build/formEditor.js:172 msgid "Back Button Text" msgstr "" -#: assets/build/formEditor.js:128205 -#: assets/build/formEditor.js:128206 +#: assets/build/formEditor.js:172 +msgid "Are you sure you want to close? Your unsaved changes will be lost as you have some validation errors." +msgstr "" + +#: assets/build/formEditor.js:172 +msgid "There are few unsaved changes. Please save your changes to reflect the updates." +msgstr "" + +#: assets/build/formEditor.js:172 +msgid "Unlock Advanced Styling" +msgstr "" + +#: assets/build/formEditor.js:172 +msgid "Get full control over your form's look with custom colors, fonts, and layouts." +msgstr "" + +#: assets/build/formEditor.js:172 #: modules/gutenberg/build/blocks.js:6 #: modules/gutenberg/build/blocks.js:8 -#: assets/build/formEditor.js:118373 -#: assets/build/formEditor.js:118374 msgid "Solid" msgstr "" -#: assets/build/formEditor.js:128416 -#: assets/build/formEditor.js:118602 +#: assets/build/formEditor.js:172 msgid "Text Color on Primary" msgstr "" -#: assets/build/formEditor.js:128583 -#: assets/build/formEditor.js:118813 +#: assets/build/formEditor.js:172 msgid "Add Custom CSS Class(es)" msgstr "" -#: assets/build/formEditor.js:128591 -#: assets/build/formEditor.js:118821 +#: assets/build/formEditor.js:172 msgid "Class names should be separated by spaces. Each class name must not start with a digit, hyphen, or underscore. They can only include letters (including Unicode characters), numbers, hyphens, and underscores." msgstr "" -#: assets/build/formEditor.js:128900 -#: assets/build/formEditor.js:119123 -msgid "Page break" +#: assets/build/formEditor.js:172 +msgid "Date Picker" msgstr "" -#: assets/build/formEditor.js:128931 -#: assets/build/formEditor.js:119155 -msgid "Form submitted successfully!" +#: assets/build/formEditor.js:172 +msgid "Time Picker" msgstr "" -#: assets/build/formEditor.js:130782 -#: assets/build/settings.js:80280 -#: assets/build/formEditor.js:121125 -#: assets/build/settings.js:73062 -msgid "Expected format for emails - email@sureforms.com or John Doe " +#: assets/build/formEditor.js:172 +msgid "Hidden" msgstr "" -#: assets/build/formEditor.js:132109 -#: assets/build/settings.js:80449 -#: assets/build/formEditor.js:122490 -#: assets/build/settings.js:73217 -msgid "Add Key" +#: assets/build/formEditor.js:172 +msgid "Slider" msgstr "" -#: assets/build/formEditor.js:132117 -#: assets/build/settings.js:80457 -#: assets/build/formEditor.js:122504 -#: assets/build/settings.js:73231 -msgid "Add Value" +#: assets/build/formEditor.js:172 +msgid "Rating" msgstr "" -#: assets/build/formEditor.js:132133 -#: assets/build/settings.js:80473 -#: assets/build/formEditor.js:122525 -#: assets/build/settings.js:73252 -msgid "Add" +#: assets/build/formEditor.js:172 +msgid "Login" msgstr "" -#: assets/build/formEditor.js:134115 -#: assets/build/formEditor.js:124566 -msgid "Failed to save. Please try again." +#: assets/build/formEditor.js:172 +msgid "Register" msgstr "" -#: assets/build/formEditor.js:134218 -#: assets/build/formEditor.js:124599 -msgid "All changes will be saved automatically when you press back." +#: assets/build/formEditor.js:172 +msgid "Lost Password" msgstr "" -#: assets/build/formEditor.js:134361 -#: assets/build/formEditor.js:124771 -msgid "Settings saved, but post attributes (password / title / content) failed to update. Retry to persist them." +#: assets/build/formEditor.js:172 +msgid "Reset Password" msgstr "" -#: assets/build/formEditor.js:134381 -#: assets/build/formEditor.js:124799 -msgid "Failed to save form settings." +#: assets/build/formEditor.js:172 +msgid "SUREFORMS PREMIUM FIELDS" msgstr "" -#: assets/build/formEditor.js:134462 -#: assets/build/settings.js:72202 -#: assets/build/formEditor.js:124900 -#: assets/build/settings.js:64527 -msgid "Savingโ€ฆ" +#: assets/build/formEditor.js:172 +msgid "Upgrade to Unlock These Fields" msgstr "" -#: assets/build/formEditor.js:134462 -#: assets/build/settings.js:72202 -#: assets/build/formEditor.js:124901 -#: assets/build/settings.js:64528 -msgid "Save" +#: assets/build/formEditor.js:172 +msgid "Add Block" msgstr "" -#: assets/build/formEditor.js:136433 -#: modules/gutenberg/build/blocks.js:6 -#: assets/build/formEditor.js:127278 -msgid "data object is empty" +#: assets/build/formEditor.js:172 +msgid "Customize with SureForms" msgstr "" -#. translators: %1$s: site URL, %2$s: site URL. -#: assets/build/formEditor.js:139122 -#: assets/build/settings.js:84061 -#: assets/build/formEditor.js:129748 -#: assets/build/settings.js:76566 -#, js-format -msgid "The current 'From Email' address may not match your website domain name (%1$s). This can cause your notification emails to be blocked or marked as spam. Alternately, try using a From Address that matches your website domain (admin@%2$s)." +#: assets/build/formEditor.js:172 +msgid "Page break" msgstr "" -#: assets/build/formEditor.js:139134 -#: assets/build/settings.js:84073 -#: assets/build/formEditor.js:129768 -#: assets/build/settings.js:76586 -msgid "Please enter a valid email address. Your notifications won't be sent if the field is not filled in correctly." +#: assets/build/formEditor.js:172 +msgid "Form submitted successfully!" msgstr "" -#. translators: %1$s: site URL, %2$s: site URL. -#: assets/build/formEditor.js:139142 -#: assets/build/settings.js:84081 -#: assets/build/formEditor.js:129779 -#: assets/build/settings.js:76597 -#, js-format -msgid "The current 'From Email' address does not match your website domain name (%1$s). This can cause your notification emails to be blocked or marked as spam. Alternately, try using a From Address that matches your website domain (admin@%2$s)." +#: assets/build/formEditor.js:172 +msgid "Conversational Layout" msgstr "" -#. translators: %s: site URL. -#: assets/build/formEditor.js:139162 -#: assets/build/settings.js:84101 -#: assets/build/formEditor.js:129807 -#: assets/build/settings.js:76625 -#, js-format -msgid "The current 'From Email' address may not match your website domain name (%s). This can cause your notification emails to be blocked or marked as spam. " +#: assets/build/formEditor.js:172 +#: assets/build/templatePicker.js:172 +msgid "Unlock Conversational Forms" msgstr "" -#. translators: %s: site URL. -#: assets/build/formEditor.js:139164 -#: assets/build/settings.js:84103 -#: assets/build/formEditor.js:129815 -#: assets/build/settings.js:76633 -#, js-format -msgid "The current 'From Email' address does not match your website domain name (%s). This can cause your notification emails to be blocked or marked as spam. " +#: assets/build/formEditor.js:172 +msgid "With the SureForms Pro Plan, you can transform your forms into engaging conversational layouts for a seamless user experience." msgstr "" -#. translators: %s: site URL. -#: assets/build/formEditor.js:139167 -#: assets/build/settings.js:84106 -#: assets/build/formEditor.js:129826 -#: assets/build/settings.js:76644 -#, js-format -msgid " Alternately, try using a From Address that matches your website domain (admin@%s)." +#: assets/build/formEditor.js:172 +msgid "Publish Your Form" msgstr "" -#: assets/build/formEditor.js:139168 -#: assets/build/settings.js:84107 -#: assets/build/formEditor.js:129836 -#: assets/build/settings.js:76654 -msgid "We strongly recommend that you install the free " +#: assets/build/formEditor.js:172 +msgid "Enable Instant Form" msgstr "" -#: assets/build/formEditor.js:139172 -#: assets/build/settings.js:84111 -#: assets/build/formEditor.js:129847 -#: assets/build/settings.js:76665 -msgid " plugin! The Setup Wizard makes it easy to fix your emails. " +#: assets/build/formEditor.js:172 +msgid "Enable This to Instantly Publish the Form" msgstr "" -#: assets/build/formEditor.js:140114 -#: assets/build/formEditor.js:130621 -msgid "SureForms Description" +#: assets/build/formEditor.js:172 +msgid "Enable Preview" msgstr "" -#: assets/build/formEditor.js:140118 -#: assets/build/formEditor.js:130628 -msgid "Form Options" +#: assets/build/formEditor.js:172 +msgid "Show Title" msgstr "" -#: assets/build/formEditor.js:140137 -#: assets/build/formEditor.js:130666 -msgid "Form Shortcode" +#: assets/build/formEditor.js:172 +msgid "Site Logo" msgstr "" -#: assets/build/formEditor.js:140138 -#: assets/build/formEditor.js:130667 -msgid "Paste this shortcode on the page or post to render this form." +#: assets/build/formEditor.js:172 +msgid "Banner Background" msgstr "" -#. translators: %d: number of imported forms -#: assets/build/forms.js:63370 -#: assets/build/forms.js:65845 -#: assets/build/forms.js:54538 -#: assets/build/forms.js:56803 -#, js-format -msgid "%d form imported successfully." -msgid_plural "%d forms imported successfully." -msgstr[0] "" -msgstr[1] "" +#: assets/build/formEditor.js:172 +msgid "Upload Image" +msgstr "" -#: assets/build/forms.js:63426 -#: assets/build/forms.js:63583 -#: assets/build/forms.js:54598 -#: assets/build/forms.js:54731 -msgid "Move form to trash?" -msgid_plural "Move forms to trash?" -msgstr[0] "" -msgstr[1] "" +#: assets/build/formEditor.js:172 +msgid "Style Your Instant Form Page Here" +msgstr "" -#. translators: %d: number of forms -#: assets/build/forms.js:63428 -#: assets/build/forms.js:54606 -#, js-format -msgid "%d form will be moved to trash and can be restored later." -msgid_plural "%d forms will be moved to trash and can be restored later." -msgstr[0] "" -msgstr[1] "" +#: assets/build/formEditor.js:172 +msgid "Use banner as page background" +msgstr "" -#: assets/build/forms.js:63464 -#: assets/build/forms.js:54630 -msgid "Restore Form" -msgid_plural "Restore Forms" -msgstr[0] "" -msgstr[1] "" +#: assets/build/formEditor.js:172 +msgid "Form Width" +msgstr "" -#. translators: %d: number of forms -#: assets/build/forms.js:63466 -#: assets/build/forms.js:54638 -#, js-format -msgid "%d form will be restored from trash." -msgid_plural "%d forms will be restored from trash." -msgstr[0] "" -msgstr[1] "" +#: assets/build/formEditor.js:172 +msgid "Instant Form Padding" +msgstr "" -#: assets/build/forms.js:63502 -#: assets/build/forms.js:54662 -msgid "Delete Form" -msgid_plural "Delete Forms" -msgstr[0] "" -msgstr[1] "" +#: assets/build/formEditor.js:172 +msgid "Instant Form Border Radius" +msgstr "" -#. translators: %d: number of forms -#: assets/build/forms.js:63504 -#: assets/build/forms.js:54670 -#, js-format -msgid "Are you sure you want to permanently delete %d form? This action cannot be undone." -msgid_plural "Are you sure you want to permanently delete %d forms? This action cannot be undone." -msgstr[0] "" -msgstr[1] "" +#: assets/build/formEditor.js:172 +msgid "URL Slug" +msgstr "" -#: assets/build/forms.js:63540 -#: assets/build/forms.js:63620 -#: assets/build/forms.js:54694 -#: assets/build/forms.js:54752 -msgid "Switch form to draft?" -msgid_plural "Switch forms to draft?" -msgstr[0] "" -msgstr[1] "" +#: assets/build/formEditor.js:172 +msgid "The last part of the URL." +msgstr "" -#. translators: %d: number of forms -#: assets/build/forms.js:63542 -#: assets/build/forms.js:54702 -#, js-format -msgid "%d form will be switched to draft and will no longer be publicly accessible." -msgid_plural "%d forms will be switched to draft and will no longer be publicly accessible." -msgstr[0] "" -msgstr[1] "" +#: assets/build/formEditor.js:172 +msgid "Learn more." +msgstr "" -#: assets/build/forms.js:63570 -#: assets/build/forms.js:63649 -#: assets/build/forms.js:64376 -#: assets/build/forms.js:64879 -#: assets/build/forms.js:54717 -#: assets/build/forms.js:54764 -#: assets/build/forms.js:55390 -#: assets/build/forms.js:55867 -msgid "Switch to Draft" +#: assets/build/formEditor.js:172 +msgid "SureForms Description" msgstr "" -#: assets/build/forms.js:63584 -#: assets/build/forms.js:54732 -msgid "This form will be moved to trash and can be restored later." +#: assets/build/formEditor.js:172 +msgid "Form Options" msgstr "" -#: assets/build/forms.js:63621 -#: assets/build/forms.js:54753 -msgid "This form will be switched to draft and will no longer be publicly accessible." +#: assets/build/formEditor.js:172 +msgid "Form Shortcode" msgstr "" -#: assets/build/forms.js:63660 -#: assets/build/forms.js:54777 -msgid "Delete form?" +#: assets/build/formEditor.js:172 +msgid "Paste this shortcode on the page or post to render this form." msgstr "" -#: assets/build/forms.js:63661 -#: assets/build/forms.js:54778 -msgid "Are you sure you want to permanently delete this form? This action cannot be undone." +#: assets/build/forms.js:2 +msgid "Export failed: no data received." msgstr "" -#: assets/build/forms.js:63697 -#: assets/build/forms.js:54798 -msgid "Duplicate form?" +#: assets/build/forms.js:172 +msgid "Please select a file to import." msgstr "" -#. translators: %s: form title -#: assets/build/forms.js:63699 -#: assets/build/forms.js:54801 -#, js-format -msgid "This will create a copy of \"%s\" with all its settings." +#: assets/build/forms.js:172 +msgid "Invalid JSON file format." msgstr "" -#: assets/build/forms.js:63771 -#: assets/build/forms.js:54881 -msgid "Error loading forms" +#: assets/build/forms.js:172 +msgid "Failed to read file." msgstr "" -#: assets/build/forms.js:64147 -#: assets/build/forms.js:55150 -msgid "No Forms" +#: assets/build/forms.js:172 +msgid "Import failed." msgstr "" -#: assets/build/forms.js:64160 -#: assets/build/forms.js:55164 -msgid "Hi there, let's get you started" +#: assets/build/forms.js:172 +msgid "An error occurred during import." msgstr "" -#: assets/build/forms.js:64165 -#: assets/build/forms.js:55176 -msgid "It looks like you haven't created any forms yet. Start building with SureForms and launch powerful forms in just a few clicks." +#: assets/build/forms.js:172 +msgid "Import Forms" msgstr "" -#: assets/build/forms.js:64169 -#: assets/build/forms.js:55185 -msgid "Design forms with our Gutenberg-native builder." +#: assets/build/forms.js:172 +msgid "Select a SureForms export file (.json) to import." msgstr "" -#: assets/build/forms.js:64169 -#: assets/build/forms.js:55189 -msgid "Use AI to generate forms instantly from a simple prompt." +#: assets/build/forms.js:172 +msgid "Please select a valid JSON file." msgstr "" -#: assets/build/forms.js:64169 -#: assets/build/forms.js:55193 -msgid "Build instant forms and share them with a linkโ€”no embedding needed." +#: assets/build/forms.js:172 +msgid "Drag and drop or browse files" msgstr "" -#: assets/build/forms.js:64169 -#: assets/build/forms.js:55197 -msgid "Build engaging conversational, calculation, and multi-step forms." +#: assets/build/forms.js:172 +msgid "Drop a form file (.json) here" msgstr "" -#: assets/build/forms.js:64193 -#: assets/build/forms.js:64458 -#: assets/build/forms.js:65269 -#: assets/build/forms.js:55230 -#: assets/build/forms.js:55517 -#: assets/build/forms.js:56263 +#: assets/build/forms.js:172 msgid "Import Form" msgstr "" -#: assets/build/forms.js:64311 -#: assets/build/forms.js:55327 +#: assets/build/forms.js:172 msgid "Published" msgstr "" -#: assets/build/forms.js:64314 -#: assets/build/forms.js:55331 +#: assets/build/forms.js:172 msgid "Drafts" msgstr "" -#: assets/build/forms.js:64402 -#: assets/build/forms.js:64854 -#: assets/build/forms.js:55429 -#: assets/build/forms.js:55850 +#: assets/build/forms.js:172 +msgid "Switch to Draft" +msgstr "" + +#: assets/build/forms.js:172 msgid "Export" msgstr "" -#: assets/build/forms.js:64442 -#: assets/build/forms.js:55497 +#: assets/build/forms.js:172 msgid "Search formsโ€ฆ" msgstr "" -#: assets/build/forms.js:64642 -#: assets/build/forms.js:55654 +#: assets/build/forms.js:172 msgid "No forms found" msgstr "" -#: assets/build/forms.js:64735 -#: assets/build/forms.js:55712 +#: assets/build/forms.js:172 msgid "Title" msgstr "" -#: assets/build/forms.js:64756 -#: assets/build/forms.js:55737 +#: assets/build/forms.js:172 msgid "(Draft)" msgstr "" -#: assets/build/forms.js:64759 -#: assets/build/forms.js:55745 +#: assets/build/forms.js:172 msgid "Shortcode" msgstr "" -#: assets/build/forms.js:64778 -#: assets/build/forms.js:55767 +#: assets/build/forms.js:172 msgid "Copied!" msgstr "" -#: assets/build/forms.js:64778 -#: assets/build/forms.js:55768 +#: assets/build/forms.js:172 msgid "Copy Shortcode" msgstr "" -#: assets/build/forms.js:65054 -#: assets/build/forms.js:65172 -#: assets/build/forms.js:56003 -#: assets/build/forms.js:56110 -msgid "Please select a valid JSON file." -msgstr "" - -#: assets/build/forms.js:65084 -#: assets/build/forms.js:56026 -msgid "Please select a file to import." -msgstr "" - -#: assets/build/forms.js:65098 -#: assets/build/forms.js:56044 -msgid "Invalid JSON file format." -msgstr "" - -#: assets/build/forms.js:65102 -#: assets/build/forms.js:56051 -msgid "Failed to read file." +#: assets/build/forms.js:172 +msgid "No Forms" msgstr "" -#: assets/build/forms.js:65131 -#: assets/build/forms.js:56074 -msgid "Import failed." +#: assets/build/forms.js:172 +msgid "Hi there, let's get you started" msgstr "" -#: assets/build/forms.js:65139 -#: assets/build/forms.js:56081 -msgid "An error occurred during import." +#: assets/build/forms.js:172 +msgid "It looks like you haven't created any forms yet. Start building with SureForms and launch powerful forms in just a few clicks." msgstr "" -#: assets/build/forms.js:65190 -#: assets/build/forms.js:56133 -msgid "Import Forms" +#: assets/build/forms.js:172 +msgid "Design forms with our Gutenberg-native builder." msgstr "" -#: assets/build/forms.js:65190 -#: assets/build/forms.js:56138 -msgid "Select a SureForms export file (.json) to import." +#: assets/build/forms.js:172 +msgid "Use AI to generate forms instantly from a simple prompt." msgstr "" -#: assets/build/forms.js:65213 -#: assets/build/forms.js:56169 -msgid "Drag and drop or browse files" +#: assets/build/forms.js:172 +msgid "Build instant forms and share them with a linkโ€”no embedding needed." msgstr "" -#: assets/build/forms.js:65216 -#: assets/build/forms.js:56178 -msgid "Drop a form file (.json) here" +#: assets/build/forms.js:172 +msgid "Build engaging conversational, calculation, and multi-step forms." msgstr "" -#. translators: %d: number of forms still pending import from the source plugin. -#: assets/build/forms.js:65432 -#: assets/build/forms.js:56407 +#: assets/build/forms.js:172 #, js-format msgid "%d form to import" msgid_plural "%d forms to import" msgstr[0] "" msgstr[1] "" -#. translators: %s: source plugin title (e.g. "Contact Form 7"). -#: assets/build/forms.js:65452 -#: assets/build/forms.js:56425 +#: assets/build/forms.js:172 #, js-format msgid "Bring your forms from %s into SureForms" msgstr "" -#: assets/build/forms.js:65464 -#: assets/build/settings.js:76579 -#: assets/build/forms.js:56445 -#: assets/build/settings.js:69032 +#: assets/build/forms.js:172 +#: assets/build/settings.js:172 msgid "Import" msgstr "" -#: assets/build/forms.js:65469 -#: assets/build/forms.js:56452 +#: assets/build/forms.js:172 msgid "Dismiss migration banner" msgstr "" -#: assets/build/forms.js:65760 -#: assets/build/forms.js:56677 +#: assets/build/forms.js:172 msgid "An error occurred while fetching forms." msgstr "" -#. translators: %d: number of forms -#: assets/build/forms.js:65783 -#: assets/build/forms.js:56702 +#: assets/build/forms.js:172 #, js-format msgid "%d form moved to trash." msgid_plural "%d forms moved to trash." msgstr[0] "" msgstr[1] "" -#. translators: %d: number of forms -#: assets/build/forms.js:65787 -#: assets/build/forms.js:56714 +#: assets/build/forms.js:172 +#, js-format +msgid "%d form restored." +msgid_plural "%d forms restored." +msgstr[0] "" +msgstr[1] "" + +#: assets/build/forms.js:172 +#, js-format +msgid "%d form permanently deleted." +msgid_plural "%d forms permanently deleted." +msgstr[0] "" +msgstr[1] "" + +#: assets/build/forms.js:172 +#, js-format +msgid "%d form switched to draft." +msgid_plural "%d forms switched to draft." +msgstr[0] "" +msgstr[1] "" + +#: assets/build/forms.js:172 +msgid "An error occurred while performing the action." +msgstr "" + +#: assets/build/forms.js:172 +#, js-format +msgid "Form \"%s\" duplicated successfully." +msgstr "" + +#: assets/build/forms.js:172 +msgid "An error occurred while duplicating the form." +msgstr "" + +#: assets/build/forms.js:172 +#, js-format +msgid "%d form imported successfully." +msgid_plural "%d forms imported successfully." +msgstr[0] "" +msgstr[1] "" + +#: assets/build/forms.js:172 +msgid "Error loading forms" +msgstr "" + +#: assets/build/forms.js:172 +msgid "Move form to trash?" +msgid_plural "Move forms to trash?" +msgstr[0] "" +msgstr[1] "" + +#: assets/build/forms.js:172 +#, js-format +msgid "%d form will be moved to trash and can be restored later." +msgid_plural "%d forms will be moved to trash and can be restored later." +msgstr[0] "" +msgstr[1] "" + +#: assets/build/forms.js:172 +msgid "Delete Form" +msgid_plural "Delete Forms" +msgstr[0] "" +msgstr[1] "" + +#: assets/build/forms.js:172 +#, js-format +msgid "Are you sure you want to permanently delete %d form? This action cannot be undone." +msgid_plural "Are you sure you want to permanently delete %d forms? This action cannot be undone." +msgstr[0] "" +msgstr[1] "" + +#: assets/build/forms.js:172 +msgid "Restore Form" +msgid_plural "Restore Forms" +msgstr[0] "" +msgstr[1] "" + +#: assets/build/forms.js:172 #, js-format -msgid "%d form restored." -msgid_plural "%d forms restored." +msgid "%d form will be restored from trash." +msgid_plural "%d forms will be restored from trash." msgstr[0] "" msgstr[1] "" -#. translators: %d: number of forms -#: assets/build/forms.js:65791 -#: assets/build/forms.js:56726 -#, js-format -msgid "%d form permanently deleted." -msgid_plural "%d forms permanently deleted." +#: assets/build/forms.js:172 +msgid "Switch form to draft?" +msgid_plural "Switch forms to draft?" msgstr[0] "" msgstr[1] "" -#. translators: %d: number of forms -#: assets/build/forms.js:65795 -#: assets/build/forms.js:56738 +#: assets/build/forms.js:172 #, js-format -msgid "%d form switched to draft." -msgid_plural "%d forms switched to draft." +msgid "%d form will be switched to draft and will no longer be publicly accessible." +msgid_plural "%d forms will be switched to draft and will no longer be publicly accessible." msgstr[0] "" msgstr[1] "" -#: assets/build/forms.js:65808 -#: assets/build/forms.js:56759 -msgid "An error occurred while performing the action." -msgstr "" - -#: assets/build/forms.js:65823 -#: assets/build/forms.js:56777 -msgid "Forms exported successfully!" +#: assets/build/forms.js:172 +msgid "This form will be moved to trash and can be restored later." msgstr "" -#: assets/build/forms.js:65826 -#: assets/build/forms.js:56782 -msgid "Unable to export forms. Please try again." +#: assets/build/forms.js:172 +msgid "This form will be switched to draft and will no longer be publicly accessible." msgstr "" -#: assets/build/forms.js:65855 -#: assets/build/forms.js:56822 -msgid "An error occurred while importing forms." +#: assets/build/forms.js:172 +msgid "Delete form?" msgstr "" -#. translators: %s: new form title -#: assets/build/forms.js:65873 -#: assets/build/forms.js:56843 -#, js-format -msgid "Form \"%s\" duplicated successfully." +#: assets/build/forms.js:172 +msgid "Are you sure you want to permanently delete this form? This action cannot be undone." msgstr "" -#: assets/build/forms.js:65882 -#: assets/build/forms.js:56857 -msgid "An error occurred while duplicating the form." +#: assets/build/forms.js:172 +msgid "Duplicate form?" msgstr "" -#: assets/build/forms.js:66288 -#: assets/build/forms.js:57211 -msgid "Export failed: no data received." +#: assets/build/forms.js:172 +#, js-format +msgid "This will create a copy of \"%s\" with all its settings." msgstr "" #: assets/build/formSubmit.js:2 @@ -18688,12 +16357,7 @@ msgid "Please create a form first" msgstr "" #: assets/build/learn.js:172 -#: assets/build/settings.js:75248 -#: assets/build/settings.js:75391 -#: assets/build/settings.js:75501 -#: assets/build/settings.js:67726 -#: assets/build/settings.js:67866 -#: assets/build/settings.js:67997 +#: assets/build/settings.js:172 msgid "Documentation" msgstr "" @@ -18757,33 +16421,25 @@ msgid "Upgrade to SureForms" msgstr "" #: assets/build/payments.js:2 -#: assets/build/settings.js:72607 -#: assets/build/settings.js:64862 +#: assets/build/settings.js:172 msgid "USD - US Dollar" msgstr "" #: assets/build/payments.js:2 #: assets/build/payments.js:172 -#: assets/build/settings.js:73137 -#: assets/build/settings.js:65493 +#: assets/build/settings.js:172 msgid "Payment Mode" msgstr "" #: assets/build/payments.js:2 #: assets/build/payments.js:172 -#: assets/build/settings.js:73154 -#: assets/build/settings.js:73661 -#: assets/build/settings.js:65514 -#: assets/build/settings.js:66001 +#: assets/build/settings.js:172 msgid "Test Mode" msgstr "" #: assets/build/payments.js:2 #: assets/build/payments.js:172 -#: assets/build/settings.js:73148 -#: assets/build/settings.js:73656 -#: assets/build/settings.js:65507 -#: assets/build/settings.js:65994 +#: assets/build/settings.js:172 msgid "Live Mode" msgstr "" @@ -19050,8 +16706,7 @@ msgid "Failed to delete log. Please try again." msgstr "" #: assets/build/payments.js:172 -#: assets/build/settings.js:76555 -#: assets/build/settings.js:68991 +#: assets/build/settings.js:172 msgid "Action" msgstr "" @@ -19191,1177 +16846,909 @@ msgstr "" msgid "Turn your forms into powerful quizzes. Upgrade to SureForms to unlock quiz capabilities:" msgstr "" -#: assets/build/settings.js:71997 -#: assets/build/settings.js:64324 -msgid "Integration" +#: assets/build/settings.js:172 +msgid "General Settings" msgstr "" -#: assets/build/settings.js:72641 -#: assets/build/settings.js:64909 -msgid "1% transaction and payment gateway fees apply." +#: assets/build/settings.js:172 +msgid "Set up email summaries, admin alerts, and data preferences to manage your forms with ease." msgstr "" -#: assets/build/settings.js:72648 -#: assets/build/settings.js:64923 -msgid "2.9% transaction and payment gateway fees apply. Activate license to reduce transaction fees." +#: assets/build/settings.js:172 +msgid "Global Defaults" msgstr "" -#: assets/build/settings.js:72654 -#: assets/build/settings.js:64936 -msgid "2.9% transaction and payment gateway fees apply." +#: assets/build/settings.js:172 +msgid "Form Restrictions" msgstr "" -#. translators: %1$s: Stripe dashboard button -#: assets/build/settings.js:72958 -#: assets/build/settings.js:65270 -#, js-format -msgid "Please visit %1$s, delete an unused webhook, then click below to retry." +#: assets/build/settings.js:172 +msgid "Configure default settings that apply to newly created forms." msgstr "" -#: assets/build/settings.js:72967 -#: assets/build/settings.js:65285 -msgid "SureForms could not create a webhook because your Stripe account has run out of free slots. Webhooks are needed to receive updates about payments." +#: assets/build/settings.js:172 +msgid "Form Validation" msgstr "" -#: assets/build/settings.js:72979 -#: assets/build/settings.js:65309 -msgid "Stripe Dashboard" +#: assets/build/settings.js:172 +msgid "Customize default error messages shown when users submit invalid or incomplete form entries." msgstr "" -#: assets/build/settings.js:72987 -#: assets/build/settings.js:65323 -msgid "Creatingโ€ฆ" +#: assets/build/settings.js:172 +msgid "reCAPTCHA" msgstr "" -#: assets/build/settings.js:72987 -#: assets/build/settings.js:65324 -msgid "Create Webhook" +#: assets/build/settings.js:172 +msgid "Turnstile" msgstr "" -#: assets/build/settings.js:73092 -#: assets/build/settings.js:65438 -msgid "Left ($100)" +#: assets/build/settings.js:172 +msgid "Honeypot" msgstr "" -#: assets/build/settings.js:73095 -#: assets/build/settings.js:65439 -msgid "Right (100$)" +#: assets/build/settings.js:172 +msgid "Enable spam protection for your forms using CAPTCHA services or honeypot security." msgstr "" -#: assets/build/settings.js:73098 -#: assets/build/settings.js:65440 -msgid "Left Space ($ 100)" +#: assets/build/settings.js:172 +msgid "Google Maps" msgstr "" -#: assets/build/settings.js:73101 -#: assets/build/settings.js:65443 -msgid "Right Space (100 $)" +#: assets/build/settings.js:172 +msgid "Configure Google Maps API key for address autocomplete and map preview." msgstr "" -#: assets/build/settings.js:73120 -#: assets/build/settings.js:65463 -msgid "Select Currency" +#: assets/build/settings.js:172 +msgid "MCP" msgstr "" -#: assets/build/settings.js:73131 -#: assets/build/settings.js:65482 -msgid "Select the default currency for payment forms." +#: assets/build/settings.js:172 +msgid "Configure AI client permissions and MCP server settings." msgstr "" -#: assets/build/settings.js:73159 -#: assets/build/settings.js:65520 -msgid "Test mode allows you to process payments without real charges. Switch to Live mode for actual transactions." +#: assets/build/settings.js:172 +msgid "View documentation" msgstr "" -#: assets/build/settings.js:73169 -#: assets/build/settings.js:65538 -msgid "Currency Sign Position" +#: assets/build/settings.js:172 +msgid "Payment Methods" msgstr "" -#: assets/build/settings.js:73180 -#: assets/build/settings.js:65557 -msgid "Select the position of the currency symbol relative to the amount." +#: assets/build/settings.js:172 +msgid "Connect and manage your payment gateways to securely accept transactions through your forms." msgstr "" -#: assets/build/settings.js:73186 -#: assets/build/settings.js:65576 -msgid "General Payment Settings" +#: assets/build/settings.js:172 +msgid "Migration" msgstr "" -#: assets/build/settings.js:73188 -#: assets/build/settings.js:65578 -msgid "These settings apply to all payment gateways." +#: assets/build/settings.js:172 +msgid "Import forms from Contact Form 7, WPForms, Gravity Forms, and other plugins into SureForms." msgstr "" -#: assets/build/settings.js:73414 -#: assets/build/settings.js:65749 -msgid "Successfully connected to Stripe!" +#: assets/build/settings.js:172 +msgid "Tuesday" msgstr "" -#: assets/build/settings.js:73456 -#: assets/build/settings.js:65794 -msgid "Invalid response from server. Please try again." +#: assets/build/settings.js:172 +msgid "Wednesday" msgstr "" -#: assets/build/settings.js:73465 -#: assets/build/settings.js:65806 -msgid "Failed to connect to Stripe." +#: assets/build/settings.js:172 +msgid "Thursday" msgstr "" -#: assets/build/settings.js:73483 -#: assets/build/settings.js:65816 -msgid "Disconnect Stripe Account" +#: assets/build/settings.js:172 +msgid "Friday" msgstr "" -#: assets/build/settings.js:73484 -#: assets/build/settings.js:65817 -msgid "Are you sure you want to disconnect your Stripe account? This will stop all active payments, subscriptions, and form transactions connected to this account." +#: assets/build/settings.js:172 +msgid "Saturday" msgstr "" -#: assets/build/settings.js:73485 -#: assets/build/settings.js:73681 -#: assets/build/settings.js:65821 -#: assets/build/settings.js:66032 -msgid "Disconnect" +#: assets/build/settings.js:172 +msgid "Sunday" msgstr "" -#: assets/build/settings.js:73514 -#: assets/build/settings.js:73559 -#: assets/build/settings.js:65843 -#: assets/build/settings.js:65897 -msgid "Failed to disconnect Stripe account." +#: assets/build/settings.js:172 +msgid "Enable email summaries" msgstr "" -#: assets/build/settings.js:73548 -#: assets/build/settings.js:65891 -msgid "Stripe account disconnected successfully." +#: assets/build/settings.js:172 +msgid "Test Email" msgstr "" -#: assets/build/settings.js:73596 -#: assets/build/settings.js:65919 -msgid "Webhook created successfully!" +#: assets/build/settings.js:172 +msgid "Schedule Reports" msgstr "" -#: assets/build/settings.js:73619 -#: assets/build/settings.js:73627 -#: assets/build/settings.js:65966 -#: assets/build/settings.js:65971 -msgid "Failed to create webhook." +#: assets/build/settings.js:172 +msgid "Enable IP logging" msgstr "" -#: assets/build/settings.js:73652 -#: assets/build/settings.js:65987 -msgid "Connection Status" +#: assets/build/settings.js:172 +msgid "If this option is turned on, the user's IP address will be saved with the form data" msgstr "" -#: assets/build/settings.js:73681 -#: assets/build/settings.js:66031 -msgid "Disconnectingโ€ฆ" +#: assets/build/settings.js:172 +msgid "Enable Admin Notification" msgstr "" -#: assets/build/settings.js:73707 -#: assets/build/settings.js:66064 -msgid "Webhook successfully connected, all Stripe events are being tracked." +#: assets/build/settings.js:172 +msgid "Admin notifications keep you informed about new form entries since your last visit." msgstr "" -#: assets/build/settings.js:73726 -#: assets/build/settings.js:66102 -msgid "Connect your Stripe account to start accepting payments through your forms." +#: assets/build/settings.js:172 +msgid "Turn on Admin Notification from here." msgstr "" -#: assets/build/settings.js:73732 -#: assets/build/settings.js:73746 -#: assets/build/settings.js:66116 -#: assets/build/settings.js:66148 -msgid "Connect to Stripe" +#: assets/build/settings.js:172 +msgid "Help shape the future of SureForms" msgstr "" -#: assets/build/settings.js:73734 -#: assets/build/settings.js:66119 -msgid "Securely connect to Stripe with just a few clicks to begin accepting payments! " +#: assets/build/settings.js:172 +msgid "Collect non-sensitive information from your website, such as the PHP version and features used, to help us fix bugs faster, make smarter decisions, and build features that actually matter to you. " msgstr "" -#: assets/build/settings.js:73739 -#: assets/build/settings.js:77054 -#: assets/build/settings.js:66129 -#: assets/build/settings.js:69477 +#: assets/build/settings.js:172 msgid "Learn More" msgstr "" -#: assets/build/settings.js:73742 -#: assets/build/settings.js:66142 -msgid "Stripe Settings" -msgstr "" - -#: assets/build/settings.js:74433 -#: assets/build/settings.js:66759 -msgid "Failed to load settings. Please refresh and try again." -msgstr "" - -#: assets/build/settings.js:74533 -#: assets/build/settings.js:66861 -msgid "Form Validation fields cannot be left blank." -msgstr "" - -#: assets/build/settings.js:74545 -#: assets/build/settings.js:66880 -msgid "Recipient email is required when email summaries are enabled." -msgstr "" - -#: assets/build/settings.js:74552 -#: assets/build/settings.js:66889 -msgid "Please enter a valid recipient email." -msgstr "" - -#: assets/build/settings.js:74608 -#: assets/build/settings.js:66939 -msgid "Settings saved." -msgstr "" - -#: assets/build/settings.js:74610 -#: assets/build/settings.js:66941 -msgid "Failed to save settings." -msgstr "" - -#: assets/build/settings.js:74612 -#: assets/build/settings.js:66944 -msgid "Some settings failed to save. Please retry." -msgstr "" - -#: assets/build/settings.js:74843 -#: assets/build/settings.js:67231 -msgid "General Settings" -msgstr "" - -#: assets/build/settings.js:74846 -#: assets/build/settings.js:67234 -msgid "Set up email summaries, admin alerts, and data preferences to manage your forms with ease." -msgstr "" - -#: assets/build/settings.js:74848 -#: assets/build/settings.js:67240 -msgid "Global Defaults" -msgstr "" - -#: assets/build/settings.js:74858 -#: assets/build/settings.js:67253 -msgid "Form Restrictions" -msgstr "" - -#: assets/build/settings.js:74864 -#: assets/build/settings.js:67261 -msgid "Configure default settings that apply to newly created forms." -msgstr "" - -#: assets/build/settings.js:74866 -#: assets/build/settings.js:67267 -msgid "Form Validation" -msgstr "" - -#: assets/build/settings.js:74869 -#: assets/build/settings.js:67270 -msgid "Customize default error messages shown when users submit invalid or incomplete form entries." -msgstr "" - -#: assets/build/settings.js:74875 -#: assets/build/settings.js:67281 -msgid "reCAPTCHA" +#: assets/build/settings.js:172 +msgid "Email Summaries" msgstr "" -#: assets/build/settings.js:74881 -#: assets/build/settings.js:67289 -msgid "Turnstile" +#: assets/build/settings.js:172 +msgid "IP Logging" msgstr "" -#: assets/build/settings.js:74884 -#: assets/build/settings.js:67293 -msgid "Honeypot" +#: assets/build/settings.js:172 +msgid "Anonymous Analytics" msgstr "" -#: assets/build/settings.js:74887 -#: assets/build/settings.js:67297 -msgid "Enable spam protection for your forms using CAPTCHA services or honeypot security." +#: assets/build/settings.js:172 +msgid "Failed to load pages. Please refresh and try again." msgstr "" -#: assets/build/settings.js:74903 -#: assets/build/settings.js:67321 -msgid "Google Maps" +#: assets/build/settings.js:172 +msgid "Required Error Messages" msgstr "" -#: assets/build/settings.js:74907 -#: assets/build/settings.js:67325 -msgid "Configure Google Maps API key for address autocomplete and map preview." +#: assets/build/settings.js:172 +msgid "Other Error Messages" msgstr "" -#: assets/build/settings.js:74909 -#: assets/build/settings.js:67331 -msgid "MCP" +#: assets/build/settings.js:172 +msgid "Validations" msgstr "" -#: assets/build/settings.js:74912 -#: assets/build/settings.js:67336 -msgid "Configure AI client permissions and MCP server settings." +#: assets/build/settings.js:172 +msgid "Input Field Unique" msgstr "" -#: assets/build/settings.js:74917 -#: assets/build/settings.js:67346 -msgid "View documentation" +#: assets/build/settings.js:172 +msgid "Email Field Unique" msgstr "" -#: assets/build/settings.js:74926 -#: assets/build/settings.js:67361 -msgid "Payment Methods" +#: assets/build/settings.js:172 +msgid "Invalid URL" msgstr "" -#: assets/build/settings.js:74929 -#: assets/build/settings.js:67365 -msgid "Connect and manage your payment gateways to securely accept transactions through your forms." +#: assets/build/settings.js:172 +msgid "Phone Field Unique" msgstr "" -#: assets/build/settings.js:74933 -#: assets/build/settings.js:67372 -msgid "Migration" +#: assets/build/settings.js:172 +msgid "Invalid Field Number Block" msgstr "" -#: assets/build/settings.js:74936 -#: assets/build/settings.js:67375 -msgid "Import forms from Contact Form 7, WPForms, Gravity Forms, and other plugins into SureForms." +#: assets/build/settings.js:172 +msgid "Confirmation Email Mismatch Message" msgstr "" -#: assets/build/settings.js:75143 -#: assets/build/settings.js:67621 -msgid "Some fields have unsaved changes. Discard them to continue, or stay to save your edits." +#: assets/build/settings.js:172 +msgid "Invalid Email" msgstr "" -#: assets/build/settings.js:75144 -#: assets/build/settings.js:67625 -msgid "Discard & switch" +#: assets/build/settings.js:172 +msgid "Number Minimum Value" msgstr "" -#: assets/build/settings.js:75209 -#: assets/build/settings.js:75350 -#: assets/build/settings.js:75462 -#: assets/build/settings.js:67681 -#: assets/build/settings.js:67818 -#: assets/build/settings.js:67949 -msgid "Site Key" +#: assets/build/settings.js:172 +#, js-format +msgid "%s represents the minimum input value. For example: \"Minimum value is 10.\"" msgstr "" -#: assets/build/settings.js:75213 -#: assets/build/settings.js:75353 -#: assets/build/settings.js:75466 -#: assets/build/settings.js:67686 -#: assets/build/settings.js:67822 -#: assets/build/settings.js:67954 -msgid "Secret Key" +#: assets/build/settings.js:172 +msgid "Number Maximum Value" msgstr "" -#: assets/build/settings.js:75228 -#: assets/build/settings.js:67698 -msgid "To enable hCAPTCHA, please add your site key and secret key. Configure these settings within the individual form." +#: assets/build/settings.js:172 +#, js-format +msgid "%s represents the maximum input value. For example: \"Maximum value is 100.\"" msgstr "" -#: assets/build/settings.js:75239 -#: assets/build/settings.js:75382 -#: assets/build/settings.js:75492 -#: assets/build/settings.js:67714 -#: assets/build/settings.js:67854 -#: assets/build/settings.js:67985 -msgid "Get Keys" +#: assets/build/settings.js:172 +msgid "Dropdown Minimum Selections" msgstr "" -#. translators: %s is the label of the input field. -#: assets/build/settings.js:75257 -#: assets/build/settings.js:75418 -#: assets/build/settings.js:75533 -#: assets/build/settings.js:67741 -#: assets/build/settings.js:67900 -#: assets/build/settings.js:68044 +#: assets/build/settings.js:172 #, js-format -msgid "Enter your %s here" +msgid "%s represents the minimum selections needed. For example: โ€œMinimum 2 selections are required.โ€" msgstr "" -#: assets/build/settings.js:75291 -#: assets/build/settings.js:67768 -msgid "Enable Honeypot Security" +#: assets/build/settings.js:172 +msgid "Dropdown Maximum Selections" msgstr "" -#: assets/build/settings.js:75292 -#: assets/build/settings.js:67769 -msgid "Enable Honeypot Security for better spam protection" +#: assets/build/settings.js:172 +#, js-format +msgid "%s represents the maximum selections allowed. For example: โ€œMaximum 4 selections are allowed.โ€" msgstr "" -#: assets/build/settings.js:75371 -#: assets/build/settings.js:67838 -msgid "To enable reCAPTCHA feature on your SureForms Please enable reCAPTCHA option on your blocks setting and select version. Add google reCAPTCHA secret and site key here. reCAPTCHA will be added to your page on front-end." +#: assets/build/settings.js:172 +msgid "Multiple Choice Minimum Selections" msgstr "" -#: assets/build/settings.js:75454 -#: assets/build/settings.js:67937 -msgid "Light" +#: assets/build/settings.js:172 +#, js-format +msgid "%s represents the minimum choices needed. For example: โ€œMinimum 1 selection is required.โ€" msgstr "" -#: assets/build/settings.js:75457 -#: assets/build/settings.js:67941 -msgid "Dark" +#: assets/build/settings.js:172 +msgid "Multiple Choice Maximum Selections" msgstr "" -#: assets/build/settings.js:75481 -#: assets/build/settings.js:67969 -msgid "To enable Cloudflare Turnstile, please add your site key and secret key. Configure these settings within the individual form." +#: assets/build/settings.js:172 +#, js-format +msgid "%s represents the maximum choices allowed. For example: โ€œMaximum 3 selections are allowed.โ€" msgstr "" -#: assets/build/settings.js:75506 -#: assets/build/settings.js:68005 -msgid "Appearance Mode" +#: assets/build/settings.js:172 +msgid "Input Field" msgstr "" -#: assets/build/settings.js:75598 -#: assets/build/settings.js:68091 -msgid "Failed to load pages. Please refresh and try again." +#: assets/build/settings.js:172 +msgid "Email Field" msgstr "" -#: assets/build/settings.js:75713 -#: assets/build/settings.js:68164 -msgid "Could not generate the import preview." +#: assets/build/settings.js:172 +msgid "URL Field" msgstr "" -#: assets/build/settings.js:75746 -#: assets/build/settings.js:68194 -msgid "Import failed. Please try again or check your error logs." +#: assets/build/settings.js:172 +msgid "Phone Field" msgstr "" -#: assets/build/settings.js:75778 -#: assets/build/settings.js:68222 -msgid "Go back" +#: assets/build/settings.js:172 +msgid "Textarea Field" msgstr "" -#: assets/build/settings.js:75792 -#: assets/build/settings.js:68246 -msgid "Update & import" +#: assets/build/settings.js:172 +msgid "Checkbox Field" msgstr "" -#: assets/build/settings.js:75792 -#: assets/build/settings.js:68247 -msgid "Confirm & import" +#: assets/build/settings.js:172 +msgid "Dropdown Field" msgstr "" -#. translators: %s: source form id. -#: assets/build/settings.js:75802 -#: assets/build/settings.js:68257 -#, js-format -msgid "Form #%s" +#: assets/build/settings.js:172 +msgid "Multiple Choice Field" msgstr "" -#. translators: %d: number of fields. -#: assets/build/settings.js:75819 -#: assets/build/settings.js:68274 -#, js-format -msgid "%d field will import" -msgid_plural "%d fields will import" -msgstr[0] "" -msgstr[1] "" - -#: assets/build/settings.js:75832 -#: assets/build/settings.js:68303 -msgid "Some fields can't be migrated yet" +#: assets/build/settings.js:172 +msgid "Address Field" msgstr "" -#: assets/build/settings.js:75838 -#: assets/build/settings.js:68310 -msgid "These fields will be skipped - add them manually after the form is created:" +#: assets/build/settings.js:172 +msgid "Number Field" msgstr "" -#: assets/build/settings.js:75850 -#: assets/build/settings.js:68331 -msgid "Some forms could not be parsed" +#: assets/build/settings.js:172 +msgid " Error Message" msgstr "" -#: assets/build/settings.js:75940 -#: assets/build/settings.js:68387 -msgid "Update existing" +#: assets/build/settings.js:172 +msgid "Site Key" msgstr "" -#: assets/build/settings.js:75946 -#: assets/build/settings.js:68389 -msgid "Create a new copy" +#: assets/build/settings.js:172 +msgid "Secret Key" msgstr "" -#: assets/build/settings.js:75999 -#: assets/build/settings.js:68425 -msgid "Could not load forms for this source." +#: assets/build/settings.js:172 +msgid "Light" msgstr "" -#: assets/build/settings.js:76082 -#: assets/build/settings.js:68503 -msgid "(untitled form)" +#: assets/build/settings.js:172 +msgid "Dark" msgstr "" -#: assets/build/settings.js:76097 -#: assets/build/settings.js:68517 -msgid "Previously imported" +#: assets/build/settings.js:172 +msgid "To enable reCAPTCHA feature on your SureForms Please enable reCAPTCHA option on your blocks setting and select version. Add google reCAPTCHA secret and site key here. reCAPTCHA will be added to your page on front-end." msgstr "" -#: assets/build/settings.js:76103 -#: assets/build/settings.js:68525 -msgid "Open existing SureForms form in a new tab" +#: assets/build/settings.js:172 +msgid "Get Keys" msgstr "" -#: assets/build/settings.js:76114 -#: assets/build/settings.js:68544 -msgid "On re-import" +#: assets/build/settings.js:172 +#, js-format +msgid "Enter your %s here" msgstr "" -#: assets/build/settings.js:76168 -#: assets/build/settings.js:68603 -msgid "No forms found in this plugin." +#: assets/build/settings.js:172 +msgid "To enable hCAPTCHA, please add your site key and secret key. Configure these settings within the individual form." msgstr "" -#. translators: 1: selected count, 2: total forms. -#: assets/build/settings.js:76185 -#: assets/build/settings.js:68623 -#, js-format -msgid "%1$d of %2$d form selected" -msgid_plural "%1$d of %2$d forms selected" -msgstr[0] "" -msgstr[1] "" +#: assets/build/settings.js:172 +msgid "To enable Cloudflare Turnstile, please add your site key and secret key. Configure these settings within the individual form." +msgstr "" -#: assets/build/settings.js:76196 -#: assets/build/settings.js:68648 -msgid "Preview update" +#: assets/build/settings.js:172 +msgid "Appearance Mode" msgstr "" -#: assets/build/settings.js:76196 -#: assets/build/settings.js:68649 -msgid "Preview import" +#: assets/build/settings.js:172 +msgid "Enable Honeypot Security" msgstr "" -#: assets/build/settings.js:76251 -#: assets/build/settings.js:68694 -msgid "Migration complete" +#: assets/build/settings.js:172 +msgid "Enable Honeypot Security for better spam protection" msgstr "" -#: assets/build/settings.js:76251 -#: assets/build/settings.js:68695 -msgid "Nothing was imported" +#: assets/build/settings.js:172 +msgid "Integration" msgstr "" -#. translators: %d: number of forms imported. -#: assets/build/settings.js:76256 -#: assets/build/settings.js:68702 -#, js-format -msgid "%d form was imported into SureForms." -msgid_plural "%d forms were imported into SureForms." -msgstr[0] "" -msgstr[1] "" +#: assets/build/settings.js:172 +msgid "Unlock powerful integrations in the Premium plan to automate your workflows and connect SureForms directly with your favourite tools." +msgstr "" -#: assets/build/settings.js:76256 -#: assets/build/settings.js:68710 -msgid "None of the selected forms could be migrated. See the warnings below for details." +#: assets/build/settings.js:172 +msgid "Send form submissions straight to CRMs, email, and marketing platforms" msgstr "" -#: assets/build/settings.js:76268 -#: assets/build/settings.js:68729 -msgid "Imported forms" +#: assets/build/settings.js:172 +msgid "Automate repetitive tasks with seamless data syncing" msgstr "" -#: assets/build/settings.js:76286 -#: assets/build/settings.js:68751 -msgid "Edit in SureForms" +#: assets/build/settings.js:172 +msgid "Access exclusive native integrations for faster workflows" msgstr "" -#: assets/build/settings.js:76289 -#: assets/build/settings.js:68761 -msgid "Some fields were skipped during import" +#: assets/build/settings.js:172 +msgid "Enable Google Address Autocomplete" msgstr "" -#: assets/build/settings.js:76295 -#: assets/build/settings.js:68768 -msgid "Add these manually in the form editor - they have no SureForms equivalent yet:" +#: assets/build/settings.js:172 +msgid "Upgrade to the SureForms Business Plan to add Google-powered address autocomplete with interactive map preview to your forms." msgstr "" -#: assets/build/settings.js:76307 -#: assets/build/settings.js:68789 -msgid "Some forms failed to import" +#: assets/build/settings.js:172 +msgid "Auto-suggest addresses as users type for faster, error-free submissions" msgstr "" -#: assets/build/settings.js:76321 -#: assets/build/settings.js:68808 -msgid "Import more forms" +#: assets/build/settings.js:172 +msgid "Show an interactive map preview with draggable pin for precise locations" msgstr "" -#: assets/build/settings.js:76426 -#: assets/build/settings.js:68867 -msgid "Could not load the list of importable plugins." +#: assets/build/settings.js:172 +msgid "Automatically populate address fields like city, state, and postal code" msgstr "" -#: assets/build/settings.js:76547 -#: assets/build/settings.js:68976 -msgid "No supported form plugins are active on this site. Activate one (such as Contact Form 7) with at least one form to import it into SureForms." +#: assets/build/settings.js:172 +msgid "1% transaction and payment gateway fees apply." msgstr "" -#: assets/build/settings.js:76551 -#: assets/build/settings.js:68987 -msgid "Plugin" +#: assets/build/settings.js:172 +msgid "2.9% transaction and payment gateway fees apply. Activate license to reduce transaction fees." +msgstr "" + +#: assets/build/settings.js:172 +msgid "2.9% transaction and payment gateway fees apply." msgstr "" -#. translators: %d: number of forms. -#: assets/build/settings.js:76568 -#: assets/build/settings.js:69011 +#: assets/build/settings.js:172 #, js-format -msgid "%d form" -msgid_plural "%d forms" -msgstr[0] "" -msgstr[1] "" +msgid "Please visit %1$s, delete an unused webhook, then click below to retry." +msgstr "" -#: assets/build/settings.js:76568 -#: assets/build/settings.js:69019 -msgid "No forms" +#: assets/build/settings.js:172 +msgid "SureForms could not create a webhook because your Stripe account has run out of free slots. Webhooks are needed to receive updates about payments." msgstr "" -#: assets/build/settings.js:76731 -#: assets/build/settings.js:69157 -msgid "Multiple choice" +#: assets/build/settings.js:172 +msgid "Stripe Dashboard" msgstr "" -#: assets/build/settings.js:76733 -#: assets/build/settings.js:69159 -msgid "Consent" +#: assets/build/settings.js:172 +msgid "Creatingโ€ฆ" msgstr "" -#: assets/build/settings.js:76859 -#: assets/build/settings.js:69241 -msgid "Tuesday" +#: assets/build/settings.js:172 +msgid "Create Webhook" msgstr "" -#: assets/build/settings.js:76862 -#: assets/build/settings.js:69242 -msgid "Wednesday" +#: assets/build/settings.js:172 +msgid "Left ($100)" msgstr "" -#: assets/build/settings.js:76865 -#: assets/build/settings.js:69243 -msgid "Thursday" +#: assets/build/settings.js:172 +msgid "Right (100$)" msgstr "" -#: assets/build/settings.js:76868 -#: assets/build/settings.js:69244 -msgid "Friday" +#: assets/build/settings.js:172 +msgid "Left Space ($ 100)" msgstr "" -#: assets/build/settings.js:76871 -#: assets/build/settings.js:69245 -msgid "Saturday" +#: assets/build/settings.js:172 +msgid "Right Space (100 $)" msgstr "" -#: assets/build/settings.js:76874 -#: assets/build/settings.js:69246 -msgid "Sunday" +#: assets/build/settings.js:172 +msgid "Select Currency" msgstr "" -#: assets/build/settings.js:76900 -#: assets/build/settings.js:69268 -msgid "Enable email summaries" +#: assets/build/settings.js:172 +msgid "Select the default currency for payment forms." msgstr "" -#: assets/build/settings.js:76964 -#: assets/build/settings.js:69333 -msgid "Test Email" +#: assets/build/settings.js:172 +msgid "Test mode allows you to process payments without real charges. Switch to Live mode for actual transactions." msgstr "" -#: assets/build/settings.js:76971 -#: assets/build/settings.js:69350 -msgid "Schedule Reports" +#: assets/build/settings.js:172 +msgid "Currency Sign Position" msgstr "" -#: assets/build/settings.js:76994 -#: assets/build/settings.js:69383 -msgid "Enable IP logging" +#: assets/build/settings.js:172 +msgid "Select the position of the currency symbol relative to the amount." msgstr "" -#: assets/build/settings.js:76995 -#: assets/build/settings.js:69384 -msgid "If this option is turned on, the user's IP address will be saved with the form data" +#: assets/build/settings.js:172 +msgid "General Payment Settings" msgstr "" -#: assets/build/settings.js:77020 -#: assets/build/settings.js:69419 -msgid "Enable Admin Notification" +#: assets/build/settings.js:172 +msgid "These settings apply to all payment gateways." msgstr "" -#: assets/build/settings.js:77021 -#: assets/build/settings.js:69420 -msgid "Admin notifications keep you informed about new form entries since your last visit." +#: assets/build/settings.js:172 +msgid "Successfully connected to Stripe!" msgstr "" -#: assets/build/settings.js:77033 -#: assets/build/settings.js:69438 -msgid "Turn on Admin Notification from here." +#: assets/build/settings.js:172 +msgid "Invalid response from server. Please try again." msgstr "" -#: assets/build/settings.js:77048 -#: assets/build/settings.js:69463 -msgid "Help shape the future of SureForms" +#: assets/build/settings.js:172 +msgid "Failed to connect to Stripe." msgstr "" -#: assets/build/settings.js:77049 -#: assets/build/settings.js:69467 -msgid "Collect non-sensitive information from your website, such as the PHP version and features used, to help us fix bugs faster, make smarter decisions, and build features that actually matter to you. " +#: assets/build/settings.js:172 +msgid "Failed to disconnect Stripe account." msgstr "" -#: assets/build/settings.js:77104 -#: assets/build/settings.js:69533 -msgid "Email Summaries" +#: assets/build/settings.js:172 +msgid "Stripe account disconnected successfully." msgstr "" -#: assets/build/settings.js:77111 -#: assets/build/settings.js:69543 -msgid "IP Logging" +#: assets/build/settings.js:172 +msgid "Webhook created successfully!" msgstr "" -#: assets/build/settings.js:77126 -#: assets/build/settings.js:69564 -msgid "Anonymous Analytics" +#: assets/build/settings.js:172 +msgid "Failed to create webhook." msgstr "" -#: assets/build/settings.js:77625 -#: assets/build/settings.js:70137 -msgid "Enable Google Address Autocomplete" +#: assets/build/settings.js:172 +msgid "Connection Status" msgstr "" -#: assets/build/settings.js:77626 -#: assets/build/settings.js:70141 -msgid "Upgrade to the SureForms Business Plan to add Google-powered address autocomplete with interactive map preview to your forms." +#: assets/build/settings.js:172 +msgid "Disconnect Stripe Account" msgstr "" -#: assets/build/settings.js:77627 -#: assets/build/settings.js:70146 -msgid "Auto-suggest addresses as users type for faster, error-free submissions" +#: assets/build/settings.js:172 +msgid "Are you sure you want to disconnect your Stripe account? This will stop all active payments, subscriptions, and form transactions connected to this account." msgstr "" -#: assets/build/settings.js:77627 -#: assets/build/settings.js:70150 -msgid "Show an interactive map preview with draggable pin for precise locations" +#: assets/build/settings.js:172 +msgid "Disconnect" msgstr "" -#: assets/build/settings.js:77627 -#: assets/build/settings.js:70154 -msgid "Automatically populate address fields like city, state, and postal code" +#: assets/build/settings.js:172 +msgid "Disconnectingโ€ฆ" msgstr "" -#: assets/build/settings.js:77670 -#: assets/build/settings.js:70202 -msgid "Unlock powerful integrations in the Premium plan to automate your workflows and connect SureForms directly with your favourite tools." +#: assets/build/settings.js:172 +msgid "Webhook successfully connected, all Stripe events are being tracked." msgstr "" -#: assets/build/settings.js:77671 -#: assets/build/settings.js:70207 -msgid "Send form submissions straight to CRMs, email, and marketing platforms" +#: assets/build/settings.js:172 +msgid "Connect your Stripe account to start accepting payments through your forms." msgstr "" -#: assets/build/settings.js:77671 -#: assets/build/settings.js:70211 -msgid "Automate repetitive tasks with seamless data syncing" +#: assets/build/settings.js:172 +msgid "Connect to Stripe" msgstr "" -#: assets/build/settings.js:77671 -#: assets/build/settings.js:70215 -msgid "Access exclusive native integrations for faster workflows" +#: assets/build/settings.js:172 +msgid "Securely connect to Stripe with just a few clicks to begin accepting payments! " msgstr "" -#: assets/build/settings.js:77752 -#: assets/build/settings.js:70275 +#: assets/build/settings.js:172 +msgid "Stripe Settings" +msgstr "" + +#: assets/build/settings.js:172 msgid "Copy to clipboard" msgstr "" -#: assets/build/settings.js:77757 -#: assets/build/settings.js:70282 +#: assets/build/settings.js:172 msgid "Claude Desktop" msgstr "" -#: assets/build/settings.js:77758 -#: assets/build/settings.js:70283 +#: assets/build/settings.js:172 msgid "~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\\Claude\\claude_desktop_config.json (Windows)" msgstr "" -#: assets/build/settings.js:77763 -#: assets/build/settings.js:70292 +#: assets/build/settings.js:172 msgid "Claude Code" msgstr "" -#: assets/build/settings.js:77764 -#: assets/build/settings.js:70293 +#: assets/build/settings.js:172 msgid ".mcp.json (project) or ~/.claude.json (global)" msgstr "" -#: assets/build/settings.js:77770 -#: assets/build/settings.js:70304 +#: assets/build/settings.js:172 msgid "Cursor" msgstr "" -#: assets/build/settings.js:77771 -#: assets/build/settings.js:70305 +#: assets/build/settings.js:172 msgid "~/.cursor/mcp.json" msgstr "" -#: assets/build/settings.js:77776 -#: assets/build/settings.js:70311 +#: assets/build/settings.js:172 msgid "VS Code (Copilot)" msgstr "" -#: assets/build/settings.js:77777 -#: assets/build/settings.js:70312 +#: assets/build/settings.js:172 msgid ".vscode/mcp.json (project) or settings.json > mcp.servers (global)" msgstr "" -#: assets/build/settings.js:77783 -#: assets/build/settings.js:70323 +#: assets/build/settings.js:172 msgid "~/.continue/config.yaml or config.json" msgstr "" -#: assets/build/settings.js:77790 -#: assets/build/settings.js:70331 +#: assets/build/settings.js:172 msgid "Your client's MCP configuration file" msgstr "" -#: assets/build/settings.js:77838 -#: assets/build/settings.js:78090 -#: assets/build/settings.js:70384 -#: assets/build/settings.js:70779 +#: assets/build/settings.js:172 msgid "Connect Your AI Client" msgstr "" -#: assets/build/settings.js:77845 -#: assets/build/settings.js:70392 +#: assets/build/settings.js:172 msgid "AI Client" msgstr "" -#: assets/build/settings.js:77861 -#: assets/build/settings.js:70410 +#: assets/build/settings.js:172 msgid "Create an Application Password โ€” " msgstr "" -#: assets/build/settings.js:77866 -#: assets/build/settings.js:70417 +#: assets/build/settings.js:172 msgid "Open Application Passwords" msgstr "" -#: assets/build/settings.js:77866 -#: assets/build/settings.js:70422 +#: assets/build/settings.js:172 msgid "Or use this CLI command to add the server quickly (you will still need to set the environment variables):" msgstr "" -#: assets/build/settings.js:77876 -#: assets/build/settings.js:70441 +#: assets/build/settings.js:172 msgid "Copy the JSON config below into: " msgstr "" -#: assets/build/settings.js:77878 -#: assets/build/settings.js:70447 +#: assets/build/settings.js:172 msgid "Replace \"your-application-password\" with the password from Step 1." msgstr "" -#: assets/build/settings.js:77890 -#: assets/build/settings.js:70466 +#: assets/build/settings.js:172 msgid "WP_API_URL โ€” your site's MCP endpoint. WP_API_USERNAME โ€” your WordPress username. WP_API_PASSWORD โ€” the application password you generated." msgstr "" -#: assets/build/settings.js:77895 -#: assets/build/settings.js:70476 +#: assets/build/settings.js:172 msgid "View setup docs" msgstr "" -#: assets/build/settings.js:77952 -#: assets/build/settings.js:70521 +#: assets/build/settings.js:172 msgid "The MCP Adapter plugin is installed but not active. Activate it to configure MCP settings." msgstr "" -#: assets/build/settings.js:77952 -#: assets/build/settings.js:70525 +#: assets/build/settings.js:172 msgid "The MCP Adapter plugin is required to connect AI clients to your forms. Download and install it from GitHub, then activate it." msgstr "" -#: assets/build/settings.js:77954 -#: assets/build/settings.js:70533 +#: assets/build/settings.js:172 msgid "Download the latest release from" msgstr "" -#: assets/build/settings.js:77959 -#: assets/build/settings.js:70548 +#: assets/build/settings.js:172 msgid "Install the plugin via Plugins > Add New Plugin > Upload Plugin." msgstr "" -#: assets/build/settings.js:77959 -#: assets/build/settings.js:70554 +#: assets/build/settings.js:172 msgid "Activate the MCP Adapter plugin." msgstr "" -#: assets/build/settings.js:77967 -#: assets/build/settings.js:70571 +#: assets/build/settings.js:172 msgid "Activatingโ€ฆ" msgstr "" -#: assets/build/settings.js:77967 -#: assets/build/settings.js:70572 +#: assets/build/settings.js:172 msgid "Activate MCP Adapter" msgstr "" -#: assets/build/settings.js:77979 -#: assets/build/settings.js:70587 +#: assets/build/settings.js:172 msgid "Download MCP Adapter" msgstr "" -#: assets/build/settings.js:77992 -#: assets/build/settings.js:70605 +#: assets/build/settings.js:172 +msgid "Experimental" +msgstr "" + +#: assets/build/settings.js:172 +msgid "Enable Abilities" +msgstr "" + +#: assets/build/settings.js:172 +msgid "Register SureForms abilities with the WordPress Abilities API. When enabled, AI clients can list, read, create, edit, and delete your forms and entries. When disabled, no abilities are registered and AI clients cannot perform any actions on your forms." +msgstr "" + +#: assets/build/settings.js:172 +msgid "Abilities API โ€” Edit" +msgstr "" + +#: assets/build/settings.js:172 msgid "Enable Edit Abilities" msgstr "" -#: assets/build/settings.js:77993 -#: assets/build/settings.js:70606 +#: assets/build/settings.js:172 msgid "When enabled, AI clients can create new forms, update form titles, fields, and settings, duplicate forms, and modify entry statuses. When disabled, these abilities are unregistered and AI clients can only read your data." msgstr "" -#: assets/build/settings.js:78004 -#: assets/build/settings.js:70627 +#: assets/build/settings.js:172 +msgid "Abilities API โ€” Delete" +msgstr "" + +#: assets/build/settings.js:172 msgid "Enable Delete Abilities" msgstr "" -#: assets/build/settings.js:78005 -#: assets/build/settings.js:70628 +#: assets/build/settings.js:172 msgid "When enabled, AI clients can permanently delete forms and entries. Deleted data cannot be recovered. When disabled, delete abilities are unregistered and AI clients cannot remove any data." msgstr "" -#: assets/build/settings.js:78016 -#: assets/build/settings.js:70650 +#: assets/build/settings.js:172 +msgid "MCP Server" +msgstr "" + +#: assets/build/settings.js:172 msgid "Enable MCP Server" msgstr "" -#: assets/build/settings.js:78017 -#: assets/build/settings.js:70654 +#: assets/build/settings.js:172 msgid "Creates a dedicated SureForms MCP endpoint that AI clients like Claude can connect to. When disabled, the endpoint is removed and external AI clients cannot discover or call any SureForms abilities." msgstr "" -#: assets/build/settings.js:78022 -#: assets/build/settings.js:70664 +#: assets/build/settings.js:172 msgid "Learn more" msgstr "" -#: assets/build/settings.js:78032 -#: assets/build/settings.js:70685 -msgid "Experimental" +#: assets/build/settings.js:172 +msgid "MCP Adapter Required" msgstr "" -#: assets/build/settings.js:78040 -#: assets/build/settings.js:78068 -#: assets/build/settings.js:70695 -#: assets/build/settings.js:70738 -msgid "Enable Abilities" +#: assets/build/settings.js:172 +msgid "No supported form plugins are active on this site. Activate one (such as Contact Form 7) with at least one form to import it into SureForms." msgstr "" -#: assets/build/settings.js:78041 -#: assets/build/settings.js:70696 -msgid "Register SureForms abilities with the WordPress Abilities API. When enabled, AI clients can list, read, create, edit, and delete your forms and entries. When disabled, no abilities are registered and AI clients cannot perform any actions on your forms." +#: assets/build/settings.js:172 +msgid "Plugin" msgstr "" -#: assets/build/settings.js:78056 -#: assets/build/settings.js:70720 -msgid "MCP Adapter Required" +#: assets/build/settings.js:172 +#, js-format +msgid "%d form" +msgid_plural "%d forms" +msgstr[0] "" +msgstr[1] "" + +#: assets/build/settings.js:172 +msgid "No forms" msgstr "" -#: assets/build/settings.js:78074 -#: assets/build/settings.js:70750 -msgid "Abilities API โ€” Edit" +#: assets/build/settings.js:172 +msgid "Update existing" msgstr "" -#: assets/build/settings.js:78080 -#: assets/build/settings.js:70760 -msgid "Abilities API โ€” Delete" +#: assets/build/settings.js:172 +msgid "Create a new copy" msgstr "" -#: assets/build/settings.js:78086 -#: assets/build/settings.js:70770 -msgid "MCP Server" +#: assets/build/settings.js:172 +msgid "Could not load forms for this source." msgstr "" -#: assets/build/settings.js:78548 -#: assets/build/settings.js:71279 -msgid "Required Error Messages" +#: assets/build/settings.js:172 +msgid "(untitled form)" msgstr "" -#: assets/build/settings.js:78551 -#: assets/build/settings.js:71283 -msgid "Other Error Messages" +#: assets/build/settings.js:172 +msgid "Previously imported" msgstr "" -#: assets/build/settings.js:78565 -#: assets/build/settings.js:71301 -msgid "Input Field Unique" +#: assets/build/settings.js:172 +msgid "Open existing SureForms form in a new tab" msgstr "" -#: assets/build/settings.js:78568 -#: assets/build/settings.js:71305 -msgid "Email Field Unique" +#: assets/build/settings.js:172 +msgid "On re-import" msgstr "" -#: assets/build/settings.js:78571 -#: assets/build/settings.js:71309 -msgid "Invalid URL" +#: assets/build/settings.js:172 +msgid "No forms found in this plugin." msgstr "" -#: assets/build/settings.js:78574 -#: assets/build/settings.js:71313 -msgid "Phone Field Unique" +#: assets/build/settings.js:172 +#, js-format +msgid "%1$d of %2$d form selected" +msgid_plural "%1$d of %2$d forms selected" +msgstr[0] "" +msgstr[1] "" + +#: assets/build/settings.js:172 +msgid "Preview update" msgstr "" -#: assets/build/settings.js:78577 -#: assets/build/settings.js:71317 -msgid "Invalid Field Number Block" +#: assets/build/settings.js:172 +msgid "Preview import" msgstr "" -#: assets/build/settings.js:78580 -#: assets/build/settings.js:71321 -msgid "Confirmation Email Mismatch Message" +#: assets/build/settings.js:172 +msgid "Multiple choice" msgstr "" -#: assets/build/settings.js:78583 -#: assets/build/settings.js:71328 -msgid "Invalid Email" +#: assets/build/settings.js:172 +msgid "Consent" msgstr "" -#: assets/build/settings.js:78586 -#: assets/build/settings.js:71332 -msgid "Number Minimum Value" +#: assets/build/settings.js:172 +msgid "Could not generate the import preview." msgstr "" -#. Translators: %s represents the minimum input value. -#: assets/build/settings.js:78588 -#: assets/build/settings.js:71334 -#, js-format -msgid "%s represents the minimum input value. For example: \"Minimum value is 10.\"" +#: assets/build/settings.js:172 +msgid "Import failed. Please try again or check your error logs." msgstr "" -#: assets/build/settings.js:78591 -#: assets/build/settings.js:71341 -msgid "Number Maximum Value" +#: assets/build/settings.js:172 +msgid "Go back" msgstr "" -#. Translators: %s represents the maximum input value. -#: assets/build/settings.js:78593 -#: assets/build/settings.js:71343 -#, js-format -msgid "%s represents the maximum input value. For example: \"Maximum value is 100.\"" +#: assets/build/settings.js:172 +msgid "Update & import" msgstr "" -#: assets/build/settings.js:78596 -#: assets/build/settings.js:71350 -msgid "Dropdown Minimum Selections" +#: assets/build/settings.js:172 +msgid "Confirm & import" msgstr "" -#. Translators: %s represents the minimum input length. -#: assets/build/settings.js:78598 -#: assets/build/settings.js:71352 +#: assets/build/settings.js:172 #, js-format -msgid "%s represents the minimum selections needed. For example: โ€œMinimum 2 selections are required.โ€" +msgid "Form #%s" msgstr "" -#: assets/build/settings.js:78601 -#: assets/build/settings.js:71359 -msgid "Dropdown Maximum Selections" +#: assets/build/settings.js:172 +#, js-format +msgid "%d field will import" +msgid_plural "%d fields will import" +msgstr[0] "" +msgstr[1] "" + +#: assets/build/settings.js:172 +msgid "Some fields can't be migrated yet" msgstr "" -#. Translators: %s represents the maximum input length. -#: assets/build/settings.js:78603 -#: assets/build/settings.js:71361 -#, js-format -msgid "%s represents the maximum selections allowed. For example: โ€œMaximum 4 selections are allowed.โ€" +#: assets/build/settings.js:172 +msgid "These fields will be skipped - add them manually after the form is created:" msgstr "" -#: assets/build/settings.js:78606 -#: assets/build/settings.js:71368 -msgid "Multiple Choice Minimum Selections" +#: assets/build/settings.js:172 +msgid "Some forms could not be parsed" msgstr "" -#. Translators: %s represents the minimum input length. -#: assets/build/settings.js:78608 -#: assets/build/settings.js:71373 -#, js-format -msgid "%s represents the minimum choices needed. For example: โ€œMinimum 1 selection is required.โ€" +#: assets/build/settings.js:172 +msgid "Migration complete" msgstr "" -#: assets/build/settings.js:78611 -#: assets/build/settings.js:71380 -msgid "Multiple Choice Maximum Selections" +#: assets/build/settings.js:172 +msgid "Nothing was imported" msgstr "" -#. Translators: %s represents the maximum input length. -#: assets/build/settings.js:78613 -#: assets/build/settings.js:71385 +#: assets/build/settings.js:172 #, js-format -msgid "%s represents the maximum choices allowed. For example: โ€œMaximum 3 selections are allowed.โ€" +msgid "%d form was imported into SureForms." +msgid_plural "%d forms were imported into SureForms." +msgstr[0] "" +msgstr[1] "" + +#: assets/build/settings.js:172 +msgid "None of the selected forms could be migrated. See the warnings below for details." msgstr "" -#: assets/build/settings.js:78617 -#: assets/build/settings.js:71398 -msgid "Input Field" +#: assets/build/settings.js:172 +msgid "Imported forms" msgstr "" -#: assets/build/settings.js:78620 -#: assets/build/settings.js:71402 -msgid "Email Field" +#: assets/build/settings.js:172 +msgid "Edit in SureForms" msgstr "" -#: assets/build/settings.js:78623 -#: assets/build/settings.js:78666 -#: assets/build/settings.js:71406 -#: assets/build/settings.js:71466 -msgid "URL Field" +#: assets/build/settings.js:172 +msgid "Some fields were skipped during import" msgstr "" -#: assets/build/settings.js:78626 -#: assets/build/settings.js:71410 -msgid "Phone Field" +#: assets/build/settings.js:172 +msgid "Add these manually in the form editor - they have no SureForms equivalent yet:" msgstr "" -#: assets/build/settings.js:78629 -#: assets/build/settings.js:78666 -#: assets/build/settings.js:71414 -#: assets/build/settings.js:71464 -msgid "Textarea Field" +#: assets/build/settings.js:172 +msgid "Some forms failed to import" msgstr "" -#: assets/build/settings.js:78632 -#: assets/build/settings.js:71418 -msgid "Checkbox Field" +#: assets/build/settings.js:172 +msgid "Import more forms" msgstr "" -#: assets/build/settings.js:78635 -#: assets/build/settings.js:71422 -msgid "Dropdown Field" +#: assets/build/settings.js:172 +msgid "Could not load the list of importable plugins." msgstr "" -#: assets/build/settings.js:78638 -#: assets/build/settings.js:71426 -msgid "Multiple Choice Field" +#: assets/build/settings.js:172 +msgid "Failed to load settings. Please refresh and try again." msgstr "" -#: assets/build/settings.js:78641 -#: assets/build/settings.js:71430 -msgid "Address Field" +#: assets/build/settings.js:172 +msgid "Form Validation fields cannot be left blank." msgstr "" -#: assets/build/settings.js:78644 -#: assets/build/settings.js:71434 -msgid "Number Field" +#: assets/build/settings.js:172 +msgid "Recipient email is required when email summaries are enabled." msgstr "" -#: assets/build/settings.js:78666 -#: assets/build/settings.js:71467 -msgid " Error Message" +#: assets/build/settings.js:172 +msgid "Please enter a valid recipient email." msgstr "" -#: assets/build/settings.js:78719 -#: assets/build/settings.js:71542 -msgid "Validations" +#: assets/build/settings.js:172 +msgid "Settings saved." +msgstr "" + +#: assets/build/settings.js:172 +msgid "Failed to save settings." +msgstr "" + +#: assets/build/settings.js:172 +msgid "Some settings failed to save. Please retry." +msgstr "" + +#: assets/build/settings.js:172 +msgid "Some fields have unsaved changes. Discard them to continue, or stay to save your edits." +msgstr "" + +#: assets/build/settings.js:172 +msgid "Discard & switch" msgstr "" #: assets/build/suremail.js:2 @@ -20476,6 +17863,14 @@ msgstr "" msgid "Collect feedback, run polls, and visualize results. Upgrade to SureForms to unlock survey capabilities:" msgstr "" +#: assets/build/templatePicker.js:172 +msgid "You do not have permission to create forms." +msgstr "" + +#: assets/build/templatePicker.js:172 +msgid "The form could not be saved. Please try again." +msgstr "" + #: assets/build/templatePicker.js:172 msgid "Generate with AI" msgstr "" diff --git a/modules/gutenberg/package.json b/modules/gutenberg/package.json index bce43f3b4..f9acb8461 100644 --- a/modules/gutenberg/package.json +++ b/modules/gutenberg/package.json @@ -66,6 +66,6 @@ "webpack": "^5.89.0" }, "volta": { - "node": "18.15.0" + "node": "24.16.0" } } diff --git a/package-lock.json b/package-lock.json index 672deb389..6a9b27b39 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "sureforms", - "version": "2.11.0", + "version": "2.11.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "sureforms", - "version": "2.11.0", + "version": "2.11.1", "license": "GPL", "dependencies": { "@bsf/force-ui": "git+https://github.com/brainstormforce/bsf-admin-ui#v1.7.7", @@ -24,8 +24,8 @@ "clsx": "^2.1.1", "cssnano": "^6.0.1", "date-fns": "^4.1.0", - "dompurify": "^3.3.0", - "gpt-po": "1.1.1", + "dompurify": "^3.3.3", + "gpt-po": "1.3.0", "html-react-parser": "^5.0.7", "intl-tel-input": "^25.14.0", "lucide-react": "^0.475.0", @@ -1865,11 +1865,12 @@ } }, "node_modules/@babel/runtime": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.7.2.tgz", - "integrity": "sha512-JONRbXbTXc9WQE2mAZd1p0Z3DZ/6vaQIkgYMSTP3KjRCyd7rCZCcfhCyX+YjwcKxcZ82UrxbRD358bpExNgrjw==", - "dependencies": { - "regenerator-runtime": "^0.13.2" + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz", + "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" } }, "node_modules/@babel/template": { @@ -2033,14 +2034,6 @@ "stylis": "4.2.0" } }, - "node_modules/@emotion/babel-plugin/node_modules/@babel/runtime": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.1.tgz", - "integrity": "sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==", - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@emotion/babel-plugin/node_modules/convert-source-map": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", @@ -2113,14 +2106,6 @@ } } }, - "node_modules/@emotion/react/node_modules/@babel/runtime": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.1.tgz", - "integrity": "sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==", - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@emotion/serialize": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.3.tgz", @@ -2465,6 +2450,30 @@ "react": ">=16.3" } }, + "node_modules/@google/genai": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@google/genai/-/genai-2.8.0.tgz", + "integrity": "sha512-pc2ayxqO5+O7AvnHBqpNHIk7PAZkHZgL31tbyx0gJZBSS9qPYiQoqwK7oYOw/ePmG6QY4EMSu+304vD5QlhXAw==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "google-auth-library": "^10.3.0", + "p-retry": "^4.6.2", + "protobufjs": "^7.5.4", + "ws": "^8.18.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "@modelcontextprotocol/sdk": "^1.25.2" + }, + "peerDependenciesMeta": { + "@modelcontextprotocol/sdk": { + "optional": true + } + } + }, "node_modules/@hapi/hoek": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", @@ -3857,6 +3866,63 @@ "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==", "dev": true }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.5.tgz", + "integrity": "sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.1.tgz", + "integrity": "sha512-vW1GmwMZNnL+gMRaovlh9yZX74kc+TTU3FObkkurpMaRtBfLP3ldjS9KQWlwZgraRE0+dheEEoAxdzcJQ8eXZg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.1.tgz", + "integrity": "sha512-GpptLrs57adMSuHi3VNj0mAF8dwh36LMaYF6XyJ6JMWlVsc+t42tm1HSEDmOs3A8fC9yyeisgLhsTVQokOZ0zw==", + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.1.tgz", + "integrity": "sha512-oOAWABowe8EAbMyWKM0tYDKi8Yaox52D+HWZhAIJqQXbqe0xI/GV7FhLWqlEKreMkfDjshR5FKgi3mnle0h6Eg==", + "license": "BSD-3-Clause" + }, "node_modules/@puppeteer/browsers": { "version": "2.10.4", "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.10.4.tgz", @@ -4131,6 +4197,12 @@ "@sinonjs/commons": "^3.0.0" } }, + "node_modules/@stablelib/base64": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/base64/-/base64-1.0.1.tgz", + "integrity": "sha512-1bnPQqSxSuc3Ii6MhBysoWCg58j97aUjuCSZrGSmDxNqtytIi0k8utUenAwTZN4V5mXXYGsVUI9zeBqy+jBOSQ==", + "license": "MIT" + }, "node_modules/@svgr/babel-plugin-add-jsx-attribute": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", @@ -4831,7 +4903,6 @@ "version": "25.5.0", "resolved": "https://registry.npmjs.org/@types/node/-/node-25.5.0.tgz", "integrity": "sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw==", - "dev": true, "dependencies": { "undici-types": "~7.18.0" } @@ -4929,8 +5000,7 @@ "node_modules/@types/retry": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", - "dev": true + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==" }, "node_modules/@types/semver": { "version": "7.7.0", @@ -5546,14 +5616,6 @@ "node": ">=12" } }, - "node_modules/@wordpress/api-fetch/node_modules/@babel/runtime": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.1.tgz", - "integrity": "sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==", - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@wordpress/babel-plugin-import-jsx-pragma": { "version": "4.41.0", "resolved": "https://registry.npmjs.org/@wordpress/babel-plugin-import-jsx-pragma/-/babel-plugin-import-jsx-pragma-4.41.0.tgz", @@ -5589,15 +5651,6 @@ "node": ">=14" } }, - "node_modules/@wordpress/babel-preset-default/node_modules/@babel/runtime": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.1.tgz", - "integrity": "sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@wordpress/base-styles": { "version": "4.49.0", "resolved": "https://registry.npmjs.org/@wordpress/base-styles/-/base-styles-4.49.0.tgz", @@ -5772,14 +5825,6 @@ "node": ">=12" } }, - "node_modules/@wordpress/element/node_modules/@babel/runtime": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.1.tgz", - "integrity": "sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==", - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@wordpress/env": { "version": "10.23.0", "resolved": "https://registry.npmjs.org/@wordpress/env/-/env-10.23.0.tgz", @@ -6148,14 +6193,6 @@ "node": ">=12" } }, - "node_modules/@wordpress/escape-html/node_modules/@babel/runtime": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.1.tgz", - "integrity": "sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==", - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@wordpress/eslint-plugin": { "version": "17.13.0", "resolved": "https://registry.npmjs.org/@wordpress/eslint-plugin/-/eslint-plugin-17.13.0.tgz", @@ -6262,14 +6299,6 @@ "node": ">=12" } }, - "node_modules/@wordpress/hooks/node_modules/@babel/runtime": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.1.tgz", - "integrity": "sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==", - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@wordpress/i18n": { "version": "4.58.0", "resolved": "https://registry.npmjs.org/@wordpress/i18n/-/i18n-4.58.0.tgz", @@ -6289,14 +6318,6 @@ "node": ">=12" } }, - "node_modules/@wordpress/i18n/node_modules/@babel/runtime": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.1.tgz", - "integrity": "sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==", - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@wordpress/icons": { "version": "9.49.0", "resolved": "https://registry.npmjs.org/@wordpress/icons/-/icons-9.49.0.tgz", @@ -6310,14 +6331,6 @@ "node": ">=12" } }, - "node_modules/@wordpress/icons/node_modules/@babel/runtime": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.1.tgz", - "integrity": "sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==", - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@wordpress/jest-console": { "version": "7.29.0", "resolved": "https://registry.npmjs.org/@wordpress/jest-console/-/jest-console-7.29.0.tgz", @@ -6334,15 +6347,6 @@ "jest": ">=29" } }, - "node_modules/@wordpress/jest-console/node_modules/@babel/runtime": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.1.tgz", - "integrity": "sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@wordpress/jest-preset-default": { "version": "11.29.0", "resolved": "https://registry.npmjs.org/@wordpress/jest-preset-default/-/jest-preset-default-11.29.0.tgz", @@ -6479,14 +6483,6 @@ "node": ">=12" } }, - "node_modules/@wordpress/primitives/node_modules/@babel/runtime": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.1.tgz", - "integrity": "sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==", - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@wordpress/scripts": { "version": "26.19.0", "resolved": "https://registry.npmjs.org/@wordpress/scripts/-/scripts-26.19.0.tgz", @@ -6565,15 +6561,6 @@ "react-dom": "^18.0.0" } }, - "node_modules/@wordpress/scripts/node_modules/@babel/runtime": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.1.tgz", - "integrity": "sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@wordpress/scripts/node_modules/@puppeteer/browsers": { "version": "1.4.6", "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-1.4.6.tgz", @@ -7491,14 +7478,6 @@ "node": ">=12" } }, - "node_modules/@wordpress/url/node_modules/@babel/runtime": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.1.tgz", - "integrity": "sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==", - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@wordpress/warning": { "version": "2.58.0", "resolved": "https://registry.npmjs.org/@wordpress/warning/-/warning-2.58.0.tgz", @@ -7532,17 +7511,6 @@ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" - } - }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -8112,7 +8080,8 @@ "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true }, "node_modules/autoprefixer": { "version": "10.4.21", @@ -8399,14 +8368,6 @@ "npm": ">=6" } }, - "node_modules/babel-plugin-macros/node_modules/@babel/runtime": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.1.tgz", - "integrity": "sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==", - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/babel-plugin-macros/node_modules/cosmiconfig": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", @@ -8618,6 +8579,15 @@ "node": "*" } }, + "node_modules/bignumber.js": { + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz", + "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==", + "license": "MIT", + "engines": { + "node": "*" + } + }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", @@ -8815,6 +8785,12 @@ "node": "*" } }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "license": "BSD-3-Clause" + }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -9415,6 +9391,7 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, "dependencies": { "delayed-stream": "~1.0.0" }, @@ -9426,7 +9403,6 @@ "version": "12.1.0", "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", - "dev": true, "engines": { "node": ">=18" } @@ -10751,6 +10727,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, "engines": { "node": ">=0.4.0" } @@ -10900,14 +10877,6 @@ "csstype": "^3.0.2" } }, - "node_modules/dom-helpers/node_modules/@babel/runtime": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.1.tgz", - "integrity": "sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==", - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/dom-serializer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", @@ -11024,6 +10993,15 @@ "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -11302,6 +11280,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", @@ -12239,14 +12218,6 @@ "node": ">= 0.6" } }, - "node_modules/event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", - "engines": { - "node": ">=6" - } - }, "node_modules/eventemitter2": { "version": "0.4.14", "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", @@ -12261,6 +12232,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, "engines": { "node": ">=0.8.x" } @@ -12580,6 +12552,12 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, + "node_modules/fast-sha256": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-sha256/-/fast-sha256-1.3.0.tgz", + "integrity": "sha512-n11RGP/lrWEFI/bWdygLxhI+pVeo1ZYIVwvvPkW7azl/rOy+F3HYRZ2K5zeE9mmkhQppyv9sQFx0JM9UabnpPQ==", + "license": "Unlicense" + }, "node_modules/fast-uri": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", @@ -12643,6 +12621,29 @@ "pend": "~1.2.0" } }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, "node_modules/figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -12956,6 +12957,7 @@ "version": "1.15.9", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "dev": true, "funding": [ { "type": "individual", @@ -13081,6 +13083,7 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==", + "dev": true, "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -13091,6 +13094,18 @@ "node": ">= 6" } }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "license": "MIT", + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -13222,6 +13237,83 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/gaxios": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.1.5.tgz", + "integrity": "sha512-5FZy72Rh8LhtjmvDrKkI+lVhrsQrVKVsItxMoDm5mNQE+xR0WVIIs+jzPSJgBvKVsLi24fZhXJIsNI0bihDzFg==", + "license": "Apache-2.0", + "dependencies": { + "extend": "^3.0.2", + "https-proxy-agent": "^7.0.1", + "node-fetch": "^3.3.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/gaxios/node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/gaxios/node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/gaxios/node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/gaxios/node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "license": "MIT", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, + "node_modules/gcp-metadata": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-8.1.2.tgz", + "integrity": "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==", + "license": "Apache-2.0", + "dependencies": { + "gaxios": "^7.0.0", + "google-logging-utils": "^1.0.0", + "json-bigint": "^1.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -13535,6 +13627,32 @@ "csstype": "^3.0.10" } }, + "node_modules/google-auth-library": { + "version": "10.7.0", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.7.0.tgz", + "integrity": "sha512-QpTAbNJ36TliZLx3TTtahR8HG0hN9RllL1e3FymOvQSIKK8JmgV58H924ub2wa2DsS3ANjjP1Aw1N+Ramc8hqQ==", + "license": "Apache-2.0", + "dependencies": { + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "gaxios": "^7.1.4", + "gcp-metadata": "8.1.2", + "google-logging-utils": "1.1.3", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/google-logging-utils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-1.1.3.tgz", + "integrity": "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, "node_modules/gopd": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", @@ -13572,84 +13690,74 @@ } }, "node_modules/gpt-po": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/gpt-po/-/gpt-po-1.1.1.tgz", - "integrity": "sha512-CPcR8pFt4Oh5KCJeT/hseyARMEnG7ug8FSynIWB/8gqH//oCk8RoLro2BbUTSJh6UXqA0hJJPUNdkOCi3HG0og==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/gpt-po/-/gpt-po-1.3.0.tgz", + "integrity": "sha512-xCG1DjraS0uvwrH1C1cLjh5nA7ZupyADA57lcksRtZhB20TZ0pa85NQr+ks7zfeBgYfBaUKToGb/3KwWXVMxBw==", + "license": "MIT", "dependencies": { - "commander": "^10.0.1", - "gettext-parser": "^6.0.0", - "openai": "^3.2.1" + "@anthropic-ai/sdk": "^0.99.0", + "@google/genai": "^2.6.0", + "commander": "^12.1.0", + "gettext-parser": "^9.0.1", + "openai": "^6.39.0" }, "bin": { "gpt-po": "lib/src/index.js" }, "engines": { - "node": ">=12.0.0" + "node": ">=20.0.0" } }, - "node_modules/gpt-po/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], + "node_modules/gpt-po/node_modules/@anthropic-ai/sdk": { + "version": "0.99.0", + "resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.99.0.tgz", + "integrity": "sha512-vdicFA9YjtvgpG8rxp39hqW4oxpkdRGPTq0QEts5TZhr2GkLozDduK/GiXrLQ7PzrKYBtIkQFdRW+QBjzlsABg==", + "license": "MIT", "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/gpt-po/node_modules/commander": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", - "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", - "engines": { - "node": ">=14" + "json-schema-to-ts": "^3.1.1", + "standardwebhooks": "^1.0.0" + }, + "bin": { + "anthropic-ai-sdk": "bin/cli" + }, + "peerDependencies": { + "zod": "^3.25.0 || ^4.0.0" + }, + "peerDependenciesMeta": { + "zod": { + "optional": true + } } }, "node_modules/gpt-po/node_modules/gettext-parser": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/gettext-parser/-/gettext-parser-6.0.0.tgz", - "integrity": "sha512-eWFsR78gc/eKnzDgc919Us3cbxQbzxK1L8vAIZrKMQqOUgULyeqmczNlBjTlVTk2FaB7nV9C1oobd/PGBOqNmg==", - "dependencies": { - "content-type": "^1.0.4", - "encoding": "^0.1.13", - "readable-stream": "^4.1.0", - "safe-buffer": "^5.2.1" - } - }, - "node_modules/gpt-po/node_modules/readable-stream": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", - "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/gettext-parser/-/gettext-parser-9.0.2.tgz", + "integrity": "sha512-dGvq3S1gpS6e9KzNkwgPED5xxfWk7mNYzzdi/fPdJF5qS7B+yo8El2ZQyyhJ79PyzTtHbwiqYOFsqBdzbQ0GPg==", + "license": "MIT", "dependencies": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" + "content-type": "^1.0.5", + "encoding": "^0.1.13" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=20" } }, - "node_modules/gpt-po/node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dependencies": { - "safe-buffer": "~5.2.0" + "node_modules/gpt-po/node_modules/openai": { + "version": "6.42.0", + "resolved": "https://registry.npmjs.org/openai/-/openai-6.42.0.tgz", + "integrity": "sha512-1WFEt/uXMXOLhYRNkgJWo08Y2YNvNwpVU72K7ibrWgWpNOXd4VojXLbe6SQ4bLiUQ3Y8jz4IiyVkylJCL1DtZg==", + "license": "Apache-2.0", + "peerDependencies": { + "ws": "^8.18.0", + "zod": "^3.25 || ^4.0" + }, + "peerDependenciesMeta": { + "ws": { + "optional": true + }, + "zod": { + "optional": true + } } }, "node_modules/graceful-fs": { @@ -14660,6 +14768,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, "funding": [ { "type": "github", @@ -16794,6 +16903,15 @@ "node": ">=6" } }, + "node_modules/json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "license": "MIT", + "dependencies": { + "bignumber.js": "^9.0.0" + } + }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -16805,6 +16923,19 @@ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, + "node_modules/json-schema-to-ts": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/json-schema-to-ts/-/json-schema-to-ts-3.1.1.tgz", + "integrity": "sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "ts-algebra": "^2.0.0" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -16856,6 +16987,27 @@ "node": ">=4.0" } }, + "node_modules/jwa": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", + "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", + "license": "MIT", + "dependencies": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz", + "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==", + "license": "MIT", + "dependencies": { + "jwa": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -17367,6 +17519,12 @@ "url": "https://tidelift.com/funding/github/npm/loglevel" } }, + "node_modules/long": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", + "license": "Apache-2.0" + }, "node_modules/lookup-closest-locale": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/lookup-closest-locale/-/lookup-closest-locale-6.2.0.tgz", @@ -17908,6 +18066,7 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, "engines": { "node": ">= 0.6" } @@ -17916,6 +18075,7 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, "dependencies": { "mime-db": "1.52.0" }, @@ -18232,6 +18392,26 @@ "dev": true, "optional": true }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "deprecated": "Use your platform's native DOMException instead", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "engines": { + "node": ">=10.5.0" + } + }, "node_modules/node-fetch": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", @@ -18730,23 +18910,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/openai": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/openai/-/openai-3.3.0.tgz", - "integrity": "sha512-uqxI/Au+aPRnsaQRe8CojU0eCR7I0mBiKjD3sNMzY6DaC1ZVrc85u98mtJW6voDug8fgGN+DIZmTDxTthxb7dQ==", - "dependencies": { - "axios": "^0.26.0", - "form-data": "^4.0.0" - } - }, - "node_modules/openai/node_modules/axios": { - "version": "0.26.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", - "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", - "dependencies": { - "follow-redirects": "^1.14.8" - } - }, "node_modules/opener": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", @@ -18986,7 +19149,6 @@ "version": "4.6.2", "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", - "dev": true, "dependencies": { "@types/retry": "0.12.0", "retry": "^0.13.1" @@ -20211,14 +20373,6 @@ "node": ">=6" } }, - "node_modules/process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", - "engines": { - "node": ">= 0.6.0" - } - }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -20262,6 +20416,29 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, + "node_modules/protobufjs": { + "version": "7.6.4", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.4.tgz", + "integrity": "sha512-RJJPTTpvFfHcWLkIa2JFWK4XvtSzS0yEWDmunqHXli1h3JlkbcQZXDZdcWxv+JK3Xsl5/UFDPZ0iGm7DAengYw==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.5", + "@protobufjs/eventemitter": "^1.1.1", + "@protobufjs/fetch": "^1.1.1", + "@protobufjs/float": "^1.0.2", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.1", + "@types/node": ">=13.7.0", + "long": "^5.3.2" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -20606,14 +20783,6 @@ "react-dom": "^16.8.5 || ^17.0.0 || ^18.0.0" } }, - "node_modules/react-beautiful-dnd/node_modules/@babel/runtime": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.1.tgz", - "integrity": "sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==", - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/react-day-picker": { "version": "9.6.7", "resolved": "https://registry.npmjs.org/react-day-picker/-/react-day-picker-9.6.7.tgz", @@ -20661,14 +20830,6 @@ "react": ">=16.13.1" } }, - "node_modules/react-error-boundary/node_modules/@babel/runtime": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz", - "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==", - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/react-hot-toast": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/react-hot-toast/-/react-hot-toast-2.5.2.tgz", @@ -20754,14 +20915,6 @@ } } }, - "node_modules/react-redux/node_modules/@babel/runtime": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.1.tgz", - "integrity": "sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==", - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/react-refresh": { "version": "0.14.2", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", @@ -20821,14 +20974,6 @@ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, - "node_modules/react-select/node_modules/@babel/runtime": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.1.tgz", - "integrity": "sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==", - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/react-select/node_modules/memoize-one": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", @@ -21164,14 +21309,6 @@ "@babel/runtime": "^7.9.2" } }, - "node_modules/redux/node_modules/@babel/runtime": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.1.tgz", - "integrity": "sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==", - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/reflect.getprototypeof": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", @@ -21212,11 +21349,6 @@ "node": ">=4" } }, - "node_modules/regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" - }, "node_modules/regexp.prototype.flags": { "version": "1.5.4", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", @@ -21439,7 +21571,6 @@ "version": "0.13.1", "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", - "dev": true, "engines": { "node": ">= 4" } @@ -22652,6 +22783,16 @@ "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==", "dev": true }, + "node_modules/standardwebhooks": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/standardwebhooks/-/standardwebhooks-1.0.0.tgz", + "integrity": "sha512-BbHGOQK9olHPMvQNHWul6MYlrRTAOKn03rOe4A8O3CLWhNf4YHBqq2HJKKC+sfqpxiBY52pNeesD6jIiLDz8jg==", + "license": "MIT", + "dependencies": { + "@stablelib/base64": "^1.0.0", + "fast-sha256": "^1.3.0" + } + }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -23906,6 +24047,12 @@ "node": ">=0.8.0" } }, + "node_modules/ts-algebra": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ts-algebra/-/ts-algebra-2.0.0.tgz", + "integrity": "sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw==", + "license": "MIT" + }, "node_modules/ts-api-utils": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", @@ -24206,8 +24353,7 @@ "node_modules/undici-types": { "version": "7.18.2", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz", - "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", - "dev": true + "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==" }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.1", @@ -24602,6 +24748,15 @@ "defaults": "^1.0.3" } }, + "node_modules/web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, "node_modules/web-vitals": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-4.2.4.tgz", @@ -25250,7 +25405,6 @@ "version": "8.18.2", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.2.tgz", "integrity": "sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==", - "dev": true, "engines": { "node": ">=10.0.0" }, diff --git a/package.json b/package.json index 128ff4d60..af226d73d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "sureforms", - "version": "2.11.0", + "version": "2.11.1", "description": "A simple yet powerful way to add forms to your website.", "main": "index.js", "scripts": { @@ -38,26 +38,26 @@ "i18n:po": "wp i18n update-po languages/sureforms.pot", "i18n:mo": "wp i18n make-mo languages", "i18n:json": "wp i18n make-json languages --no-purge", - "i18n:gptpo:nl": "gpt-po translate --po languages/sureforms-nl_NL.po --lang nl --verbose", - "i18n:gptpo:fr": "gpt-po translate --po languages/sureforms-fr_FR.po --lang fr --verbose", - "i18n:gptpo:de": "gpt-po translate --po languages/sureforms-de_DE.po --lang de --verbose", - "i18n:gptpo:es": "gpt-po translate --po languages/sureforms-es_ES.po --lang es --verbose", - "i18n:gptpo:it": "gpt-po translate --po languages/sureforms-it_IT.po --lang it --verbose", - "i18n:gptpo:pt": "gpt-po translate --po languages/sureforms-pt_PT.po --lang pt --verbose", - "i18n:gptpo:pl": "gpt-po translate --po languages/sureforms-pl_PL.po --lang pl --verbose", - "i18n:gptpo:id": "gpt-po translate --po languages/sureforms-id_ID.po --lang id --verbose", - "i18n:gptpo:ptbr": "gpt-po translate --po languages/sureforms-pt_BR.po --lang pt --verbose", - "i18n:gptpo:ru": "gpt-po translate --po languages/sureforms-ru_RU.po --lang ru --verbose", - "i18n:gptpo:tr": "gpt-po translate --po languages/sureforms-tr_TR.po --lang tr --verbose", - "i18n:gptpo:ja": "gpt-po translate --po languages/sureforms-ja.po --lang ja --verbose", - "i18n:gptpo:zh": "gpt-po translate --po languages/sureforms-zh_CN.po --lang zh --verbose", - "i18n:gptpo:ar": "gpt-po translate --po languages/sureforms-ar.po --lang ar --verbose", - "i18n:gptpo:sv": "gpt-po translate --po languages/sureforms-sv_SE.po --lang sv --verbose", - "i18n:gptpo:vi": "gpt-po translate --po languages/sureforms-vi.po --lang vi --verbose", - "i18n:gptpo:he": "gpt-po translate --po languages/sureforms-he_IL.po --lang he --verbose", - "i18n:gptpo:th": "gpt-po translate --po languages/sureforms-th.po --lang th --verbose", - "i18n:gptpo:el": "gpt-po translate --po languages/sureforms-el.po --lang el --verbose", - "i18n:gptpo:cs": "gpt-po translate --po languages/sureforms-cs_CZ.po --lang cs --verbose" + "i18n:gptpo:nl": "gpt-po translate --po languages/sureforms-nl_NL.po --lang nl --model gpt-4o --verbose", + "i18n:gptpo:fr": "gpt-po translate --po languages/sureforms-fr_FR.po --lang fr --model gpt-4o --verbose", + "i18n:gptpo:de": "gpt-po translate --po languages/sureforms-de_DE.po --lang de --model gpt-4o --verbose", + "i18n:gptpo:es": "gpt-po translate --po languages/sureforms-es_ES.po --lang es --model gpt-4o --verbose", + "i18n:gptpo:it": "gpt-po translate --po languages/sureforms-it_IT.po --lang it --model gpt-4o --verbose", + "i18n:gptpo:pt": "gpt-po translate --po languages/sureforms-pt_PT.po --lang pt --model gpt-4o --verbose", + "i18n:gptpo:pl": "gpt-po translate --po languages/sureforms-pl_PL.po --lang pl --model gpt-4o --verbose", + "i18n:gptpo:id": "gpt-po translate --po languages/sureforms-id_ID.po --lang id --model gpt-4o --verbose", + "i18n:gptpo:ptbr": "gpt-po translate --po languages/sureforms-pt_BR.po --lang pt --model gpt-4o --verbose", + "i18n:gptpo:ru": "gpt-po translate --po languages/sureforms-ru_RU.po --lang ru --model gpt-4o --verbose", + "i18n:gptpo:tr": "gpt-po translate --po languages/sureforms-tr_TR.po --lang tr --model gpt-4o --verbose", + "i18n:gptpo:ja": "gpt-po translate --po languages/sureforms-ja.po --lang ja --model gpt-4o --verbose", + "i18n:gptpo:zh": "gpt-po translate --po languages/sureforms-zh_CN.po --lang zh --model gpt-4o --verbose", + "i18n:gptpo:ar": "gpt-po translate --po languages/sureforms-ar.po --lang ar --model gpt-4o --verbose", + "i18n:gptpo:sv": "gpt-po translate --po languages/sureforms-sv_SE.po --lang sv --model gpt-4o --verbose", + "i18n:gptpo:vi": "gpt-po translate --po languages/sureforms-vi.po --lang vi --model gpt-4o --verbose", + "i18n:gptpo:he": "gpt-po translate --po languages/sureforms-he_IL.po --lang he --model gpt-4o --verbose", + "i18n:gptpo:th": "gpt-po translate --po languages/sureforms-th.po --lang th --model gpt-4o --verbose", + "i18n:gptpo:el": "gpt-po translate --po languages/sureforms-el.po --lang el --model gpt-4o --verbose", + "i18n:gptpo:cs": "gpt-po translate --po languages/sureforms-cs_CZ.po --lang cs --model gpt-4o --verbose" }, "repository": "git+https://github.com/brainstormforce/sureforms.git", "author": "Brainstorm Force", @@ -113,7 +113,7 @@ "cssnano": "^6.0.1", "date-fns": "^4.1.0", "dompurify": "^3.3.3", - "gpt-po": "1.1.1", + "gpt-po": "1.3.0", "html-react-parser": "^5.0.7", "intl-tel-input": "^25.14.0", "lucide-react": "^0.475.0", @@ -132,6 +132,6 @@ "use-debounce": "^10.0.0" }, "volta": { - "node": "20.20.1" + "node": "24.16.0" } } \ No newline at end of file diff --git a/readme.txt b/readme.txt index 912e06596..40cdffaa2 100644 --- a/readme.txt +++ b/readme.txt @@ -1,14 +1,14 @@ -=== SureForms - Drag & Drop Contact Form, Payment Form, Survey, Quiz, Calculator & Custom Form Builder === +=== SureForms - Drag & Drop Contact Form & Form Builder, Payment Form, Survey, Quiz & Calculator === Contributors: brainstormforce Tags: forms, contact form, form builder, survey, payment form Requires at least: 6.4 Tested up to: 7.0 Requires PHP: 7.4 -Stable tag: 2.11.0 +Stable tag: 2.11.1 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html -The AI-powered WordPress form builder. Build contact, payment, quiz, survey & multi-step forms in minutes, no code needed. +AI WordPress form builder. Create contact forms, payment forms, surveys, quizzes & multi-step forms โ€” drag & drop, no code. == Description == @@ -26,23 +26,13 @@ Trusted by **500,000+ websites**, SureForms is the modern alternative to traditi ### CREATE BEAUTIFUL RESPONSIVE FORMS USING WORDPRESS BLOCK EDITOR (GUTENBERG EDITOR) WITHOUT CODING โšก -Our mission at SureForms is to empower you to build **beautiful WordPress forms without any code**. +Our mission at SureForms is to empower you to build **beautiful contact forms and custom WordPress forms without any code**. We're taking a fresh approach with Gutenberg, WordPress's native drag-and-drop builder, to make creating contact forms and custom forms seamless and intuitive โ€” with no new interface to learn. SureForms is a beginner-friendly WordPress form plugin that makes building contact forms and other high-converting custom forms fast and simple, with advanced features like multi-step forms, conversational forms, payment forms, conditional logic, calculations, native integrations, and more. -Good design and user experience are crucial for forms. Yet many website owners struggle to make their forms blend seamlessly with their site's look and feel, often leading to lower response rates. - -In this regard, SureForms addresses several pain points commonly experienced by WordPress users: - -- Complex Process of Form Building -- Design Limitations -- Lack of Mobile-friendliness and Accessibility -- Limited Engagement in Their Forms -- Spam and Security Issues - -SureForms is packed with features to address these pain points of WordPress users. +Good design and user experience are crucial for contact forms. Yet many website owners struggle to make their contact forms blend seamlessly with their site's look and feel, often leading to lower response rates. ### POWERFUL FEATURES OF SUREFORMS ๐Ÿ’ช @@ -95,7 +85,7 @@ With SureForms' own Instant Form feature, you can publish forms with a unique sh #### Mobile-Friendly Responsive Forms -SureForms recognizes the importance of mobile-friendly forms. Every form created with SureForms is designed with a mobile-first approach, ensuring it looks and functions flawlessly on phones, tablets, and desktops alike. +SureForms recognizes the importance of mobile-friendly contact forms. Every form created with SureForms is designed with a mobile-first approach, ensuring it looks and functions flawlessly on phones, tablets, and desktops alike. #### Multi-Column Form Layouts @@ -221,7 +211,7 @@ Let users save their progress and come back to complete the form later. Capture in-progress form submissions automatically โ€” recover abandoned forms and follow up with users who dropped off before completing. **Form Restrictions:** -Restrict form visibility and submissions by IP address, country, keywords, user login status, or password. Set submission limits per day, week, month, year, or lifetime. +Restrict form visibility and submissions by IP address, country, keywords, user login status, or password โ€” with regex support for advanced validation. Set submission limits per day, week, month, year, or lifetime. [**Custom Registration & Login Forms**](https://sureforms.com/features/login-and-registration/?utm_source=wordpress.org&utm_medium=registration_login): Fully functional, branded Registration and Login forms for your WordPress site using just a block. @@ -229,9 +219,6 @@ Fully functional, branded Registration and Login forms for your WordPress site u [**Custom Post Type Creation**](https://sureforms.com/features/post-creation/?utm_source=wordpress.org&utm_medium=post_creation): Create WordPress posts or custom post types directly from form submissions. -**Field Restrictions:** -Restrict form submissions by IP, country, keywords, user login, or password โ€” with regex support for advanced validation. - **Conditional Emails & Confirmations:** Send different email notifications and show different confirmation messages based on form field values. @@ -246,34 +233,7 @@ Customize form appearance with advanced styling options when embedding forms via [**Advanced Native Integrations**](https://sureforms.com/integrations/?utm_source=wordpress.org&utm_medium=integrations): Connect your forms natively with top apps and services to automate workflows and save time โ€” no third-party add-ons or plugins required. -SureForms connects natively with: -- Google Sheets -- Mailchimp -- FluentCRM -- Telegram -- HubSpot -- MailerLite -- Brevo (Sendinblue) -- ActiveCampaign -- Kit -- GetResponse -- Airtable -- MailJet -- Campaign Monitor -- Drip -- Salesflare -- Breeze -- Latepoint -- Hostinger Reach -- AgileCRM -- WPFusion -- Klaviyo -- Keap -- Notion -- MailPoet -- MailerPress -- Zoho CRM -- SureContact +SureForms connects natively with Google Sheets, Mailchimp, FluentCRM, HubSpot, Brevo, ActiveCampaign, Zoho CRM, Klaviyo, Airtable, Notion, Telegram, MailerLite, GetResponse, Campaign Monitor, Drip, MailPoet, Kit, Keap, and 25+ more. **Zapier Integration:** Connect your forms with 5,000+ apps through Zapier for limitless automation. @@ -291,11 +251,9 @@ Customize form appearance directly within your favorite page builder: - Bricks Builder โ€” styling options in the Bricks panel - Elementor โ€” styling controls in the Elementor widget -With SureForms, we are here to fix the real issues users face with WordPress forms. That's why **500,000+ websites** have embraced SureForms for all their form-related needs. - ### HOW IT WORKS โ“ -From installation to creating your first form, SureForms is designed to be simple and intuitive. Here is how it works: +From installation to creating your first contact form, SureForms is designed to be simple and intuitive. Here is how it works: #### Step 1: Install the SureForms WordPress Plugin ๐Ÿ”Œ @@ -313,53 +271,18 @@ Once your form is ready, easily embed it on any page or post using the provided SureForms is built for anyone who needs contact forms, custom forms, or advanced user-friendly forms on WordPress. -- **Website Owners:** For any GDPR-compliant forms without coding. +- **Website Owners:** For any GDPR-compliant contact form without coding. - **Designers:** For forms that match site aesthetics with custom styling options. - **Developers:** Ability to extend with clean APIs, hooks, and custom CSS. - **No-Code Professionals:** Use advanced features like Conditional Logic, Multi-step, and Conversational Forms with ease. - **Agencies:** To save time with easy integration for scalable workflows. - **E-commerce Stores:** To power up Checkouts, Registrations, and Customer Forms. - **Educators & Communities:** To build student Registration or Login Forms, Feedback Forms, or Membership Forms quickly. - -Don't think this is just it. There is no limit to the types of businesses and organizations that can benefit from using SureForms. - ### WORDPRESS THEMES & PLUGINS THAT SUREFORMS SUPPORTS ๐Ÿ”— -#### SureForms works with any theme, including: - -- Astra -- Spectra One -- Blocksy -- Bricks Builder -- Flatsome -- GeneratePress -- Hestia -- Kadence -- Neve - -#### SureForms is compatible with all plugins, including: - -- Spectra -- Easy Digital Downloads -- FluentCRM -- GiveWP -- LearnDash -- LifterLMS -- MemberPress -- PrestoPlayer -- Restrict Content Pro -- SureCart -- SureMembers -- OttoKit -- The Events Calendar -- TutorLMS -- Wishlist Member -- WooCommerce -- CartFlows -- Elementor Pro -- Beaver Builder -- Divi Builder -- And many more +SureForms works with any theme, including Astra, Spectra One, Blocksy, Bricks, Flatsome, GeneratePress, Hestia, Kadence, and Neve. + +It is compatible with popular plugins including WooCommerce, Easy Digital Downloads, GiveWP, LearnDash, LifterLMS, MemberPress, Restrict Content Pro, SureCart, SureMembers, OttoKit, The Events Calendar, TutorLMS, Wishlist Member, CartFlows, Elementor Pro, Beaver Builder, Divi, and many more. ### CONNECT WITH OUR TEAM AND COMMUNITY @@ -535,6 +458,10 @@ Yes. SureForms Business includes fully functional user registration forms and lo You can report security issues through our [Bug Bounty Program](https://brainstormforce.com/bug-bounty-program/). We collaborate with Patchstack to provide opportunities for researchers to report vulnerabilities. The Patchstack team will help validate, triage, and handle any reported security issues. == Changelog == += 2.11.1 - 16th June 2026 = +* Fix: Phone field auto country detection always resolved to the United States. +* Fix: Corrected the Cloudflare Turnstile "Get Keys" link. +* Fix: This update addressed a security bug. Props to Yaswanth Reddy Sunkara for reporting it responsibly to our team. = 2.11.0 - 10th June 2026 = * New: Added a Form Migrator to import forms from Contact Form 7, WPForms, Gravity Forms, and Ninja Forms in a single click. * New: Added native WPML support to translate each form individually using String Packages. @@ -542,12 +469,6 @@ You can report security issues through our [Bug Bounty Program](https://brainsto * Improvement: Improved compatibility with older Block API versions so the SureForms editor loads reliably across WordPress environments. * Fix: Resolved an issue where the Textarea character counter was misaligned. * Fix: Resolved an issue where the {entry_id} smart tag failed to resolve in email notifications. -= 2.10.0 - 27th May 2026 = -* New: Added a live character counter to Textarea fields. -* New: Added a one-click converter that turns raw HTML forms into native SureForms in gutenberg editor. -* Improvement: Added dynamic default value support for multi-select Dropdown and Multi-Choice fields. -* Improvement: Entry URL now records actual submission page. -* Fix: CSV export was stripping line breaks from Textarea submissions. The full changelog is available [here](https://sureforms.com/whats-new/?utm_source=wordpress.org&utm_medium=whats_new). == Upgrade Notice == diff --git a/src/admin/settings/components/security/Turnstile.js b/src/admin/settings/components/security/Turnstile.js index dec22ca38..194e0bc4c 100644 --- a/src/admin/settings/components/security/Turnstile.js +++ b/src/admin/settings/components/security/Turnstile.js @@ -49,7 +49,7 @@ const Turnstile = ( { securitytabOptions, updateGlobalSettings } ) => {