diff --git a/.claude/agents/code-simplifier.md b/.claude/agents/code-simplifier.md deleted file mode 100644 index 2dfa2039d..000000000 --- a/.claude/agents/code-simplifier.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -name: code-simplifier -description: Reviews recent code changes and suggests simplifications — reduces complexity, removes dead code, flattens nesting, applies DRY. -tools: Read, Glob, Grep -model: sonnet ---- - -You are a code simplification expert for a WordPress/React plugin. - -## Your Task - -Review the recently changed files and suggest concrete simplifications. Do NOT make changes — only report findings. - -## What to Look For - -### PHP -- Duplicated logic that can be extracted into a shared method -- Deeply nested conditionals that can be flattened with early returns -- Dead code (unused variables, unreachable branches, commented-out code) -- Verbose array/string operations that WordPress has helpers for -- Overly complex conditionals that can be simplified - -### JavaScript/React -- Components doing too much — can they be split? -- Duplicated JSX or logic across components -- State that could be derived instead of stored -- useEffect with dependencies that could be simplified -- Unnecessary re-renders from inline objects/functions in props - -## Output Format - -For each finding: - -``` -### file-path:line-number -**Type:** DRY | Complexity | Dead Code | Optimization -**Current:** Brief description of current code -**Suggestion:** How to simplify (1-2 sentences) -**Impact:** Low | Medium | High -``` - -End with a summary: total findings by type and priority. - -## Rules -- Only report findings with clear, concrete improvements -- No subjective style preferences — only measurable simplifications -- Skip third-party code (`inc/lib/`, `node_modules/`, `vendor/`) -- Be precise with line numbers diff --git a/.claude/agents/srfm-block-checker.md b/.claude/agents/srfm-block-checker.md deleted file mode 100644 index ec7bbf8b9..000000000 --- a/.claude/agents/srfm-block-checker.md +++ /dev/null @@ -1,60 +0,0 @@ ---- -name: srfm-block-checker -description: Audits SureForms block render files for security issues — checks output escaping, input sanitization, ABSPATH guards, and WPCS compliance. -tools: Read, Glob, Grep -model: sonnet ---- - -You are a WordPress security reviewer specialized in Gutenberg block rendering. - -## Your Task - -Audit SureForms block PHP files for common security and quality issues. - -## Files to Check - -1. All block render files: `inc/blocks/*/block.php` -2. All field markup files: `inc/fields/*.php` -3. The base block class: `inc/blocks/base.php` - -## Checklist for Each File - -For every file, check and report: - -### Security -- [ ] **ABSPATH guard** — File starts with `if ( ! defined( 'ABSPATH' ) ) { exit; }` -- [ ] **Output escaping** — All `echo` statements use `esc_html()`, `esc_attr()`, `wp_kses_post()`, or `wp_kses()`. Flag any raw `echo $var` without escaping (note: `// phpcs:ignore` comments may indicate intentional bypass — flag these for review) -- [ ] **Attribute sanitization** — Block attributes accessed from `$attributes` are sanitized before use -- [ ] **No direct `$_GET`/`$_POST`/`$_REQUEST`** — Block render should never read superglobals directly - -### Quality -- [ ] **`@since` tag present** — Class and methods have `@since` docblock tags -- [ ] **Namespace follows convention** — Uses `SRFM\Inc\Blocks\{BlockName}` pattern -- [ ] **Extends Base** — Block class extends `SRFM\Inc\Blocks\Base` -- [ ] **Return type** — `render()` method returns `string|bool` - -## Output Format - -For each file, output: - -``` -### block-name/block.php -- PASS: ABSPATH guard present -- WARN: Line 33 — raw echo with phpcs:ignore, verify markup() output is pre-escaped -- PASS: No superglobals used -- FAIL: Missing @since tag on render() method -``` - -End with a summary table: - -| Block | Security | Quality | Issues | -|-------|----------|---------|--------| -| input | WARN | FAIL | 2 | -| email | PASS | PASS | 0 | - -## Important - -- Be precise — include line numbers for every issue -- Distinguish FAIL (must fix) from WARN (review needed) -- Do NOT suggest code changes — only report findings -- Check ALL block files, not just a sample diff --git a/.claude/commands/sureforms:investigate.md b/.claude/commands/sureforms:investigate.md deleted file mode 100644 index d171756ec..000000000 --- a/.claude/commands/sureforms:investigate.md +++ /dev/null @@ -1,67 +0,0 @@ -# Investigate Issue - -Investigate a reported issue using parallel subagents for speed. - -## Input - -$ARGUMENTS — GitHub issue URL, Jira ticket ID, or a description of the issue. - -If no arguments provided, stop and ask: "Please provide an issue URL, Jira ticket ID, or describe the issue." - -## Step 1 — Read the Issue - -- If a GitHub URL: use `gh issue view` to read the issue -- If a Jira ticket: use the Jira MCP tools to read the ticket -- If a description: use the provided text directly - -Extract: title, description, steps to reproduce, expected vs actual behavior, screenshots, labels. - -## Step 2 — Classify - -Determine the type: -- **Bug** — something is broken, unexpected behavior, error, regression -- **Feature** — new functionality requested -- **Improvement** — enhancement to existing functionality - -Tell the user: "This looks like a **[type]**. Proceeding with [investigation/planning]." - -## Step 3 — Investigate with Subagents - -Use subagents to parallelize the investigation: - -### For Bugs: -Launch these subagents in parallel: -1. **Code Search Agent** — Search the codebase for files related to the bug (grep for keywords, function names, error messages, related hooks/filters) -2. **Test Coverage Agent** — Check if there are existing tests covering this area, identify gaps -3. **Impact Analysis Agent** — Trace all usages of the affected code to understand blast radius - -Once all agents report back, synthesize findings: -- Present the probable root cause with file path and line number -- Show which other areas might be affected -- Suggest a fix with a clear explanation -- Ask the user: "Should I apply this fix?" -- If yes — apply the fix, run linters, and suggest running relevant tests - -### For Features: -1. Enter plan mode -2. Launch subagents in parallel: - - **Pattern Discovery Agent** — Find similar existing features in the codebase to follow the same patterns - - **Impact Analysis Agent** — Identify all files that will need changes -3. Use findings to outline implementation steps -4. Present the plan for approval - -### For Improvements: -1. Launch subagents in parallel: - - **Code Search Agent** — Read the relevant existing code - - **Impact Analysis Agent** — Trace dependencies to understand what might break -2. Suggest the minimal changes needed -3. Ask the user: "Should I implement these changes?" -4. If yes — apply changes and run linters - -## Rules -- Always use subagents for investigation to maximize speed -- Show your reasoning — which files you checked and why -- Be precise with file paths and line numbers -- For bugs, prioritize finding the root cause over applying a quick patch -- Never make changes without asking first -- After any code change, run the verification checklist from CLAUDE.md diff --git a/.claude/commands/sureforms:update-readme.md b/.claude/commands/sureforms:update-readme.md deleted file mode 100644 index b3d9d8a6f..000000000 --- a/.claude/commands/sureforms:update-readme.md +++ /dev/null @@ -1,327 +0,0 @@ ---- -description: Audit and update the WordPress.org readme.txt — analyze new features, research competitors, draft changes, and create a PR ---- - -# SureForms readme.txt Update - -Comprehensive audit and update of the `readme.txt` (and `README.md`) for the WordPress.org listing. - -## Arguments - -Parse from: $ARGUMENTS - -Expected format: `[version] [--full]` - -- `version` — optional. Baseline version to analyze changes since (e.g., `2.5.0`). If not provided, auto-detect from the most recent `= X.X.X` changelog header in `readme.txt`. -- `--full` — optional flag. Perform a full rewrite of all sections instead of an incremental update. - -If no arguments are given, auto-detect the baseline and proceed with incremental mode. - -## Working Directory - -All commands and file paths are relative to the sureforms plugin root — the directory containing `sureforms.php`. - ---- - -## Phase 1: Analyze What's New - -### Step 1.1 — Determine Baseline Version - -- If `version` argument was provided, use that as the baseline. -- Otherwise, read the `== Changelog ==` section of `readme.txt`, extract the most recent version header (`= X.X.X - ... =`), and use that version as the baseline. -- Resolve the git tag: `v` (e.g., `v2.5.0`). Verify it exists with `git tag -l "v"`. -- If the tag does not exist, list available tags (`git tag --sort=-version:refname | head -10`) and ask the user to pick one. - -### Step 1.2 — Gather Changes Since Baseline - -Launch **3 Explore subagents in parallel** (single message, 3 Agent tool calls): - -**Agent 1 — Git History Analysis:** -- Run `git log v..HEAD --oneline` to get all commits since the baseline. -- Categorize commits: new features, improvements, bug fixes, refactors. -- Focus on commits touching: `inc/blocks/`, `inc/fields/`, `inc/payments/`, `inc/ai-form-builder/`, `modules/`, `src/blocks/`, `inc/page-builders/`. -- Report: list of significant user-facing changes with commit hashes and affected areas. - -**Agent 2 — Free Codebase Feature Scan:** -- List all blocks in `inc/blocks/` — compare against the readme's "Input Fields" and feature bullets. -- Check `inc/payments/` for payment providers. -- Check `inc/ai-form-builder/` for AI feature updates. -- Check `modules/` for any new modules. -- Check `inc/global-settings/` for new settings sections. -- Check `inc/rest-api.php` for new REST endpoints. -- Check `inc/page-builders/` for page builder compatibility additions. -- Report: features present in code but missing from readme. - -**Agent 3 — Pro Codebase Feature Scan:** -- Check `../sureforms-pro/inc/pro/native-integrations/integrations/` — list ALL integration JSON files and compare against the readme's integration list. -- Check `../sureforms-pro/inc/blocks/` for pro-only blocks. -- Check `../sureforms-pro/inc/pro/` subdirectories for pro features (conversational-form, save-resume, signature, zapier, etc.). -- Check `../sureforms-pro/inc/extensions/` for conditional logic, field-restrictions, etc. -- If `../sureforms-pro/` does not exist, skip this agent and warn: "Pro plugin not found. Only free features will be analyzed." -- Report: pro features/integrations present in code but missing from readme. - -### Step 1.3 — Present Gap Analysis - -Merge all agent results and present a table: - -``` -┌─────────────────────────────────────┬────────┬──────────────────────────────┐ -│ Area │ Status │ Details │ -├─────────────────────────────────────┼────────┼──────────────────────────────┤ -│ Free field types match readme │ ✅/❌ │ Code: N, Readme: M │ -│ Pro blocks mentioned │ ✅/❌ │ Missing: ... │ -│ Integration list up to date │ ✅/❌ │ Missing: ... │ -│ Pro features all listed │ ✅/❌ │ Missing: ... │ -│ Payment providers accurate │ ✅/❌ │ │ -│ Page builder compat listed │ ✅/❌ │ │ -│ "Tested up to" WP version │ ✅/❌ │ Readme: X.X, Current: Y.Y │ -│ New features since v │ ℹ️ │ N features found │ -└─────────────────────────────────────┴────────┴──────────────────────────────┘ -``` - -Tell the user: "Phase 1 complete. Found **N gaps** and **M new features** to incorporate. Proceeding to competitor research." - ---- - -## Phase 2: Competitor & Market Research - -### Step 2.1 — Research Competitor READMEs - -Use **WebSearch** to run these searches in parallel: - -1. `"WPForms" site:wordpress.org/plugins description features` -2. `"Gravity Forms" site:wordpress.org/plugins description features` -3. `"Fluent Forms" site:wordpress.org/plugins fluentform features` -4. `"Formidable Forms" site:wordpress.org/plugins description features` -5. `"Contact Form 7" site:wordpress.org/plugins description` -6. `"WordPress.org readme.txt best practices 2025 2026"` - -For each competitor, use **WebFetch** on the top result URL if needed to extract: -- How they structure feature lists -- Marketing language and benefit-focused copy -- How they distinguish free vs pro features -- FAQ structure and common questions -- Trust signals (install counts, star ratings, testimonials) - -### Step 2.2 — Present Research Summary - -Show a comparison table: - -``` -Feature Highlighted by Competitors │ SureForms Has It? │ In Readme? -──────────────────────────────────────┼───────────────────┼────────── -Conditional Logic │ ✅ (Pro) │ ✅/❌ -File Upload │ ✅ (Pro) │ ✅/❌ -Drag & Drop Builder │ ✅ (Free) │ ✅/❌ -... │ │ -``` - -Also note: -- SEO-relevant keywords competitors use that SureForms is missing. -- Structural patterns that work well (comparison tables, benefit-focused headers). -- Any WordPress.org formatting trends. - -Tell the user: "Phase 2 complete. Ready to draft the update. Shall I proceed?" - -**⏸️ WAIT for user confirmation before proceeding to Phase 3.** - ---- - -## Phase 3: Draft the Update - -### Step 3.1 — Determine Scope - -- If `--full` flag was passed: draft ALL sections from scratch. -- Otherwise: draft only sections that need changes based on Phase 1 and Phase 2 findings. - -### Step 3.2 — Draft Each Section - -For each section that needs updating, present in this format: - -``` -━━━ SECTION: [Section Name] ━━━ - -── CURRENT ── -[Current text from readme.txt, abbreviated if very long] - -── PROPOSED ── -[New text] - -── CHANGES ── -• Added: [what was added] -• Removed: [what was removed, if any] -• Reworded: [what was reworded and why] -``` - -Sections to evaluate (in order): - -1. **Plugin header** — Stable tag, Tested up to, Tags (optimize for WordPress.org search) -2. **Short description** — Must be under 150 characters. Make it compelling and keyword-rich. -3. **Long description** — Feature bullets, AI section, payment section, field types list -4. **Premium features section** — Integration list, pro-only features, pro field types -5. **FAQ** — Add questions for new features, update outdated answers -6. **3rd Party Services** — Add any new external services used -7. **Compatibility lists** — Themes and plugins - -### Step 3.3 — WordPress.org Compliance Check - -Verify the draft against WordPress.org readme standards: -- ✅ Short description is under 150 characters -- ✅ No disallowed HTML in description -- ✅ `== Changelog ==` section exists and is properly formatted -- ✅ `== Frequently Asked Questions ==` uses correct `= Question =` format -- ✅ No broken markdown that WordPress.org would render incorrectly -- ✅ Stable tag matches the version in the main plugin file - -### Step 3.4 — Present Full Draft - -Present all drafted sections together with a summary: - -``` -📋 Readme Update Summary -───────────────────────────────────── -Sections modified: N -Lines added: +X -Lines removed: -Y -New features listed: Z -New integrations: W -New FAQ entries: Q -WP.org compliance: ✅ All checks pass -``` - -Tell the user: "Please review the draft above. You can: -1. **Approve** — proceed to apply changes and create PR -2. **Request edits** — tell me what to change -3. **Abort** — cancel the update" - -**⏸️ WAIT for explicit user approval. Do NOT proceed without it.** - ---- - -## Phase 4: User Review & Iteration - -This phase is a loop: - -1. If user **requests edits** → apply them to the draft and re-present the affected sections. Ask again for approval. -2. If user **approves** → proceed to Phase 5. -3. If user **aborts** → stop and report "Readme update cancelled. No changes were made." - ---- - -## Phase 5: Apply & Create PR - -### Step 5.1 — Create Branch - -```bash -git fetch origin -git checkout dev -git pull origin dev -git checkout -b chore/update-readme -``` - -If `chore/update-readme` already exists, append a date suffix: `chore/update-readme-YYYYMMDD`. - -### Step 5.2 — Apply Changes - -Edit `readme.txt` with the approved draft changes. Apply section by section — do NOT rewrite sections that weren't modified. - -### Step 5.3 — Regenerate README.md - -```bash -npx grunt readme -``` - -Verify `README.md` was updated. If `grunt readme` fails, check that `npm install` has been run and `grunt-wp-readme-to-markdown` is in `devDependencies`. - -### Step 5.4 — Verify - -Read the updated `readme.txt` and confirm: -- Stable tag matches current plugin version -- Tested up to is correct -- Short description is under 150 characters -- All sections are properly formatted -- No stray draft markers or debug text - -### Step 5.5 — Commit and Push - -```bash -git add readme.txt README.md -git commit -m "chore: update readme.txt for WordPress.org listing - -Update plugin description, feature lists, integrations, FAQ, -and compatibility information to reflect current capabilities. - -Co-Authored-By: Claude Opus 4.6 (1M context) " -git push -u origin chore/update-readme -``` - -### Step 5.6 — Create PR - -```bash -gh pr create \ - --title "chore: Update readme.txt for WordPress.org" \ - --base dev \ - --body "$(cat <<'EOF' -## Summary -- Updated readme.txt to reflect current plugin capabilities -- Regenerated README.md via `grunt readme` - -## What Changed -[List each section that was modified and what changed] - -## Research Notes -- Competitor READMEs reviewed: WPForms, Gravity Forms, Fluent Forms, Formidable, CF7 -- Gaps identified and addressed: [count] - -## Test Plan -- [ ] Preview on WordPress.org readme validator -- [ ] Verify all links in the readme are working -- [ ] Confirm feature claims match actual plugin capabilities -- [ ] Verify short description is under 150 characters - -🤖 Generated with [Claude Code](https://claude.com/claude-code) -EOF -)" -``` - -### Step 5.7 — Final Report - -``` -✅ Readme Update Complete -───────────────────────────────────────── -✅ Phase 1: Gap analysis complete -✅ Phase 2: Competitor research complete -✅ Phase 3: Draft created -✅ Phase 4: User review passed -✅ Phase 5: Changes applied -✅ Branch: chore/update-readme (from dev) -✅ readme.txt updated -✅ README.md regenerated -✅ PR: - -Sections updated: - • [List each modified section] -``` - ---- - -## Rules - -- **NEVER modify readme.txt without user approval.** Always present the full draft first. -- **NEVER invent features.** Only document what actually exists in the codebase. -- **NEVER modify changelog entries.** The changelog is managed by `/sureforms:version-bump`. -- **ALWAYS branch from `dev`**, never from `master` or `next-release`. -- **ALWAYS run `npx grunt readme`** after modifying `readme.txt` to regenerate `README.md`. -- **ALWAYS verify feature claims** by checking the actual codebase, not just commit messages. -- **Keep the 150-character limit** for the WordPress.org short description. -- **Maintain the existing voice and tone** — professional, benefit-focused, not overly salesy. - -## Error Recovery - -| Symptom | Fix | -|---------|-----| -| `grunt readme` fails | Run `npm install` first; verify `grunt-wp-readme-to-markdown` is in `devDependencies` | -| Branch already exists | Append date suffix: `chore/update-readme-YYYYMMDD` | -| Pro plugin not found at `../sureforms-pro/` | Skip pro analysis, warn user, document only free features | -| Git tag not found | List available tags and ask user to pick one | -| WebSearch unavailable | Skip Phase 2, proceed with codebase analysis only, note the limitation | diff --git a/.claude/commands/sureforms:version-bump.md b/.claude/commands/sureforms:version-bump.md deleted file mode 100644 index 5f48a2e1f..000000000 --- a/.claude/commands/sureforms:version-bump.md +++ /dev/null @@ -1,204 +0,0 @@ -# SureForms Release Version Bump - -Automates the SureForms version bump release checklist end-to-end. - -## Arguments - -Parse from: $ARGUMENTS - -Expected format: ` [pro-version] [branch]` - -- `version` — **required**. Version number to release (e.g., `2.5.2`). If not provided, stop immediately and tell the user: `"Version number is required. Usage: /sureforms:version-bump [pro-version] [branch]"` -- `pro-version` — optional. Version to set for `SRFM_PRO_RECOMMENDED_VER`. If not provided, ask: `"What should SRFM_PRO_RECOMMENDED_VER be set to? (default: )"` and default to the core version if the user presses Enter or skips. -- `branch` — optional. Source branch to cut from — must be `dev` or `next-release`. Default: `next-release`. - -## Working Directory - -All commands and file paths are relative to the sureforms plugin root. Detect it as the directory containing `sureforms.php` — typically the current working directory or a `sureforms/` subdirectory of it. - ---- - -## Steps - -### Step 1 — Validate Arguments - -- Extract `version`, `pro-version`, and `branch` from `$ARGUMENTS`. -- Abort with usage message if `version` is missing. -- If `branch` is provided but not `dev` or `next-release`, abort: `"Invalid branch. Must be 'dev' or 'next-release'."` -- If `pro-version` was not passed as an argument, prompt the user for it (default: same as `version`). - ---- - -### Step 2 — Create Version Bump Branch - -Run from the sureforms plugin root: - -```bash -git fetch origin -git checkout -git pull origin -git checkout -b version-bump- -``` - -Confirm the new branch was created successfully before continuing. - ---- - -### Step 3 — Run Grunt Version Bump - -```bash -npx grunt version-bump --ver= -``` - -This runs `bumpup` (updates `package.json`) and `replace` (updates version strings in `readme.txt` and `sureforms.php`). - ---- - -### Step 4 — Verify package.json and package-lock.json - -- Read `package.json` → confirm `"version"` equals ``. -- Read `package-lock.json` → confirm the top-level `"version"` and `packages[""].version` both equal ``. -- If `package-lock.json` is out of sync, patch **only** the two version string values — do not alter any whitespace, indentation, line endings, or surrounding characters: - - Top-level: replace only the value in `"version": ""` → `"version": ""` - - Inside `"packages": { "": { ... } }`: replace only the value in `"version": ""` → `"version": ""` - - The resulting diff must show **exactly 2 lines changed** — only the version string on each line. No other bytes in the file should change. - - Do **not** run `npm install` — dependency conflicts can cause it to fail and it is not needed for this change. - ---- - -### Step 5 — Verify readme.txt — Stable tag - -- Read `readme.txt` and confirm `Stable tag: `. -- If incorrect, edit the line to the correct value. - ---- - -### Step 6 — Verify readme.txt — Tested up to - -- Fetch the latest WordPress version by running: - ```bash - curl -s "https://api.wordpress.org/core/version-check/1.7/" | grep -o '"version":"[^"]*"' | head -1 | cut -d'"' -f4 - ``` -- Store the result as ``. -- Read `readme.txt` and check the current `Tested up to:` value. -- If it does **not** match ``, update the line to `Tested up to: `. -- Confirm the final value in the file after any edit. - ---- - -### Step 7 — Verify sureforms.php — Plugin Header Version - -- Read `sureforms.php` lines 1–15. -- Confirm `Version: ` in the plugin header comment. -- If incorrect, edit to the correct value. - ---- - -### Step 8 — Verify SRFM_VER - -- Confirm `define( 'SRFM_VER', '' );` in `sureforms.php`. -- If incorrect, edit to the correct value. - ---- - -### Step 9 — Verify SRFM_PRO_RECOMMENDED_VER - -- Confirm `define( 'SRFM_PRO_RECOMMENDED_VER', '' );` in `sureforms.php`. -- If incorrect, edit to the correct value. - ---- - -### Step 10 — Verify Changelog Entry in readme.txt - -- Read the `== Changelog ==` section of `readme.txt`. -- **Check for a placeholder entry** matching `= x.x.x =` (case-insensitive): - - If **found**: ask the user: `"What is the release date for ? (e.g. 19th February 2026)"`. Replace the placeholder header with `= - =`, matching the exact formatting of existing changelog entries (spaces around the `=`, date style matching what is already present). -- **Check for an entry** matching `= -`: - - If **missing** after the above: warn the user and **pause** — they must add a changelog entry for `` before the process can continue. The expected format is: - ``` - = - DD Month YYYY = - * New: ... - * Improvement: ... - * Fix: ... - ``` - - If **found**: confirm the date is present and the format matches SureForms standards. -- **Polish each bullet line** of the `` entry: - - Fix any grammatical or spelling errors. - - Rewrite passive or vague phrasing into clear, active, benefit-led language (e.g. "Fixed bug where X" → "Fix: Resolved an issue where X to ensure Y"). - - Keep the improvements **subtle and factual** — do not invent features or exaggerate. The prefix (`New:`, `Improvement:`, `Fix:`) must stay unchanged. - - Show the user a before/after diff of any lines you changed and ask for confirmation before writing. -- Then sort the bullet lines of the `` entry so they follow this group order: - 1. `* New:` lines - 2. `* Improvement:` lines - 3. `* Fix:` lines - 4. Any other prefixes come last -- Within each group, sort lines **alphabetically** (case-insensitive) by the text that follows the prefix. -- Write the re-ordered lines back to `readme.txt` if any reordering was needed, and report whether changes were made. - ---- - -### Step 11 — Trim Changelog to 3 Entries - -- Parse the `== Changelog ==` section of `readme.txt` to identify all version entries (lines matching `= X.X.X - ...=`). -- Keep only the **3 most recent** entries (the new `` entry plus the 2 entries immediately before it), including all their bullet lines. -- Remove all older entries that follow the 3rd entry, up to but not including the next `==` section header. -- Write the trimmed content back to `readme.txt`. -- Report how many entries were removed (e.g., "Removed 4 old changelog entries"). - ---- - -### Step 12 — Generate README.md - -```bash -npx grunt readme -``` - ---- - -### Step 13 — Generate POT File - -```bash -npm run makepot -``` - ---- - -### Step 14 — Commit and Open PR - -```bash -git add -A -git commit -m "Version Bump " -git push origin version-bump- -gh pr create \ - --repo brainstormforce/sureforms \ - --title "Version Bump " \ - --base \ - --label "Release PR,skip-title-check" -``` - ---- - -### Step 15 — Final Report - -Print a status summary for every step, then the PR URL: - -``` -Release Bump: -───────────────────────────────────────── -✅ Branch created: version-bump- (from ) -✅ grunt version-bump: completed -✅ package.json: -✅ package-lock.json: -✅ readme.txt Stable tag: -✅ readme.txt Tested up to: -✅ sureforms.php Version: -✅ SRFM_VER: -✅ SRFM_PRO_RECOMMENDED_VER: -✅ Changelog entry polished, confirmed, and sorted (New → Improvement → Fix, alphabetical within groups) -✅ Changelog trimmed to 3 entries (N removed) -✅ README.md generated -✅ POT file generated -✅ PR opened: -``` - -If any step failed (❌) or needs attention (⚠️), list the required actions at the bottom. diff --git a/.claude/commands/sync-release-branches.md b/.claude/commands/sync-release-branches.md deleted file mode 100644 index 210f07139..000000000 --- a/.claude/commands/sync-release-branches.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -allowed-tools: Bash(git:*) -auto-approve: true -description: Sync master into dev and dev into next-release after a release ---- - -# Sync Release Branches - -After a release, sync the three main branches: master → dev → next-release. - -## Instructions - -Follow these steps sequentially. If any step fails, jump to the Error Recovery section. - -### Step 1: Record current state - -1. Record the current branch: -```bash -git rev-parse --abbrev-ref HEAD -``` -Store this as ORIGINAL_BRANCH. - -2. Check for uncommitted changes: -```bash -git status --porcelain -``` -If there is ANY output, stash the changes: -```bash -git stash -``` -Store HAD_STASH=true. Otherwise HAD_STASH=false. - -### Step 2: Fetch latest from remote - -```bash -git fetch origin -``` - -### Step 3: Update master - -```bash -git checkout master -git pull origin master -``` - -### Step 4: Merge master into dev - -```bash -git checkout dev -git pull origin dev -git pull origin master -``` - -If there are merge conflicts, STOP. Tell the user: "Merge conflicts while merging master into dev. Please resolve them manually." List the conflicting files. - -If merge succeeds: -```bash -git push origin dev -``` - -### Step 5: Merge dev into next-release - -```bash -git checkout next-release -git pull origin next-release -git pull origin dev -``` - -If there are merge conflicts, STOP. Tell the user: "Merge conflicts while merging dev into next-release. Please resolve them manually." List the conflicting files. - -If merge succeeds: -```bash -git push origin next-release -``` - -### Step 6: Return to original branch - -```bash -git checkout ${ORIGINAL_BRANCH} -``` - -If HAD_STASH=true: -```bash -git stash pop -``` - -Report success: "Branch sync complete. master → dev → next-release are now in sync." - -## Error Recovery - -If any step fails after switching branches: -1. Switch back to original branch: `git checkout ${ORIGINAL_BRANCH}` -2. Restore stash if needed: `git stash pop` (only if HAD_STASH=true) -3. Report the error to the user. - -NEVER force-push. If a merge has conflicts, stop and let the user resolve them. diff --git a/.claude/settings.json b/.claude/settings.json deleted file mode 100644 index 02b620f27..000000000 --- a/.claude/settings.json +++ /dev/null @@ -1,73 +0,0 @@ -{ - "hooks": { - "PreToolUse": [ - { - "matcher": "Bash", - "hooks": [ - { - "type": "command", - "command": "if echo \"$CLAUDE_BASH_COMMAND\" | grep -q '^git commit'; then echo '--- PreCommit: Running checks ---' && composer lint 2>&1 | tail -5 && composer phpstan 2>&1 | tail -5 && composer insights 2>&1 | tail -5; fi" - } - ] - } - ], - "PostToolUse": [ - { - "matcher": "Write|Edit", - "hooks": [ - { - "type": "command", - "command": "case \"$CLAUDE_FILE_PATH\" in *.php) vendor/bin/phpcbf \"$CLAUDE_FILE_PATH\" 2>/dev/null || true;; *.js|*.jsx) npx wp-scripts lint-js --fix \"$CLAUDE_FILE_PATH\" 2>/dev/null || true;; *.scss|*.css) npx wp-scripts lint-style --fix \"$CLAUDE_FILE_PATH\" 2>/dev/null || true;; esac" - } - ] - } - ] - }, - "permissions": { - "allow": [ - "Bash(npm run lint-js*)", - "Bash(npm run lint-css*)", - "Bash(npm run pretty*)", - "Bash(npm run build*)", - "Bash(npm run start)", - "Bash(npm run test:unit)", - "Bash(npm run test:e2e)", - "Bash(npm run play:*)", - "Bash(npm run makepot)", - "Bash(npm run i18n:*)", - "Bash(composer lint*)", - "Bash(composer format*)", - "Bash(composer test*)", - "Bash(composer phpstan*)", - "Bash(composer insights*)", - "Bash(npx playwright test*)", - "Bash(npx grunt *)", - "Bash(composer install*)", - "Bash(npm install*)", - "Bash(curl *)", - "Bash(git status*)", - "Bash(git diff*)", - "Bash(git log*)", - "Bash(git branch*)", - "Bash(git show*)", - "Bash(git stash*)", - "Bash(git checkout*)", - "Bash(git add*)", - "Bash(git commit*)", - "Bash(git merge*)", - "Bash(git rebase*)", - "Bash(git fetch*)", - "Bash(git pull*)", - "Bash(gh pr *)", - "Bash(gh issue *)", - "Bash(gh api *)", - "Bash(ls *)", - "Bash(wc *)", - "Bash(which *)", - "Bash(node -e *)", - "Bash(php -r *)", - "Bash(wp *)" - ], - "deny": [] - } -} diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index 1519283f0..ebf7af3d0 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 18 + - name: Setup Node 20 uses: actions/setup-node@v6 with: - node-version: '18.15.0' + node-version: '20.20.1' - name: Restore node_modules cache id: npm-cache @@ -143,10 +143,10 @@ jobs: - name: Checkout uses: actions/checkout@v6 - - name: Setup Node 18 + - name: Setup Node 20 uses: actions/setup-node@v6 with: - node-version: '18.15.0' + node-version: '20.20.1' - name: Restore node_modules cache id: npm-cache diff --git a/.github/workflows/push-asset-readme-update.yml b/.github/workflows/push-asset-readme-update.yml deleted file mode 100644 index e2d2932be..000000000 --- a/.github/workflows/push-asset-readme-update.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: Plugin asset/readme update -on: - push: - branches: - - master - paths: - - 'readme.txt' - - '.wordpress-org/**' -jobs: - master: - name: Push to main - runs-on: ubuntu-22.04 - steps: - - uses: actions/checkout@master - - name: Build - run: | - npm install --force - npm run build - - name: WordPress.org plugin asset/readme update - uses: 10up/action-wordpress-plugin-asset-update@stable - env: - SVN_PASSWORD: ${{ secrets.SVN_PASSWORD }} - SVN_USERNAME: ${{ secrets.SVN_USERNAME }} diff --git a/.github/workflows/push-to-deploy.yml b/.github/workflows/push-to-deploy.yml deleted file mode 100644 index 039c0107b..000000000 --- a/.github/workflows/push-to-deploy.yml +++ /dev/null @@ -1,19 +0,0 @@ -name: Deploy to WordPress.org -on: - release: - types: [published] -jobs: - tag: - name: New tag - runs-on: ubuntu-22.04 - steps: - - uses: actions/checkout@master - - name: Build - run: | - npm install --force - npm run build - - name: WordPress Plugin Deploy - uses: 10up/action-wordpress-plugin-deploy@master - env: - SVN_USERNAME: ${{ secrets.SVN_USERNAME }} - SVN_PASSWORD: ${{ secrets.SVN_PASSWORD }} diff --git a/.github/workflows/release-pr-template.yml b/.github/workflows/release-pr-template.yml deleted file mode 100644 index b296fcd31..000000000 --- a/.github/workflows/release-pr-template.yml +++ /dev/null @@ -1,41 +0,0 @@ - -name: Update checklist for Release PR - -on: - pull_request: - types: [ labeled ] - -jobs: - update_pr: - name: Update checklist for Release PR - if: ${{ github.event.label.name == 'Release PR' }} - runs-on: ubuntu-latest - steps: - - name: Check Branch - id: check-branch - run: | - if [[ ${{ github.base_ref }} == master || ${{ github.base_ref }} == dev || ${{ github.base_ref }} == next-release ]]; then - echo ::set-output name=match::true - fi - - uses: tzkhan/pr-update-action@v2 - if: steps.check-branch.outputs.match == 'true' - with: - repo-token: "${{ secrets.GITHUB_TOKEN }}" - base-branch-regex: '[A-Za-z\d-_.\\/]+' - head-branch-regex: '[A-Za-z\d-_.\\/]+' - body-template: | - --- - ### Release Checklist: - - [ ] Run to update version number : `grunt version-bump --ver=` - - [ ] Verify the version number in `package.json` and `package-lock.json` - - [ ] Verify `Stable tag` is `` in readme.txt - - [ ] Verify `Tested upto` is set to latest tested version of WordPress - - [ ] Update version in `sureforms.php` in plugin description - - [ ] Verify constant `SRFM_VER` in `sureforms.php` with latest version of SureForms - - [ ] Verify constant `SRFM_PRO_RECOMMENDED_VER` in `sureforms.php` with compatible version of SureForms Pro - - [ ] Verify changelog `date` and `content` as per SureForms standards - - [ ] Generate README.md : `grunt readme` - - [ ] Generate POT file : `npm run makepot` - --- - body-update-action: 'suffix' - body-uppercase-base-match: false diff --git a/.github/workflows/release-tag-draft.yml b/.github/workflows/release-tag-draft.yml deleted file mode 100644 index c1ad7f48d..000000000 --- a/.github/workflows/release-tag-draft.yml +++ /dev/null @@ -1,83 +0,0 @@ -name: Create a release tag - -on: - push: - branches: - - master - paths: - # Release happens only if the version number in main file is updated. - - 'sureforms.php' - -jobs: - build-artifact: - name: Build Release Artifact - runs-on: ubuntu-22.04 - outputs: - current_version: ${{ steps.get_version.outputs.current_version }} - steps: - - name: Checkout code - uses: actions/checkout@v6 - with: - ref: master - - - name: Initialize mandatory git config - run: | - git config user.name "github-actions[bot]" - git config user.email "github-actions[bot]@users.noreply.github.com" - - - name: Compute current version - id: get_version - run: | - CURRENT_VERSION=$(jq --raw-output '.version' package.json) - echo "current_version=${CURRENT_VERSION}" >> $GITHUB_OUTPUT - - - name: Install Node.js and npm - uses: actions/setup-node@v6 - with: - node-version: '18.15.0' - cache: 'npm' - - - name: Install dependencies - run: npm ci --legacy-peer-deps - - - name: Build - run: npm run build - - - name: Build plugin ZIP file - run: bash ./bin/build-zip.sh - - - name: Upload artifact - uses: actions/upload-artifact@v7 - with: - name: sureforms-plugin - path: ./artifact/sureforms.zip - - create-release: - name: Create Release Draft and Attach Asset - needs: [build-artifact] - runs-on: ubuntu-latest - steps: - - name: Set Release Version - id: get_release_version - env: - VERSION: ${{ needs.build-artifact.outputs.current_version }} - run: echo "version=$(echo $VERSION | cut -d / -f 3 | sed 's/-rc./ RC/' )" >> $GITHUB_OUTPUT - - - name: Download Plugin Zip Artifact - uses: actions/download-artifact@v8 - with: - name: sureforms-plugin - - - name: Create Release Draft - id: create_release - uses: softprops/action-gh-release@v2 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - name: Version ${{ steps.get_release_version.outputs.version }} - tag_name: "v${{ steps.get_release_version.outputs.version }}" - target_commitish: master - draft: true - prerelease: false - body: 'Replace changelog here' - files: ./sureforms.zip diff --git a/.github/workflows/update-translations.yml b/.github/workflows/update-translations.yml deleted file mode 100644 index e9943b33b..000000000 --- a/.github/workflows/update-translations.yml +++ /dev/null @@ -1,176 +0,0 @@ -name: Update Translations - -on: - issue_comment: - types: [created] - -# Only allow one i18n job per PR at a time. -concurrency: - group: i18n-${{ github.event.issue.number }} - cancel-in-progress: true - -permissions: - contents: write - pull-requests: write - issues: write - -jobs: - i18n: - if: | - github.event.comment.body == '/i18n' && - github.event.issue.pull_request != null - runs-on: ubuntu-latest - - steps: - # Acknowledge the command with a reaction - - name: Add reaction to comment - uses: peter-evans/create-or-update-comment@v5 - with: - comment-id: ${{ github.event.comment.id }} - reactions: rocket - - # Get PR metadata (head branch, fork detection) - - name: Get PR details - id: pr - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - PR_JSON=$(gh api repos/${{ github.repository }}/pulls/${{ github.event.issue.number }}) - HEAD_REF=$(echo "$PR_JSON" | jq -r '.head.ref') - HEAD_REPO=$(echo "$PR_JSON" | jq -r '.head.repo.full_name') - IS_FORK=$(echo "$PR_JSON" | jq -r '.head.repo.full_name != .base.repo.full_name') - - echo "head_ref=$HEAD_REF" >> "$GITHUB_OUTPUT" - echo "head_repo=$HEAD_REPO" >> "$GITHUB_OUTPUT" - echo "is_fork=$IS_FORK" >> "$GITHUB_OUTPUT" - - # Block fork PRs — secrets are not available - - name: Block fork PRs - if: steps.pr.outputs.is_fork == 'true' - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - gh pr comment "${{ github.event.issue.number }}" \ - --repo "${{ github.repository }}" \ - --body "**i18n update skipped**: This PR is from a fork. Translation updates require repository secrets and cannot run on fork PRs." - exit 1 - - # Notify that the workflow has started - - name: Comment starting - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - gh pr comment "${{ github.event.issue.number }}" \ - --repo "${{ github.repository }}" \ - --body "**Translations update started** :hourglass_flowing_sand: - Building and generating translations for 7 languages (nl, fr, de, es, it, pt, pl)... - [View workflow run](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})" - - # Checkout the actual PR branch (not default branch) - - name: Checkout PR branch - uses: actions/checkout@v6 - with: - ref: ${{ steps.pr.outputs.head_ref }} - fetch-depth: 0 - token: ${{ secrets.GITHUB_TOKEN }} - - - name: Set up Node.js - uses: actions/setup-node@v6 - with: - node-version: '18.15.0' - cache: 'npm' - - - name: Install WP-CLI - run: | - curl -sSfL -o wp-cli.phar 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 - wp --info - - - name: Install dependencies - run: npm ci --legacy-peer-deps - - # Build first so makepot picks up all the latest strings - - name: Build - run: npm run build - - # Run the full i18n pipeline (makepot -> po -> gpt-translate -> mo -> json) - - name: Run i18n script - env: - OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - run: | - set -euo pipefail - bash bin/i18n.sh - - # Check if any files changed - - name: Check for changes - id: changes - run: | - if git diff --quiet; then - echo "changed=false" >> "$GITHUB_OUTPUT" - else - echo "changed=true" >> "$GITHUB_OUTPUT" - CHANGED_FILES=$(git diff --name-only | wc -l | tr -d ' ') - echo "file_count=$CHANGED_FILES" >> "$GITHUB_OUTPUT" - fi - - # Create a separate branch, commit, push, and open a PR - - name: Commit, push, and create PR - if: steps.changes.outputs.changed == 'true' - id: create_pr - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - git config user.name "github-actions[bot]" - git config user.email "github-actions[bot]@users.noreply.github.com" - - BRANCH="i18n/${{ steps.pr.outputs.head_ref }}" - git checkout -b "$BRANCH" - git add . - git commit -m "chore: update i18n translations - - Auto-generated by /i18n command on PR #${{ github.event.issue.number }}" - git push origin "$BRANCH" - - PR_URL=$(gh pr create \ - --title "chore: update i18n translations" \ - --body "This PR updates translation files for 7 languages (nl, fr, de, es, it, pt, pl). - - Triggered by \`/i18n\` command on #${{ github.event.issue.number }}." \ - --base "${{ steps.pr.outputs.head_ref }}" \ - --head "$BRANCH") - - echo "pr_url=$PR_URL" >> "$GITHUB_OUTPUT" - - # Comment on the original PR with a link to the translations PR - - name: Comment success - if: steps.changes.outputs.changed == 'true' - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - gh pr comment "${{ github.event.issue.number }}" \ - --repo "${{ github.repository }}" \ - --body "**Translations PR created** :white_check_mark: - ${{ steps.changes.outputs.file_count }} files changed across 7 languages. - Review and merge: ${{ steps.create_pr.outputs.pr_url }}" - - - name: Comment no changes - if: steps.changes.outputs.changed == 'false' - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - gh pr comment "${{ github.event.issue.number }}" \ - --repo "${{ github.repository }}" \ - --body "**No translation changes** :white_check_mark: - All translation files are already up to date." - - # On any failure, comment with a link to the logs - - name: Comment failure - if: failure() - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - gh pr comment "${{ github.event.issue.number }}" \ - --repo "${{ github.repository }}" \ - --body "**Translation update failed** :x: - [View workflow logs](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) for details." diff --git a/.scripts/git-hooks/pre-commit b/.scripts/git-hooks/pre-commit deleted file mode 100644 index ce0ba23ea..000000000 --- a/.scripts/git-hooks/pre-commit +++ /dev/null @@ -1,106 +0,0 @@ -#!/bin/sh - -# Check PHPCS before commit -# Ref - -# https://github.com/smgladkovskiy/phpcs-git-pre-commit/blob/master/src/pre-commit -# https://dev.to/akdevcraft/git-pre-hook-pre-commit-hook-with-npm-project-44p2 - -echo "***** Running pre-commit ******" - -PROJECT=$(php -r "echo dirname(dirname(dirname(realpath('$0'))));") -STAGED_FILES_CMD=$(git diff --cached --name-only --diff-filter=ACMR HEAD | grep \\.php) -UNSTAGED_FILES_CMD=$(git diff --name-only --diff-filter=ACMR | grep \\.php) - -# Determine if a file list is passed -if [ "$#" -eq 1 ] -then - oIFS=$IFS - IFS=' - ' - SFILES="$1" - IFS=$oIFS -fi - -SFILES=${SFILES:-$STAGED_FILES_CMD} - -STAGED_BUT_MODIFIED_FILES=$(php -r "\$sfiles=(explode(\"\\n\", '$SFILES'));\$usfiles=(explode(\"\\n\", '$UNSTAGED_FILES_CMD'));echo implode(\"\\n\",array_intersect(\$usfiles,\$sfiles));") - -if [ -z "$STAGED_BUT_MODIFIED_FILES" ]; then - echo "OK" -else - echo "Files staged but then modified:\n" - echo "${STAGED_BUT_MODIFIED_FILES}" - exit 1 -fi - -# echo $PROJECT -# echo $SFILES - -echo "Checking files for PHP Lint..." -for FILE in $SFILES -do - # echo "$PROJECT/$FILE" - php -l -d display_errors=0 "./$FILE" - if [ $? != 0 ] - then - echo "Fix the error before commit." - exit 1 - fi - FILES="$FILES ./$FILE" -done - -if [ "$FILES" = "" ] -then - echo "All good..." - exit 0 -fi - -if [ "$FILES" != "" ] -then - echo "Running PHPCS (Code Sniffer) Check..." - composer lint -n $FILES - if [ $? != 0 ] - then - echo "Please fix the PHPCS errors before commit!" - echo " => Run this command for automatic fixes." - echo " composer format-- $FILES" - exit 1 - fi -fi - -if [ "$FILES" != "" ] -then - echo "Running PHPStan Check..." - composer phpstan - if [ $? != 0 ] - then - echo "Please fix the PHPStan errors before commit!" - echo " => Run this command to check PHPStan errors." - echo " composer phpstan" - exit 1 - fi -fi - -if [ "$FILES" != "" ] -then - echo "Running CSS linting issues..." - npm run lint-css - if [ $? != 0 ] - then - echo "Please fix the CSS issues before commit!" - exit 1 - fi -fi - -if [ "$FILES" != "" ] -then - echo "Running JS linting issues..." - npm run lint-js - if [ $? != 0 ] - then - echo "Please fix the JS issues before commit!" - exit 1 - fi -fi - -exit $? diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md deleted file mode 100644 index 2afeea1d5..000000000 --- a/ARCHITECTURE.md +++ /dev/null @@ -1,355 +0,0 @@ -# SureForms Architecture Documentation - -## Table of Contents - -1. [Introduction](#introduction) -2. [System Architecture](#system-architecture) -3. [Core Components](#core-components) -4. [Data Flow](#data-flow) -5. [Form Building Process](#form-building-process) -6. [AI Integration](#ai-integration) -7. [Form Submission and Processing](#form-submission-and-processing) -8. [Security Features](#security-features) -9. [Extension Points](#extension-points) -10. [Technical Debt and Improvement Areas](#technical-debt-and-improvement-areas) -11. [Development Guidelines](#development-guidelines) - -## Introduction - -SureForms is a modern WordPress form builder plugin designed to provide an intuitive, no-code form building experience. It leverages WordPress's native block editor (Gutenberg) to create a seamless form building experience that integrates naturally with the WordPress ecosystem. - -### Key Features - -- **Native WordPress Integration**: Built on top of the WordPress block editor -- **AI-Powered Form Generation**: Create forms quickly using AI suggestions -- **No-Code Flexibility**: Advanced features without requiring coding knowledge -- **Mobile-First Design**: Responsive forms that work across all devices -- **Modern UI/UX**: Clean, intuitive interface for both admins and users -- **Security Features**: Anti-spam protection, GDPR compliance, and data security -- **Extensibility**: Developer-friendly architecture with hooks and filters - -## System Architecture - -SureForms follows a modular architecture pattern, separating concerns into distinct components that interact through well-defined interfaces. - -```mermaid -graph TD - A[WordPress Core] --> B[SureForms Plugin] - B --> C[Admin Interface] - B --> D[Form Builder] - B --> E[Form Renderer] - B --> F[Form Processor] - B --> G[Database Layer] - B --> H[AI Integration] - - C --> I[Settings Management] - C --> J[Form Management] - C --> K[Entry Management] - - D --> L[Block Editor Integration] - D --> M[Form Templates] - D --> N[Field Components] - - E --> O[Frontend Rendering] - E --> P[Validation] - - F --> Q[Submission Handler] - F --> R[Email Notifications] - F --> S[Confirmation Handler] - - G --> T[Custom Post Types] - G --> U[Custom Database Tables] - G --> V[Metadata Storage] - - H --> W[AI Form Generator] - H --> X[AI Middleware] -``` - -## Core Components - -### Plugin Loader (`Plugin_Loader`) - -The central initialization class that bootstraps the plugin, registers hooks, and loads core components. It follows a singleton pattern to ensure only one instance exists. - -### Post Types (`Post_Types`) - -Registers and manages custom post types for forms and entries. Handles the admin UI customizations for these post types. - -### Form Submit (`Form_Submit`) - -Processes form submissions through REST API endpoints, validates input data, handles file uploads, processes anti-spam measures, and triggers email notifications. - -### AI Form Builder (`AI_Form_Builder`) - -Integrates with AI services to generate form structures based on user prompts. Communicates with middleware services to process AI requests. - -### Database Layer - -Custom database tables for storing form entries and related data, separate from the WordPress post tables for better performance and data organization. - -### Frontend Assets (`Frontend_Assets`) - -Manages the loading of CSS and JavaScript assets for the frontend rendering of forms. - -### Email Notifications - -Handles the sending of email notifications based on form submissions, with support for multiple notification templates and recipients. - -## Data Flow - -### Form Creation Flow - -```mermaid -sequenceDiagram - participant User - participant WordPress - participant FormBuilder - participant Database - - User->>WordPress: Access Form Builder - WordPress->>FormBuilder: Initialize Builder Interface - FormBuilder->>User: Display Form Builder UI - - alt Manual Form Creation - User->>FormBuilder: Add/Configure Form Fields - FormBuilder->>User: Update UI Preview - else AI-Assisted Creation - User->>FormBuilder: Enter Form Description - FormBuilder->>AI: Send Form Description - AI->>FormBuilder: Return Suggested Form Structure - FormBuilder->>User: Display AI-Generated Form - User->>FormBuilder: Modify/Approve Form - end - - User->>FormBuilder: Save Form - FormBuilder->>Database: Store Form Configuration - Database->>WordPress: Return Form ID - WordPress->>User: Confirm Form Creation -``` - -### Form Submission Flow - -```mermaid -sequenceDiagram - participant User - participant Frontend - participant REST_API - participant Validation - participant AntiSpam - participant Database - participant EmailSystem - - User->>Frontend: Fill Form - Frontend->>User: Validate Client-Side - User->>Frontend: Submit Form - Frontend->>REST_API: POST Form Data - - REST_API->>Validation: Validate Data - Validation->>REST_API: Validation Result - - REST_API->>AntiSpam: Check for Spam - AntiSpam->>REST_API: Spam Check Result - - alt Valid Submission - REST_API->>Database: Store Entry - Database->>REST_API: Entry ID - REST_API->>EmailSystem: Trigger Notifications - EmailSystem->>REST_API: Email Status - REST_API->>Frontend: Success Response - Frontend->>User: Show Confirmation - else Invalid Submission - REST_API->>Frontend: Error Response - Frontend->>User: Show Error Message - end -``` - -## Form Building Process - -SureForms uses WordPress's block editor as the foundation for its form builder. This approach provides several advantages: - -1. **Familiar Interface**: Users already familiar with WordPress's editor can easily adapt -2. **Native Integration**: Seamless integration with WordPress core functionality -3. **Extensibility**: Ability to leverage the block ecosystem - -### Block Structure - -Forms are composed of various block types: - -- **Container Blocks**: Group and organize form fields -- **Field Blocks**: Individual form inputs (text, email, checkbox, etc.) -- **Layout Blocks**: Control the visual arrangement of fields -- **Special Blocks**: Submit buttons, GDPR notices, etc. - -Each block has its own edit and save components, following the WordPress block API pattern. - -### Form Data Storage - -Form configurations are stored as custom post types with: - -- Post content: Stores the block structure (serialized blocks) -- Post meta: Stores form settings, styling options, and other configuration data - -## AI Integration - -SureForms features an AI-powered form generation system that allows users to create forms by describing them in natural language. - -```mermaid -graph TD - A[User Input] --> B[AI Middleware] - B --> C[AI Service] - C --> D[Form Structure Generation] - D --> E[Field Mapping] - E --> F[Block Generation] - F --> G[Form Preview] - G --> H[User Edits] - H --> I[Final Form] -``` - -### AI Form Generation Process - -1. User provides a description of the desired form -2. The description is sent to the AI middleware -3. AI analyzes the description and generates a structured form definition -4. The form definition is mapped to SureForms field types -5. Blocks are generated and inserted into the editor -6. User can review and modify the generated form - -## Form Submission and Processing - -### Submission Handling - -Form submissions are processed through a custom REST API endpoint that: - -1. Validates the form data against defined rules -2. Checks for spam using various methods (honeypot, reCAPTCHA, etc.) -3. Processes file uploads if present -4. Stores the submission in the database -5. Triggers email notifications -6. Returns appropriate success/error responses - -### Email Notifications - -The email notification system supports: - -- Multiple notification templates per form -- Dynamic content using smart tags -- HTML email formatting -- Conditional sending based on form data -- Custom headers (CC, BCC, Reply-To) - -```mermaid -graph TD - A[Form Submission] --> B[Email Notification System] - B --> C{Multiple Recipients?} - C -->|Yes| D[Process Each Recipient] - C -->|No| E[Single Email] - D --> F[Parse Email Template] - E --> F - F --> G[Replace Smart Tags] - G --> H[Apply Email Template] - H --> I[Send Email] - I --> J{Success?} - J -->|Yes| K[Log Success] - J -->|No| L[Log Failure] -``` - -## Security Features - -SureForms implements multiple security measures to protect against common vulnerabilities: - -### Anti-Spam Protection - -- **Honeypot Fields**: Hidden fields to catch automated submissions -- **reCAPTCHA Integration**: Multiple versions of Google reCAPTCHA -- **hCaptcha Support**: Alternative to reCAPTCHA -- **Cloudflare Turnstile**: Modern CAPTCHA alternative - -### Data Protection - -- **GDPR Compliance**: Options to enable GDPR-compliant data handling -- **Data Encryption**: Sensitive data can be encrypted in storage -- **Auto-Delete Entries**: Automatic deletion of entries after a specified period - -### Input Validation - -- **Client-Side Validation**: Immediate feedback to users -- **Server-Side Validation**: Thorough validation of all submitted data -- **File Upload Security**: Strict file type and size validation - -## Extension Points - -SureForms provides several extension points for developers: - -### WordPress Hooks - -```php -// Example of filter hook for email notification -add_filter('srfm_email_notification', function($parsed, $submission_data, $item, $form_data) { - // Modify email content or recipients - return $parsed; -}, 10, 4); - -// Example of action hook before form submission -add_action('srfm_before_submission', function($form_data) { - // Perform custom actions before form processing -}); -``` - -### JavaScript API - -```javascript -// Example of extending the form validation -window.sureFormsHooks.addFilter( - 'srfm.validation.rules', - 'my-plugin/custom-validation', - function(rules, fieldData) { - // Add custom validation rules - return rules; - } -); -``` - -## Technical Debt and Improvement Areas - -1. **Performance Optimization**: - - Lazy loading of form assets - - Improved caching strategies - -2. **Code Refactoring**: - - Further modularization of components - - Consistent naming conventions - -3. **Testing Coverage**: - - Increase unit and integration test coverage - - Automated UI testing - -## Development Guidelines - -### Coding Standards - -SureForms follows WordPress coding standards with some additional guidelines: - -- PHP: PSR-12 with WordPress-specific adaptations -- JavaScript: ESLint with WordPress configuration -- CSS: Follows WordPress CSS coding standards - -### Development Workflow - -1. **Feature Planning**: Document requirements and design -2. **Development**: Implement features with appropriate tests -3. **Code Review**: Peer review for quality assurance -4. **Testing**: Automated and manual testing -5. **Documentation**: Update technical and user documentation -6. **Release**: Version tagging and deployment - -### Version Control - -- Feature branches for new development -- Pull request workflow for code review -- Semantic versioning for releases - -## Conclusion - -SureForms represents a modern approach to WordPress form building, combining the power of the block editor with advanced features like AI form generation. Its modular architecture and extensive extension points make it both user-friendly and developer-friendly, while its focus on security and performance ensures a reliable experience for all users. - -The plugin continues to evolve with a focus on improving user experience, expanding integration capabilities, and optimizing performance across all devices and platforms. diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index cf66c59fc..000000000 --- a/CLAUDE.md +++ /dev/null @@ -1,165 +0,0 @@ -# SureForms - CLAUDE.md - -## Project Overview -SureForms is a WordPress form builder plugin (v2.5.1) by Brainstorm Force. AI-powered drag-and-drop form building using the Gutenberg block editor. - -- **Plugin slug:** `sureforms` | **Text domain:** `sureforms` -- **Prefix:** `SRFM_` (constants), `srfm` (slug), `sureforms_` (post types/DB) -- **Minimum PHP:** 7.4 | **Minimum WP:** 6.4 - -## Tech Stack -- **Backend:** PHP 7.4+ / WordPress Plugin API / Custom REST endpoints -- **Frontend:** React 18 + WordPress Gutenberg blocks -- **Styling:** TailwindCSS 3.4 + SASS + PostCSS -- **Build:** WordPress Scripts (Webpack 5) + Grunt -- **Testing:** PHPUnit 9 (unit) + Playwright (E2E) -- **Static Analysis:** PHPStan level 9 + PHPCS (WordPress-Extra) -- **Node:** 18.15.0 (Volta) | **UI Library:** @bsf/force-ui - -## Commands - -### Build -```bash -npm run start # Dev server with watch -npm run build # Full production build -npm run build:script # Webpack only -npm run build:sass # SASS only -``` - -### Lint & Format -```bash -npm run lint-js # ESLint -npm run lint-js:fix # ESLint auto-fix -npm run lint-css # Stylelint -composer lint # PHPCS -composer format # PHPCBF auto-fix -composer phpstan # PHPStan level 9 -composer insights # PHP Insights -``` - -### Test -```bash -composer test # PHPUnit -composer test:coverage # PHPUnit with coverage -npm run test:unit # JS unit tests -npm run play:up # Start WP test env -npm run play:run # Playwright E2E -npm run play:stop # Stop WP test env -``` - -### i18n -```bash -npm run makepot # Generate .pot -npm run i18n:po # Update .po from .pot -npm run i18n:mo # Compile .mo -npm run i18n:json # JSON translations -``` - -## Architecture - -### Directory Structure -``` -sureforms/ -├── sureforms.php # Entry point, constants -├── plugin-loader.php # Bootstrap -├── inc/ # PHP backend -│ ├── helper.php # Central utility (large — minimize changes) -│ ├── rest-api.php # REST endpoints -│ ├── form-submit.php # Submission handler -│ ├── entries.php # Entry management -│ ├── post-types.php # CPT registration -│ ├── blocks/ # PHP block rendering -│ ├── fields/ # Field type handlers -│ ├── database/ # Custom DB tables -│ ├── payments/ # Stripe integration -│ ├── ai-form-builder/ # AI form generation -│ ├── global-settings/ # Plugin settings -│ ├── page-builders/ # Elementor/Bricks compat -│ └── lib/ # Third-party (DO NOT modify) -├── src/ # React/JS source -│ ├── admin/ # Admin UI -│ ├── blocks/ # Gutenberg block JS -│ ├── components/ # Shared React components -│ ├── store/ # WordPress data store -│ ├── utils/ # JS utilities -│ └── srfm-controls/ # Custom block controls -├── assets/ # Compiled output (gitignored) -├── sass/ # SASS source -├── modules/ # Feature modules -├── templates/ # PHP templates -├── tests/ # PHPUnit + Playwright + Docker -└── languages/ # Translation files -``` - -### Webpack Aliases -``` -@Admin → src/admin/ @Blocks → src/blocks/ @Controls → src/srfm-controls/ -@Components → src/components/ @Utils → src/utils/ @Svg → assets/svg/ -@Attributes → src/blocks-attributes/ @Image → images/ @IncBlocks → inc/blocks/ -``` - -### Key Data Structures -- **Post Type:** `sureforms_form` — Forms as CPT with block content -- **Custom Tables:** `sureforms_entries`, `sureforms_payments` -- **REST Namespace:** Custom endpoints in `inc/rest-api.php` - -## Code Rules - -### PHP -- Follow WPCS. Use `sureforms` text domain for all translatable strings -- `@since x.x.x` on all new functions/classes (updated in release PRs) -- NEVER `echo` without escaping — use `esc_html()`, `esc_attr()`, `wp_kses_post()` -- NEVER use `$_GET/$_POST/$_REQUEST` directly — use `sanitize_text_field( wp_unslash( ... ) )` -- NEVER skip security verification on endpoints/AJAX handlers - - **Public form submission endpoints** use HMAC tokens via `Submit_Token::verify()` (`inc/submit-token.php`) — NOT nonces. These are cache-safe and session-independent. The `// phpcs:ignore WordPress.Security.NonceVerification.Missing` comment is expected on these handlers. - - **Admin/authenticated endpoints** still use traditional nonces (`wp_verify_nonce()` / `check_ajax_referer()`) -- NEVER skip capability checks — use `current_user_can()` before privileged operations -- NEVER use `wp_die()` in REST callbacks — use `WP_Error` with proper response codes -- NEVER hardcode table names — use `$wpdb->prefix . 'sureforms_entries'` -- ALWAYS use `wp_json_encode()`, `wp_remote_get/post()`, `gmdate()`, `wp_safe_redirect()` - -### JavaScript/React -- Follow WordPress Scripts ESLint config -- Use WordPress data stores (`useSelect`/`useDispatch`) — never raw fetch in blocks -- Import from `@wordpress/*` packages — never import React directly -- Use `__()` from `@wordpress/i18n` — never hardcode user-facing strings -- Use TailwindCSS utility classes; use `@bsf/force-ui` for admin UI -- NEVER use `dangerouslySetInnerHTML` — use `RawHTML` from `@wordpress/element` - -### General -- NEVER create files unless absolutely necessary — prefer editing existing files -- NEVER proactively create documentation files unless explicitly requested - -## Gotchas -- **Custom DB tables** introduced in v0.0.13 — migration is irreversible -- **PHPStan level 9** is strict; check baseline before adding new ignores -- **Grunt** still used alongside Webpack for CSS minification and release packaging -- **`inc/lib/`** is third-party code — do not lint or modify -- **Node 18.15.0** pinned via Volta — other versions may cause build issues - -## Verification Before Done -After code changes, verify before reporting done: - -**JS:** `npm run lint-js` → `npm run build:script` -**SASS:** `npm run build:sass` (if touched) - -Checklist: -- Re-read the diff for obvious issues -- No debug code left (`console.log`, `error_log`, `var_dump`) -- All new functions have `@since x.x.x` -- All user-facing strings use `__()` / `_e()` -- Security checks on new endpoints/handlers (HMAC token for public, nonce for admin) -- For significant changes, suggest `npm run play:run` - -## Self-Improvement Loop -- When corrected, add a rule to **Learned Rules** so the mistake never repeats -- When a pattern causes a bug or CI failure, document it immediately -- Periodically prune outdated rules - -## Learned Rules - -- NEVER flag `phpcs:ignore WordPress.Security.NonceVerification.Missing` as a security issue on public form submission handlers (form submit, field validation, Stripe/PayPal payment intents) — these use HMAC token verification (`Submit_Token::verify()`) instead of nonces for page-cache compatibility. The HMAC token is embedded in the form at render time and verified server-side without any session dependency. -- ALWAYS use `Submit_Token::generate($form_id)` / `Submit_Token::verify($token, $form_id)` for public-facing form security — nonces (`wp_verify_nonce`) are only for admin/authenticated endpoints. - -## Current Focus - diff --git a/COMPREHENSIVE_ANALYSIS.md b/COMPREHENSIVE_ANALYSIS.md deleted file mode 100644 index aed786d38..000000000 --- a/COMPREHENSIVE_ANALYSIS.md +++ /dev/null @@ -1,304 +0,0 @@ -# SureForms: Comprehensive Analysis - -This document provides a multi-perspective analysis of the SureForms WordPress plugin, examining it from software architecture, development, and product management viewpoints. - -## Table of Contents - -1. [Software Architecture Analysis](#software-architecture-analysis) -2. [Development Perspective](#development-perspective) -3. [Product Management Analysis](#product-management-analysis) -4. [Integration Capabilities](#integration-capabilities) -5. [Future Development Roadmap](#future-development-roadmap) - -## Software Architecture Analysis - -### Core Architecture - -SureForms follows a modular architecture pattern with clear separation of concerns. The plugin is built around several key components: - -```mermaid -graph TD - A[WordPress Core] --> B[SureForms Plugin] - B --> C[Plugin_Loader] - C --> D[Core Components] - D --> E[Post_Types] - D --> F[Form_Submit] - D --> G[Block_Patterns] - D --> H[Frontend_Assets] - D --> I[AI_Form_Builder] - D --> J[Rest_Api] - D --> K[Database] - K --> L[Custom Tables] - K --> M[Post Meta] -``` - -The architecture leverages WordPress's plugin system and follows object-oriented principles with extensive use of the singleton pattern for core components. - -### Data Flow Architecture - -The data flow within SureForms follows a clear pattern: - -```mermaid -sequenceDiagram - participant User - participant Frontend - participant BlockEditor - participant REST_API - participant Database - - User->>BlockEditor: Create Form - BlockEditor->>Database: Store Form Configuration - User->>Frontend: View & Submit Form - Frontend->>REST_API: Submit Form Data - REST_API->>Database: Store Submission - REST_API->>Frontend: Return Response -``` - -This separation ensures clean data handling and allows for extensibility at various points in the process. - -### Component Analysis - -#### Plugin Loader - -The `Plugin_Loader` class serves as the entry point for the plugin, handling initialization, autoloading, and hook registration. It follows the singleton pattern to ensure only one instance exists. - -#### Post Types - -The `Post_Types` class manages custom post types for forms and entries, including admin UI customizations, shortcode functionality, and metadata registration. - -#### Form Submit - -The `Form_Submit` class processes form submissions through REST API endpoints, handling validation, file uploads, anti-spam measures, and email notifications. - -#### Database Layer - -SureForms uses both WordPress custom post types and custom database tables: -- Custom post type `sureforms_form` for form configurations -- Custom table `{prefix}_srfm_entries` for form submissions - -This hybrid approach leverages WordPress's content management for forms while optimizing data storage for submissions. - -#### AI Integration - -The AI form builder component connects with external AI services through a middleware layer, translating natural language descriptions into structured form definitions. - -### Technical Debt Assessment - -Current areas of technical debt include: - -1. **Performance Optimization** - - Opportunity for more aggressive asset loading strategies - - Potential for improved caching mechanisms - -2. **Code Organization** - - Some components have grown large and could benefit from further modularization - - Inconsistent naming conventions in some areas - -3. **Testing Coverage** - - Limited automated testing for JavaScript components - - Opportunity for more comprehensive integration tests - -## Development Perspective - -### Code Quality - -The codebase demonstrates several positive qualities: - -- **Consistent Structure**: Well-organized directory structure -- **Modern Practices**: Use of namespaces, autoloading, and OOP principles -- **Documentation**: Comprehensive inline documentation -- **Separation of Concerns**: Clear boundaries between components - -Areas for improvement include: - -- **Testing Coverage**: Expanding unit and integration tests -- **Consistent Naming**: Standardizing naming conventions across all components -- **Performance Profiling**: Identifying and addressing performance bottlenecks - -### Development Workflow - -The development process appears to follow modern practices: - -- **Version Control**: Git-based workflow with feature branches -- **Code Review**: Evidence of peer review processes -- **Continuous Integration**: GitHub Actions for automated testing -- **Semantic Versioning**: Clear versioning strategy - -### Extension Points - -SureForms provides several extension mechanisms: - -1. **WordPress Hooks** - - Actions for process intervention - - Filters for data modification - -2. **JavaScript API** - - Client-side hooks for extending functionality - - Custom events for integration - -3. **Block API** - - Ability to register custom form field blocks - - Block filters for modifying existing blocks - -4. **Template System** - - Customizable templates for form rendering - - Theme override capabilities - -### Technology Stack - -The plugin leverages a modern technology stack: - -- **PHP**: Core server-side logic -- **JavaScript/React**: Block editor integration and frontend functionality -- **CSS/SCSS**: Styling with preprocessor support -- **MySQL**: Database storage -- **REST API**: Data communication -- **AI Services**: Form generation capabilities - -## Product Management Analysis - -### User Segments - -SureForms targets several distinct user segments: - -1. **Website Owners** - - Need: Simple form creation without technical knowledge - - Value: Intuitive interface, pre-designed templates - -2. **Designers** - - Need: Visually appealing forms that match site design - - Value: Design customization, aesthetic controls - -3. **Developers** - - Need: Extensible platform with clean APIs - - Value: Hooks, filters, and documentation - -4. **No-Code Professionals** - - Need: Advanced functionality without coding - - Value: Conditional logic, multi-step forms - -### Feature Analysis - -The feature set is well-aligned with user needs: - -| Feature | User Segment | Value Proposition | -|---------|--------------|-------------------| -| Block Editor Integration | All | Familiar, native WordPress experience | -| AI Form Generation | All | Rapid form creation with minimal effort | -| Mobile-First Design | All | Forms work well on all devices | -| Advanced Field Types | No-Code Professionals | Complex form capabilities without coding | -| Developer Hooks | Developers | Extensibility for custom needs | -| Visual Customization | Designers | Forms match site aesthetics | -| Anti-Spam Features | All | Protection from spam submissions | -| GDPR Compliance | All | Legal compliance and data protection | - -### Competitive Positioning - -SureForms differentiates itself through: - -1. **Native WordPress Integration**: Using the block editor rather than a custom interface -2. **AI-Powered Creation**: Faster form building through AI assistance -3. **Design Focus**: Emphasis on visual appeal and user experience -4. **Developer-Friendly**: Clean architecture and extension points - -### Market Fit - -The product demonstrates strong market fit by addressing several key pain points: - -1. **Complex Form Building**: Simplifying the process through AI and intuitive interface -2. **Design Limitations**: Providing modern styling out-of-the-box -3. **Mobile Responsiveness**: Ensuring forms work well on all devices -4. **Technical Barriers**: Enabling advanced features without coding requirements - -## Integration Capabilities - -### WordPress Ecosystem - -SureForms integrates well with the WordPress ecosystem: - -- **Themes**: Compatible with major themes including Astra, Kadence, GeneratePress -- **Page Builders**: Works with Elementor, Beaver Builder, Divi -- **Plugins**: Compatible with popular plugins like WooCommerce, Easy Digital Downloads - -### External Services - -The plugin offers integration with several external services: - -- **reCAPTCHA**: Anti-spam protection -- **hCaptcha**: Alternative CAPTCHA solution -- **Cloudflare Turnstile**: Modern CAPTCHA alternative -- **AI Services**: Form generation capabilities - -### API Architecture - -The API architecture facilitates integration: - -```mermaid -graph LR - A[WordPress] --> B[SureForms Core] - B --> C[REST API] - C --> D[External Integrations] - D --> E[CRM Systems] - D --> F[Email Marketing] - D --> G[Payment Processors] - D --> H[AI Services] -``` - -This architecture allows for flexible integration with various third-party services. - -## Future Development Roadmap - -Based on the analysis, several development priorities emerge: - -### Short-Term Priorities - -1. **Performance Optimization** - - Implement lazy loading for form assets - - Optimize database queries for large form submissions - -2. **Code Quality Improvements** - - Increase test coverage - - Standardize naming conventions - - Refactor larger components - -3. **Integration Expansion** - - Add more third-party service integrations - - Enhance existing integrations with deeper functionality - -### Medium-Term Priorities - -1. **Advanced AI Capabilities** - - Improve form generation accuracy - - Add form analytics and insights - -2. **Enhanced User Experience** - - Streamline the form building process - - Improve form submission handling - -3. **Developer Tools** - - Create comprehensive API documentation - - Develop example extensions - -### Long-Term Vision - -1. **Form Ecosystem** - - Develop a marketplace for extensions - - Create specialized form solutions for different industries - -2. **Enterprise Features** - - Advanced workflow automation - - Enhanced security and compliance features - -3. **SaaS Potential** - - Explore hosted form solution alongside WordPress plugin - - Develop cloud-based form management - -## Conclusion - -SureForms represents a modern approach to WordPress form building, combining native block editor integration with AI-powered form generation. Its architecture demonstrates good separation of concerns and extensibility, while its feature set addresses key user needs across multiple segments. - -The product is well-positioned in the competitive form builder market, with clear differentiation through its WordPress integration, AI capabilities, and design focus. Future development should focus on expanding integrations, enhancing AI capabilities, and improving performance to maintain this competitive advantage. - -From a technical perspective, the codebase is well-structured but would benefit from increased test coverage and some refactoring of larger components. The extension system provides good flexibility for developers, though more comprehensive documentation would enhance this further. - -Overall, SureForms shows strong potential for continued growth and adoption, particularly as the WordPress ecosystem continues to embrace the block editor and AI-powered tools become increasingly important in the website building process. diff --git a/Gruntfile.js b/Gruntfile.js index 7e2e42f1e..74032f045 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -12,6 +12,11 @@ module.exports = function ( grunt ) { sourcemap: 'none', outputStyle: 'expanded', linefeed: 'lf', + silenceDeprecations: [ + 'legacy-js-api', + 'import', + 'global-builtin', + ], }, dist: { files: [ @@ -32,7 +37,7 @@ module.exports = function ( grunt ) { map: false, processors: [ autoprefixer( { - browsers: [ + overrideBrowserslist: [ '> 1%', 'ie >= 11', 'last 1 Android versions', diff --git a/PRODUCT_ANALYSIS.md b/PRODUCT_ANALYSIS.md deleted file mode 100644 index a6c4e595e..000000000 --- a/PRODUCT_ANALYSIS.md +++ /dev/null @@ -1,251 +0,0 @@ -# SureForms Product Analysis - -## Executive Summary - -SureForms is a modern WordPress form builder plugin that differentiates itself through its native WordPress integration, AI-powered form generation, and focus on user experience. This analysis examines the product from multiple perspectives to provide a comprehensive understanding of its strengths, challenges, and opportunities for growth. - -## Table of Contents - -1. [Product Overview](#product-overview) -2. [Market Analysis](#market-analysis) -3. [User Experience Analysis](#user-experience-analysis) -4. [Technical Analysis](#technical-analysis) -5. [Competitive Analysis](#competitive-analysis) -6. [SWOT Analysis](#swot-analysis) -7. [Growth Opportunities](#growth-opportunities) -8. [Recommendations](#recommendations) - -## Product Overview - -SureForms is a WordPress form builder plugin that leverages the native WordPress block editor (Gutenberg) to provide an intuitive form building experience. Key features include: - -- **Native WordPress Integration**: Built on top of the WordPress block editor -- **AI-Powered Form Generation**: Create forms quickly using AI suggestions -- **No-Code Flexibility**: Advanced features without requiring coding knowledge -- **Mobile-First Design**: Responsive forms that work across all devices -- **Modern UI/UX**: Clean, intuitive interface for both admins and users -- **Security Features**: Anti-spam protection, GDPR compliance, and data security -- **Extensibility**: Developer-friendly architecture with hooks and filters - -The plugin is currently at version 1.7.0 and requires WordPress 6.4+ and PHP 7.4+. - -## Market Analysis - -### Target Audience - -SureForms targets several key user segments: - -1. **Website Owners**: Individuals and businesses who manage their own WordPress websites and need to collect information from visitors -2. **Designers**: Professionals who value good design and want to create visually appealing forms -3. **Developers**: Technical users who need a developer-friendly solution with clean APIs and hooks -4. **No-Code Professionals**: Users who need advanced form features without coding skills - -### Market Positioning - -SureForms positions itself as a modern alternative to traditional form builders, emphasizing: - -1. **Seamless WordPress Integration**: Using the native block editor rather than a separate interface -2. **Design-First Approach**: Focusing on aesthetics and user experience -3. **AI-Powered Efficiency**: Leveraging AI to speed up form creation -4. **Simplicity Without Compromise**: Providing advanced features in an accessible way - -### Market Trends - -Several trends in the WordPress form builder market are relevant to SureForms: - -1. **Shift to Block Editor**: Growing adoption of Gutenberg and block-based themes -2. **AI Integration**: Increasing use of AI for content and design generation -3. **Mobile-First Design**: Continued emphasis on mobile responsiveness -4. **Privacy Compliance**: Growing importance of GDPR and other privacy regulations -5. **No-Code Movement**: Rising demand for powerful tools that don't require coding skills - -## User Experience Analysis - -### Form Creation Experience - -SureForms provides a streamlined form creation experience: - -- **Block-Based Building**: Drag-and-drop interface using familiar WordPress blocks -- **AI Form Generation**: Natural language prompts to quickly create form structures -- **Visual Editing**: Real-time preview of forms as they're built -- **Templates**: Pre-designed form templates for common use cases - -### Form Submission Experience - -The end-user experience for form submission is optimized for: - -- **Responsive Design**: Forms adapt to different screen sizes -- **Inline Validation**: Real-time feedback on form inputs -- **Accessibility**: Support for screen readers and keyboard navigation -- **Confirmation Messages**: Customizable success messages and redirects - -### Admin Experience - -The admin interface focuses on: - -- **Intuitive Management**: Easy access to forms, entries, and settings -- **Data Visualization**: Visual reporting of form submission data -- **Entry Management**: Tools for viewing, filtering, and exporting submissions -- **Email Notifications**: Customizable email alerts for new submissions - -## Technical Analysis - -### Architecture - -SureForms follows a modular architecture with clear separation of concerns: - -- **Core Plugin**: Handles initialization, hooks, and basic functionality -- **Block System**: Manages form field blocks and their behavior -- **Form Processing**: Handles form submissions and data storage -- **AI Integration**: Connects with AI services for form generation -- **Extension System**: Provides hooks and filters for customization - -### Performance - -The plugin is designed with performance in mind: - -- **Optimized Asset Loading**: CSS and JS loaded only when needed -- **Efficient Database Usage**: Custom tables with appropriate indexes -- **Caching Strategies**: Caching of frequently accessed data -- **Minimal Dependencies**: Limited reliance on external libraries - -### Security - -Security features include: - -- **Input Validation**: Thorough validation of all user inputs -- **Anti-Spam Measures**: Multiple options for spam prevention -- **Data Protection**: GDPR compliance features -- **File Upload Security**: Strict validation of uploaded files - -### Extensibility - -The plugin provides several extension points: - -- **WordPress Hooks**: Actions and filters for modifying behavior -- **JavaScript API**: Client-side hooks for extending functionality -- **Block API**: Ability to create custom form field blocks -- **Template System**: Customizable templates for form rendering - -## Competitive Analysis - -### Key Competitors - -1. **Gravity Forms**: Established premium form builder with extensive features -2. **WPForms**: User-friendly form builder with a focus on simplicity -3. **Formidable Forms**: Advanced form builder with data management features -4. **Ninja Forms**: Modular form builder with add-on marketplace -5. **Contact Form 7**: Simple, free form builder with large user base - -### Competitive Advantages - -SureForms differentiates itself through: - -1. **Native Block Editor Integration**: More seamless WordPress experience -2. **AI-Powered Form Creation**: Faster form building process -3. **Modern Design Focus**: Better out-of-the-box aesthetics -4. **Developer-Friendly Architecture**: Clean APIs and extension points -5. **Mobile-First Approach**: Better experience on mobile devices - -### Competitive Challenges - -Areas where competitors may have advantages: - -1. **Ecosystem Maturity**: Established competitors have larger add-on ecosystems -2. **Market Recognition**: Lower brand awareness as a newer entrant -3. **Feature Depth**: Some competitors have more specialized features -4. **Integration Breadth**: Fewer third-party service integrations - -## SWOT Analysis - -### Strengths - -- Native integration with WordPress block editor -- AI-powered form generation capabilities -- Modern, clean design aesthetic -- Mobile-first responsive approach -- Developer-friendly architecture -- Focus on user experience - -### Weaknesses - -- Newer entrant in a mature market -- Smaller ecosystem of extensions and add-ons -- Limited third-party integrations compared to competitors -- Requires newer versions of WordPress and PHP - -### Opportunities - -- Growing adoption of the WordPress block editor -- Increasing demand for AI-powered tools -- Rising importance of mobile-friendly forms -- Expanding market for no-code solutions -- Potential for vertical-specific form solutions - -### Threats - -- Established competitors with loyal user bases -- WordPress core changes affecting block editor functionality -- Potential AI regulation affecting AI form generation -- Market commoditization driving price competition -- Alternative form solutions outside WordPress ecosystem - -## Growth Opportunities - -### Product Development - -1. **Expanded AI Capabilities**: More sophisticated form generation and analysis -2. **Vertical-Specific Templates**: Forms tailored to specific industries or use cases -3. **Advanced Conditional Logic**: More powerful dynamic form behavior -4. **Enhanced Data Analysis**: Better visualization and reporting of form data -5. **Multi-Step Form Improvements**: More sophisticated multi-page form experiences - -### Market Expansion - -1. **Agency Partner Program**: Dedicated resources for agencies and developers -2. **Vertical Marketing**: Targeted solutions for specific industries -3. **Educational Content**: Tutorials and resources to drive adoption -4. **Integration Partnerships**: Collaborations with complementary services -5. **International Expansion**: Localization for key markets - -### Business Model - -1. **Freemium Model**: Free core plugin with premium add-ons or features -2. **Subscription Tiers**: Different service levels for different user needs -3. **White-Label Solutions**: Customizable versions for agencies and resellers -4. **Enterprise Offerings**: Custom solutions for larger organizations -5. **Marketplace**: Platform for third-party extensions - -## Recommendations - -### Short-Term (0-6 months) - -1. **Expand Integration Ecosystem**: Add connections to popular CRM and email marketing platforms -2. **Enhance AI Form Builder**: Improve accuracy and capabilities of AI form generation -3. **Develop Educational Content**: Create tutorials and documentation to drive adoption -4. **Optimize Performance**: Further improve loading speed and resource usage -5. **Implement User Feedback System**: Gather structured feedback from early adopters - -### Medium-Term (6-12 months) - -1. **Launch Partner Program**: Develop resources for agencies and developers -2. **Create Vertical Solutions**: Develop specialized templates for key industries -3. **Expand Block Library**: Add more specialized form field types -4. **Improve Analytics**: Enhance data visualization and reporting capabilities -5. **Develop Extension Marketplace**: Create platform for third-party add-ons - -### Long-Term (12+ months) - -1. **Develop Enterprise Features**: Add capabilities for larger organizations -2. **Explore SaaS Model**: Consider hosted form solution alongside WordPress plugin -3. **Implement Advanced AI**: Add predictive analytics and personalization -4. **Create Form Ecosystem**: Develop complementary products and services -5. **Explore International Markets**: Localize for key global markets - -## Conclusion - -SureForms represents a modern approach to WordPress form building, combining the power of the native block editor with AI-powered form generation. Its focus on user experience, design, and developer-friendly architecture positions it well in the competitive form builder market. - -By leveraging its strengths in WordPress integration and AI capabilities while addressing its challenges in market recognition and ecosystem development, SureForms has significant potential for growth. The recommended strategies focus on expanding integrations, enhancing AI capabilities, developing educational resources, and creating specialized solutions for key market segments. - -With continued development and strategic focus, SureForms can establish itself as a leading WordPress form solution for the modern web. diff --git a/README.md b/README.md index 2cb76add9..4e348ffe6 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ **Requires at least:** 6.4 **Tested up to:** 6.9.4 **Requires PHP:** 7.4 -**Stable tag:** 2.8.1 +**Stable tag:** 2.8.2 **License:** GPLv2 or later **License URI:** http://www.gnu.org/licenses/gpl-2.0.html @@ -478,6 +478,13 @@ You can collect payments securely through Stripe in the free version. PayPal pay You can report the issue 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.8.2 - 5th May 2026 ### +* New: Added "Both" payment type so a single form can collect one-time and subscription payments together. +* New: Added Hidden field support for the payment block's dynamic amount. +* New: Added minimum character limit support for the Textarea field. +* Improvement: Added extension hooks for windowed entry caps in form restriction. +* Fix: Fixed AI Form Builder silent failures and replaced generic error messages with clearer feedback. +* Fix: Resolved an issue where the Confirm Email field could silently block form submission when the Email field was not marked as required. ### 2.8.1 - 27th April 2026 ### * New: Added support for dynamic default values on Dropdown and Multi-Choice fields. * New: Added {entry_id} smart tag for use in email templates, confirmations, and dynamic content. @@ -493,15 +500,6 @@ You can report the issue through our [Bug Bounty Program](https://brainstormforc * Fix: Fixed crash when saving a form containing the Register block. * Fix: Fixed inability to deselect a preselected option in single-selection controls (radio, dropdown) within the editor. * Fix: Fixed Quill rich text editor toolbar strings not being translatable. -### 2.7.1 - 9th April 2026 ### -* New: Added a customizable Field Slug panel to all form blocks. -* New: Added Payment Description field to the Stripe payment block with smart tag support. -* Fix: Fixed Elementor form title toggle working in reverse. -* Fix: Fixed non-Latin character field labels generating unstable slugs that broke conditional confirmation logic. -* Fix: Fixed PHP warnings for undefined array keys in compliance settings and AI field mapping. -* Fix: Fixed slugs with underscores not mapping correctly during smart tag and integration processing. -* Fix: Fixed textarea values losing line breaks in {form:field} smart tags. -* Fix: Fixed {current_page_url} smart tag resolving to REST API URL in email notifications. The full changelog is available [here](https://sureforms.com/whats-new/). ## Upgrade Notice ## diff --git a/TECHNICAL_OVERVIEW.md b/TECHNICAL_OVERVIEW.md deleted file mode 100644 index 9d2d44140..000000000 --- a/TECHNICAL_OVERVIEW.md +++ /dev/null @@ -1,393 +0,0 @@ -# SureForms Technical Overview - -## Introduction - -SureForms is a modern WordPress form builder plugin that leverages the native WordPress block editor (Gutenberg) to provide an intuitive, no-code form building experience. This document provides a comprehensive technical overview of the plugin's architecture, components, and functionality. - -## Table of Contents - -1. [Plugin Architecture](#plugin-architecture) -2. [Core Components](#core-components) -3. [Database Structure](#database-structure) -4. [Form Building System](#form-building-system) -5. [Form Submission Process](#form-submission-process) -6. [AI Integration](#ai-integration) -7. [Security Features](#security-features) -8. [Extension Points](#extension-points) -9. [Performance Considerations](#performance-considerations) -10. [Future Development](#future-development) - -## Plugin Architecture - -SureForms follows a modular architecture pattern with clear separation of concerns. The plugin is structured around several key components that interact through well-defined interfaces. - -### Directory Structure - -``` -sureforms/ -├── admin/ # Admin-specific functionality -├── api/ # REST API endpoints -├── assets/ # CSS, JS, and other assets -├── inc/ # Core functionality -│ ├── ai-form-builder/ # AI form generation -│ ├── blocks/ # Block registration -│ ├── compatibility/ # Theme/plugin compatibility -│ ├── database/ # Custom database tables -│ ├── email/ # Email notification system -│ ├── fields/ # Form field definitions -│ ├── global-settings/ # Global plugin settings -│ ├── lib/ # Third-party libraries -│ ├── page-builders/ # Page builder integrations -│ ├── single-form-settings/ # Form-specific settings -│ └── traits/ # Shared PHP traits -├── languages/ # Internationalization files -├── modules/ # Feature modules -│ ├── gutenberg/ # Gutenberg integration -│ └── quick-action-sidebar/ # Quick action UI -├── src/ # JavaScript source files -│ ├── admin/ # Admin JS -│ ├── blocks/ # Block JS -│ ├── components/ # Reusable React components -│ ├── lib/ # JS libraries -│ ├── store/ # Redux store -│ ├── styles/ # SCSS files -│ └── utils/ # Utility functions -└── templates/ # Template files -``` - -### Initialization Flow - -The plugin follows a structured initialization process: - -1. `sureforms.php` - Main plugin file that defines constants and includes the plugin loader -2. `plugin-loader.php` - Initializes the plugin and registers core components -3. Core components are loaded through the `Plugin_Loader` class using autoloading -4. WordPress hooks are registered to integrate with the WordPress lifecycle - -```mermaid -graph TD - A[sureforms.php] --> B[plugin-loader.php] - B --> C[Plugin_Loader class] - C --> D[Register hooks] - C --> E[Autoload classes] - C --> F[Load textdomain] - D --> G[Init core components] - G --> H[Post_Types] - G --> I[Form_Submit] - G --> J[Block_Patterns] - G --> K[Frontend_Assets] - G --> L[AI_Form_Builder] - G --> M[Rest_Api] -``` - -## Core Components - -### Plugin_Loader - -The central initialization class that bootstraps the plugin, registers hooks, and loads core components. It follows a singleton pattern to ensure only one instance exists. - -```php -class Plugin_Loader { - private static $instance = null; - - public static function get_instance() { - if (null === self::$instance) { - self::$instance = new self(); - do_action('srfm_core_loaded'); - } - return self::$instance; - } - - // Initialization methods... -} -``` - -### Post_Types - -Registers and manages custom post types for forms and entries. Handles the admin UI customizations for these post types. - -Key features: -- Registers `sureforms_form` post type for storing form configurations -- Adds custom columns to the admin list view -- Implements shortcode functionality -- Manages form metadata registration - -### Form_Submit - -Processes form submissions through REST API endpoints, validates input data, handles file uploads, processes anti-spam measures, and triggers email notifications. - -Key features: -- Registers `/sureforms/v1/submit-form` REST API endpoint -- Validates form submissions against defined rules -- Processes file uploads with security checks -- Handles anti-spam measures (honeypot, reCAPTCHA, hCaptcha, Cloudflare Turnstile) -- Stores submissions in the database -- Triggers email notifications - -### AI_Form_Builder - -Integrates with AI services to generate form structures based on user prompts. Communicates with middleware services to process AI requests. - -Key features: -- Processes natural language descriptions into form structures -- Maps AI-generated fields to SureForms field types -- Generates block structures for the editor - -## Database Structure - -SureForms uses both WordPress custom post types and custom database tables to store data efficiently. - -### Custom Post Types - -- **sureforms_form**: Stores form configurations - - Post content: Serialized blocks representing the form structure - - Post meta: Form settings, styling options, and other configuration data - -### Custom Database Tables - -- **{prefix}_srfm_entries**: Stores form submissions - - ID: Primary key - - form_id: Associated form ID - - user_id: Submitter's user ID (if logged in) - - form_data: JSON-encoded submission data - - submission_info: Browser, IP, and device information - - status: Entry status (read, unread, trash) - - logs: Activity logs for the entry - - created_at: Submission timestamp - -```mermaid -erDiagram - FORMS ||--o{ ENTRIES : "has" - FORMS { - int ID - string post_title - text post_content - string post_status - datetime post_date - } - ENTRIES { - int ID - int form_id - int user_id - json form_data - json submission_info - string status - json logs - datetime created_at - } - FORMS ||--o{ FORM_META : "has" - FORM_META { - int meta_id - int post_id - string meta_key - mixed meta_value - } -``` - -## Form Building System - -SureForms uses WordPress's block editor as the foundation for its form builder. - -### Block Structure - -Forms are composed of various block types: - -- **Container Blocks**: Group and organize form fields -- **Field Blocks**: Individual form inputs (text, email, checkbox, etc.) -- **Layout Blocks**: Control the visual arrangement of fields -- **Special Blocks**: Submit buttons, GDPR notices, etc. - -Each block has its own edit and save components, following the WordPress block API pattern. - -### Block Registration - -Blocks are registered using the WordPress block registration API: - -```javascript -registerBlockType('sureforms/input', { - title: __('Text Field', 'sureforms'), - icon: 'text', - category: 'sureforms', - attributes: { - // Block attributes - }, - edit: Edit, - save: Save -}); -``` - -### Form Rendering - -Forms are rendered on the frontend using a combination of server-side rendering and client-side JavaScript: - -1. The form shortcode or block triggers the `Generate_Form_Markup::get_form_markup()` method -2. The method retrieves the form configuration and generates the HTML markup -3. Frontend JavaScript initializes the form functionality (validation, submission, etc.) - -## Form Submission Process - -### Client-Side Flow - -1. User fills out the form -2. Client-side validation checks for errors -3. Form data is collected and serialized -4. AJAX request is sent to the REST API endpoint -5. Response is processed and appropriate feedback is shown to the user - -### Server-Side Flow - -1. REST API endpoint receives the form submission -2. Data is validated and sanitized -3. Anti-spam checks are performed -4. If GDPR compliance is enabled, appropriate data handling is applied -5. Submission is stored in the database (unless configured not to) -6. Email notifications are triggered -7. Response is sent back to the client - -```mermaid -sequenceDiagram - participant User - participant Browser - participant REST_API - participant Database - participant Email - - User->>Browser: Fill form - Browser->>Browser: Validate input - User->>Browser: Submit form - Browser->>REST_API: POST /sureforms/v1/submit-form - REST_API->>REST_API: Validate data - REST_API->>REST_API: Anti-spam check - REST_API->>Database: Store submission - REST_API->>Email: Send notifications - REST_API->>Browser: Return response - Browser->>User: Show confirmation -``` - -## AI Integration - -SureForms features an AI-powered form generation system that allows users to create forms by describing them in natural language. - -### AI Form Generation Process - -1. User provides a description of the desired form -2. The description is sent to the AI middleware -3. AI analyzes the description and generates a structured form definition -4. The form definition is mapped to SureForms field types -5. Blocks are generated and inserted into the editor -6. User can review and modify the generated form - -### AI Middleware - -The AI middleware acts as a bridge between SureForms and the AI service: - -1. Receives the form description from SureForms -2. Processes the description using AI models -3. Returns a structured form definition -4. Handles authentication and rate limiting - -## Security Features - -SureForms implements multiple security measures to protect against common vulnerabilities: - -### Anti-Spam Protection - -- **Honeypot Fields**: Hidden fields to catch automated submissions -- **reCAPTCHA Integration**: Multiple versions of Google reCAPTCHA -- **hCaptcha Support**: Alternative to reCAPTCHA -- **Cloudflare Turnstile**: Modern CAPTCHA alternative - -### Data Protection - -- **GDPR Compliance**: Options to enable GDPR-compliant data handling -- **Data Encryption**: Sensitive data can be encrypted in storage -- **Auto-Delete Entries**: Automatic deletion of entries after a specified period - -### Input Validation - -- **Client-Side Validation**: Immediate feedback to users -- **Server-Side Validation**: Thorough validation of all submitted data -- **File Upload Security**: Strict file type and size validation - -## Extension Points - -SureForms provides several extension points for developers: - -### WordPress Hooks - -```php -// Example of filter hook for email notification -add_filter('srfm_email_notification', function($parsed, $submission_data, $item, $form_data) { - // Modify email content or recipients - return $parsed; -}, 10, 4); - -// Example of action hook before form submission -add_action('srfm_before_submission', function($form_data) { - // Perform custom actions before form processing -}); -``` - -### JavaScript API - -```javascript -// Example of extending the form validation -window.sureFormsHooks.addFilter( - 'srfm.validation.rules', - 'my-plugin/custom-validation', - function(rules, fieldData) { - // Add custom validation rules - return rules; - } -); -``` - -## Performance Considerations - -SureForms is designed with performance in mind: - -### Asset Loading - -- CSS and JavaScript assets are loaded only when needed -- Assets are minified and optimized for production -- Critical CSS is inlined for faster rendering - -### Database Optimization - -- Custom database tables with appropriate indexes -- Efficient queries with proper WHERE clauses -- Caching of frequently accessed data - -### Form Rendering - -- Server-side rendering for initial form display -- Progressive enhancement for JavaScript features -- Lazy loading of heavy components - -## Future Development - -Planned enhancements for future versions: - -1. **Enhanced AI Capabilities** - - More sophisticated form generation - - AI-powered form analytics - -2. **Advanced Integrations** - - More third-party service integrations - - Improved CRM connections - -3. **Performance Optimizations** - - Further asset optimization - - Enhanced caching strategies - -4. **Accessibility Improvements** - - Better screen reader support - - Keyboard navigation enhancements - -5. **Developer Tools** - - More comprehensive API documentation - - Additional extension points - -## Conclusion - -SureForms represents a modern approach to WordPress form building, combining the power of the block editor with advanced features like AI form generation. Its modular architecture and extensive extension points make it both user-friendly and developer-friendly, while its focus on security and performance ensures a reliable experience for all users. diff --git a/assets/js/payment-manager.js b/assets/js/payment-manager.js index d779d0211..1353ce4e2 100644 --- a/assets/js/payment-manager.js +++ b/assets/js/payment-manager.js @@ -19,9 +19,24 @@ class PaymentManager { : this.blockId; this.paymentInput = paymentBlock.querySelector( '.srfm-payment-input' ); this.form = form; + // AbortController scopes the document-level srfm_payment_type_changed + // listener so it is removable on form re-initialization. Pattern mirrors + // PAYMENT_UTILITY.listenAmountChanges() in stripe-payment.js. + this.abortController = new AbortController(); this.init(); } + /** + * Tear down listeners owned by this instance. Called by + * initializePaymentManagers before replacing this manager so document-level + * listeners don't accumulate across form re-initializations. + */ + destroy() { + if ( this.abortController ) { + this.abortController.abort(); + } + } + init() { // Set initial active method this.updateActiveMethod(); @@ -65,6 +80,30 @@ class PaymentManager { this.handleAccordionHeaderClick( header ); } ); } ); + + // BOTH MODE: forward the payment-type change so gateways can reinit if needed. + // stripe-payment.js dispatches `srfm_payment_type_changed` on the document. + // We keep a per-instance listener so multiple payment blocks on a page don't + // step on each other. Scoped to abortController so it can be torn down on + // form re-initialization (see destroy()). + document.addEventListener( + 'srfm_payment_type_changed', + ( event ) => { + if ( event?.detail?.blockId !== this.blockId ) { + return; + } + if ( event?.detail?.form !== this.form ) { + return; + } + // Re-broadcast a payment-method event so accordion gateways re-render + // for the new mode (Stripe is already handled by reinitForBlock). + this.dispatchPaymentMethodEvent( + this.getSelectedMethod(), + this.form + ); + }, + { signal: this.abortController.signal } + ); } /** @@ -316,6 +355,10 @@ function initializePaymentManagers() { window.srfmPaymentManagers = {}; } + // Tear down the previous manager (if any) so its document-level + // srfm_payment_type_changed listener is removed before we replace it. + window.srfmPaymentManagers[ compositeKey ]?.destroy?.(); + window.srfmPaymentManagers[ compositeKey ] = new PaymentManager( paymentBlock, form diff --git a/assets/js/stripe-payment.js b/assets/js/stripe-payment.js index 6201fefb5..51da1b498 100644 --- a/assets/js/stripe-payment.js +++ b/assets/js/stripe-payment.js @@ -25,6 +25,10 @@ class StripePayment { static paymentElements = {}; static paymentIntents = {}; static subscriptionIntents = {}; + // BOTH MODE: per-block guard so rapid type-flips don't race two + // Stripe.elements() instances on the same DOM container. Keyed by + // compositeKey, cleared in the 'ready' handler of the new element. + static reinitInProgress = new Set(); // Initialize on page load static { @@ -301,22 +305,24 @@ class StripePayment { window.srfmPaymentElements = StripePayment.paymentElements; // Setup event handlers - this.setupPaymentElementEvents( paymentElement ); + this.setupPaymentElementEvents( paymentElement, compositeKey ); } /** * Setup event handlers for payment element. * * @param {Object} paymentElement - The Stripe payment element. + * @param {string} compositeKey - Composite key (instanceId-blockId) used to clear the reinit-in-flight flag. * @return {void} This function does not return a value. */ - setupPaymentElementEvents( paymentElement ) { - // Ready event - paymentElement.on( 'ready', () => {} ); - - // Change event (handling differs by payment type) - paymentElement.on( 'change', () => { - // Lets manage the event.error, event.complete events if required. + setupPaymentElementEvents( paymentElement, compositeKey ) { + // Ready event — clears the reinit-in-flight flag so subsequent type + // flips can proceed. Without this, a stale flag would block all future + // reinits for this block. + paymentElement.on( 'ready', () => { + if ( compositeKey ) { + StripePayment.reinitInProgress.delete( compositeKey ); + } } ); } @@ -647,7 +653,7 @@ class StripePayment { } static async confirmStripePayment( compositeKey, paymentData, form ) { - const { stripe, elements, clientSecret, paymentType } = paymentData; + const { stripe, elements, clientSecret } = paymentData; // Extract original blockId from compositeKey for DOM queries // compositeKey format is always "numericInstanceId-blockId" @@ -666,6 +672,17 @@ class StripePayment { '.srfm-payment-input' ); + // BOTH MODE: read paymentType fresh from the live data attribute rather + // than the cached paymentData. reinitForBlock() rebuilds the cache on + // type flip, and a confirm captured before the flip would otherwise + // branch on a stale type. If paymentType and clientSecret ever truly + // diverge, Stripe itself rejects the wrong confirmSetup/confirmPayment + // call — no need for a redundant client-side guard here. + const paymentType = + paymentInput.getAttribute( 'data-payment-type' ) || + paymentData.paymentType || + 'one-time'; + const amountType = paymentInput.getAttribute( 'data-amount-type' ) || 'fixed'; @@ -810,6 +827,54 @@ class StripePayment { } } +// BOTH MODE: start — helper to re-mount Stripe Elements when the user flips the +// payment-type chooser between one-time and subscription. Stripe's elements.update() +// does not reliably support switching `mode`, so we unmount, drop the cached +// element, and let the existing initializer pathway recreate everything. +StripePayment.reinitForBlock = function ( form, paymentBlock ) { + const paymentInput = paymentBlock.querySelector( 'input.srfm-payment-input' ); + if ( ! paymentInput ) { + return; + } + + const blockId = paymentBlock.getAttribute( 'data-block-id' ); + const compositeKey = getPaymentKey( form, blockId ); + + // Bail if a reinit is already in flight for this block. Stripe's iframe + // mount is async, and a second pass before 'ready' fires would race two + // elements.create('payment') instances on the same DOM container. The + // caller (radio change handler) reverts the radio UI when this guard + // trips so the visible state stays consistent. + if ( StripePayment.reinitInProgress.has( compositeKey ) ) { + return; + } + + const existing = StripePayment.paymentElements[ compositeKey ]; + if ( existing && existing.paymentElement ) { + try { + existing.paymentElement.unmount(); + } catch ( err ) { + // Already unmounted — safe to ignore. + } + } + delete StripePayment.paymentElements[ compositeKey ]; + delete StripePayment.paymentIntents[ compositeKey ]; + delete StripePayment.subscriptionIntents[ compositeKey ]; + window.srfmPaymentElements = StripePayment.paymentElements; + + StripePayment.reinitInProgress.add( compositeKey ); + + // Re-init only the target block. Previously this used `new StripePayment(form)` + // which walked every payment block in the form and re-ran processPayment on + // each — wasted work on multi-block forms. Object.create gives us a stub + // bound to the form (the only `this` field processPayment touches indirectly + // via initializePaymentElements) without triggering the constructor walk. + const stub = Object.create( StripePayment.prototype ); + stub.form = form; + stub.processPayment( paymentBlock ); +}; +// BOTH MODE: end + // Make StripePayment available globally for form submission window.StripePayment = StripePayment; @@ -904,9 +969,14 @@ const PAYMENT_UTILITY = { amount, inputFormatType = 'us-style' ) => { - const getPlaceHolderElement = paymentInput - .closest( '.srfm-block' ) - .querySelector( '.srfm-payment-value' ); + // BOTH MODE: in "both" payment-type mode two .srfm-payment-value spans + // exist (one per amount block). Target the VISIBLE one so the correct + // type's amount updates. Falls back to the first match for non-both mode. + const paymentBlock = paymentInput.closest( '.srfm-block' ); + const getPlaceHolderElement = + paymentBlock.querySelector( + '.srfm-payment-amount-block:not([hidden]) .srfm-payment-value' + ) || paymentBlock.querySelector( '.srfm-payment-value' ); if ( getPlaceHolderElement ) { const getCurrencySymbol = getPlaceHolderElement.getAttribute( 'data-currency-symbol' @@ -966,6 +1036,20 @@ const PAYMENT_UTILITY = { 'data-variable-amount-field' ); + // BOTH MODE: tear down any listeners previously bound for this + // payment input. switchActivePaymentType() calls this method again + // each time the user flips one-time/subscription, which previously + // piled up duplicate listeners on the source field. Round-trip + // flips compounded the leak (field A → field B → field A → ...). + // Each prior listener still fires on input events and can overwrite + // the displayed amount with a stale source field's value. + if ( paymentInput._srfmAmountListenerController ) { + paymentInput._srfmAmountListenerController.abort(); + } + const controller = new AbortController(); + paymentInput._srfmAmountListenerController = controller; + const listenerOpts = { signal: controller.signal }; + if ( getBlockMappedSlug ) { const getMappedBlock = PAYMENT_UTILITY.currentForm.querySelector( @@ -998,7 +1082,8 @@ const PAYMENT_UTILITY = { getMappedBlockInputValue, inputFormatType ); - } + }, + listenerOpts ); // Get initial format type for the initial value const inputFormatType = @@ -1020,17 +1105,21 @@ const PAYMENT_UTILITY = { '.srfm-input-dropdown-hidden' ); if ( hiddenInput ) { - hiddenInput.addEventListener( 'change', () => { - const amount = - PAYMENT_UTILITY.getDropdownAmount( - getMappedBlock, - hiddenInput + hiddenInput.addEventListener( + 'change', + () => { + const amount = + PAYMENT_UTILITY.getDropdownAmount( + getMappedBlock, + hiddenInput + ); + PAYMENT_UTILITY.updatePaymentBlockAmount( + paymentInput, + amount ); - PAYMENT_UTILITY.updatePaymentBlockAmount( - paymentInput, - amount - ); - } ); + }, + listenerOpts + ); // Set initial value const initialAmount = PAYMENT_UTILITY.getDropdownAmount( @@ -1051,17 +1140,21 @@ const PAYMENT_UTILITY = { '.srfm-input-multi-choice-hidden' ); if ( hiddenInput ) { - hiddenInput.addEventListener( 'change', () => { - const amount = - PAYMENT_UTILITY.getMultiChoiceAmount( - getMappedBlock, - hiddenInput + hiddenInput.addEventListener( + 'change', + () => { + const amount = + PAYMENT_UTILITY.getMultiChoiceAmount( + getMappedBlock, + hiddenInput + ); + PAYMENT_UTILITY.updatePaymentBlockAmount( + paymentInput, + amount ); - PAYMENT_UTILITY.updatePaymentBlockAmount( - paymentInput, - amount - ); - } ); + }, + listenerOpts + ); // Set initial value const initialAmount = PAYMENT_UTILITY.getMultiChoiceAmount( @@ -1073,6 +1166,47 @@ const PAYMENT_UTILITY = { initialAmount ); } + } else if ( + getMappedBlock.classList.contains( + 'srfm-hidden-block' + ) + ) { + const hiddenFieldInput = + getMappedBlock.querySelector( + '.srfm-hidden-input' + ); + if ( hiddenFieldInput ) { + // Hidden inputs don't fire native input/change + // events when set programmatically, so listen + // for both — integrators that set the value + // via JS should dispatch a 'change' event. + const syncAmount = () => { + const trimmed = + hiddenFieldInput.value.trim(); + const rawValue = + /^\d+(\.\d+)?$/.test( trimmed ) + ? parseFloat( trimmed ) + : NaN; + const amount = + isNaN( rawValue ) || rawValue < 0 + ? 0 + : rawValue; + PAYMENT_UTILITY.updatePaymentBlockAmount( + paymentInput, + amount + ); + }; + hiddenFieldInput.addEventListener( + 'change', + syncAmount + ); + hiddenFieldInput.addEventListener( + 'input', + syncAmount + ); + // Set initial value from defaultValue. + syncAmount(); + } } } } @@ -1274,6 +1408,239 @@ document.addEventListener( 'srfm_form_after_initialization', ( event ) => { if ( paymentBlocks.length > 0 ) { new StripePayment( form ); PAYMENT_UTILITY.init( form ); + // BOTH MODE: wire the one-time / subscription radio chooser, if present. + initPaymentTypeChoosers( form ); } } } ); + +// BOTH MODE: start — payment-type chooser (one-time vs subscription) wiring. + +/** + * Wire the payment-type chooser radios for any payment blocks in this form + * that were saved with paymentType === 'both'. + * + * @param {HTMLFormElement} form - The form element. + */ +function initPaymentTypeChoosers( form ) { + const paymentBlocks = form.querySelectorAll( + '.srfm-block.srfm-payment-block' + ); + + paymentBlocks.forEach( ( paymentBlock ) => { + const paymentInput = paymentBlock.querySelector( + 'input.srfm-payment-input' + ); + if ( ! paymentInput ) { + return; + } + + // Only wire when the admin chose "both" mode. + if ( + paymentInput.getAttribute( 'data-original-payment-type' ) !== + 'both' + ) { + return; + } + + const radios = paymentBlock.querySelectorAll( + '.srfm-payment-type-choice-radio' + ); + if ( radios.length === 0 ) { + return; + } + + radios.forEach( ( radio ) => { + radio.addEventListener( 'change', ( event ) => { + if ( ! event.target.checked ) { + return; + } + + // BOTH MODE: block type-flip while a payment is in flight. + // reinitForBlock() unmounts the Stripe Element and deletes the + // cached intent the pending confirmPayment is still using — + // flipping mid-submit produces double charges or wrong-type + // completions. Revert the radio to whatever data-payment-type + // currently is so the UI does not lie about the user's choice. + const blockId = + paymentBlock.getAttribute( 'data-block-id' ); + const compositeKey = getPaymentKey( form, blockId ); + const reinitInFlight = + StripePayment.reinitInProgress.has( compositeKey ); + + if ( + form.dataset.srfmPaymentInFlight === 'true' || + reinitInFlight + ) { + const activeType = + paymentInput.getAttribute( 'data-payment-type' ) || + 'one-time'; + radios.forEach( ( r ) => { + r.checked = r.value === activeType; + } ); + return; + } + + switchActivePaymentType( + form, + paymentBlock, + paymentInput, + event.target.value + ); + } ); + } ); + } ); +} + +/** + * Apply a new active payment type to the block. Updates DOM visibility, syncs + * the live data-* attributes that the rest of the JS reads, re-initializes + * the Stripe Element in the new mode, and dispatches a gateway-agnostic event + * so other gateways (e.g. PayPal in sureforms-pro) can react. + * + * @param {HTMLFormElement} form - The form element. + * @param {HTMLElement} paymentBlock - The payment block wrapper. + * @param {HTMLInputElement} paymentInput - The hidden payment input. + * @param {string} newType - 'one-time' or 'subscription'. + */ +function switchActivePaymentType( form, paymentBlock, paymentInput, newType ) { + const safeType = newType === 'subscription' ? 'subscription' : 'one-time'; + + // 1. Toggle visible amount block. + const amountBlocks = paymentBlock.querySelectorAll( + '.srfm-payment-amount-block' + ); + amountBlocks.forEach( ( el ) => { + if ( el.getAttribute( 'data-payment-type' ) === safeType ) { + el.removeAttribute( 'hidden' ); + } else { + el.setAttribute( 'hidden', '' ); + } + } ); + + // 2. Sync the live data attributes from the per-type configuration. + const prefix = safeType === 'subscription' ? 'subscription' : 'one-time'; + const amountType = + paymentInput.getAttribute( `data-${ prefix }-amount-type` ) || 'fixed'; + const fixedAmount = + paymentInput.getAttribute( `data-${ prefix }-fixed-amount` ) || '0'; + const minimumAmount = + paymentInput.getAttribute( `data-${ prefix }-minimum-amount` ) || '0'; + const variableField = + paymentInput.getAttribute( `data-${ prefix }-variable-amount-field` ) || + ''; + + paymentInput.setAttribute( 'data-payment-type', safeType ); + paymentInput.setAttribute( 'data-amount-type', amountType ); + paymentInput.setAttribute( 'data-fixed-amount', fixedAmount ); + + if ( parseFloat( minimumAmount ) > 0 ) { + paymentInput.setAttribute( 'data-minimum-amount', minimumAmount ); + } else { + paymentInput.removeAttribute( 'data-minimum-amount' ); + } + + if ( amountType === 'variable' && variableField ) { + paymentInput.setAttribute( 'data-variable-amount-field', variableField ); + } else { + paymentInput.removeAttribute( 'data-variable-amount-field' ); + // Also clear any cached current-amount so stale values don't leak across choices. + paymentInput.removeAttribute( 'data-current-amount' ); + } + + // 3. Re-initialize Stripe Element in the new mode. + if ( typeof StripePayment.reinitForBlock === 'function' ) { + StripePayment.reinitForBlock( form, paymentBlock ); + } + + // 3b. BOTH MODE: re-wire variable-amount listeners and trigger an immediate + // display update for the new type. listenAmountChanges() queries + // [data-variable-amount-field] which was just updated above, so it will + // find and wire the correct field. The immediate update populates the + // amount span which is empty at PHP render time for variable types. + if ( amountType === 'variable' && variableField ) { + PAYMENT_UTILITY.listenAmountChanges(); + + // Read current value from the mapped field and update the display now. + const mappedBlock = form.querySelector( + `.srfm-block.srfm-slug-${ variableField }` + ); + if ( mappedBlock ) { + const numberInput = mappedBlock.querySelector( + 'input.srfm-input-common' + ); + const dropdownInput = mappedBlock.querySelector( + '.srfm-input-dropdown-hidden' + ); + const multiChoiceInput = mappedBlock.querySelector( + '.srfm-input-multi-choice-hidden' + ); + const hiddenFieldInput = + mappedBlock.querySelector( '.srfm-hidden-input' ); + + let currentValue = 0; + if ( numberInput ) { + currentValue = numberInput.value || 0; + } else if ( dropdownInput ) { + currentValue = + PAYMENT_UTILITY.getDropdownAmount( + mappedBlock, + dropdownInput + ) || 0; + } else if ( multiChoiceInput ) { + currentValue = + PAYMENT_UTILITY.getMultiChoiceAmount( + mappedBlock, + multiChoiceInput + ) || 0; + } else if ( hiddenFieldInput ) { + // Mirror syncAmount() in listenAmountChanges — accept only numeric + // strings, clamp negatives to 0. Without this branch, currentValue + // stays 0 and overwrites the value syncAmount() just wrote during + // listenAmountChanges() above, breaking initial-amount pickup on + // every one-time/subscription flip. + const trimmed = hiddenFieldInput.value.trim(); + const rawValue = /^\d+(\.\d+)?$/.test( trimmed ) + ? parseFloat( trimmed ) + : NaN; + currentValue = + isNaN( rawValue ) || rawValue < 0 ? 0 : rawValue; + } + + PAYMENT_UTILITY.updatePaymentBlockAmount( + paymentInput, + currentValue + ); + } else { + // No mapped field found — show placeholder. + PAYMENT_UTILITY.updatePaymentBlockAmount( paymentInput, 0 ); + } + } + + // 4. Dispatch gateway-agnostic event so other gateways (PayPal etc.) can react. + // + // Event contract — `srfm_payment_type_changed` (document-level, bubbles): + // detail: { + // blockId: string — Original payment block id (no instance prefix). + // form: HTMLFormElement — Form element the payment block belongs to. + // paymentType: 'one-time' | 'subscription' — The newly active type. + // paymentInput: HTMLInputElement — The hidden .srfm-payment-input element. + // } + // Companion event `srfm_payment_method_changed` (dispatched in payment-manager.js) + // uses a deliberately narrower shape — { blockId, paymentMethod, form } — because + // gateway listeners only need the method id; if you need paymentInput on that + // path, query it from the form rather than expanding the schema (avoids drift). + const blockId = paymentBlock.getAttribute( 'data-block-id' ); + document.dispatchEvent( + new CustomEvent( 'srfm_payment_type_changed', { + detail: { + blockId, + form, + paymentType: safeType, + paymentInput, + }, + bubbles: true, + } ) + ); +} +// BOTH MODE: end diff --git a/assets/js/unminified/payment.js b/assets/js/unminified/payment.js index 22f15e529..c4d90af53 100644 --- a/assets/js/unminified/payment.js +++ b/assets/js/unminified/payment.js @@ -105,7 +105,10 @@ function validateThePaymentBlock( form ) { 'data-customer-name-field' ); - // Get payment type (subscription or one-time) + // Get payment type (subscription or one-time). + // BOTH MODE: when the admin chose "both", data-payment-type is kept in sync with the + // active radio choice by the chooser handler in stripe-payment.js, so reading it + // directly here continues to give the correct effective type at submission time. const paymentType = paymentInput.getAttribute( 'data-payment-type' ) || 'one-time'; const isSubscription = paymentType === 'subscription'; @@ -194,6 +197,14 @@ function validateThePaymentBlock( form ) { * @param {HTMLElement} form - The form element. */ export async function handleFormPayment( form ) { + // BOTH MODE: mark the form as having a payment in flight so the type-flip + // chooser can no-op while createIntent + Stripe.confirmPayment are pending. + // Without this guard, flipping mid-submit unmounts the Stripe Element and + // deletes the cached intent the in-flight confirmation is still using — + // which can produce a second charge on retry, or complete the original + // (now wrong-type) charge silently. + form.dataset.srfmPaymentInFlight = 'true'; + try { const valiDatePaymentBlocks = validateThePaymentBlock( form ); @@ -234,6 +245,8 @@ export async function handleFormPayment( form ) { ), paymentResultOnCreateIntent: null, }; + } finally { + delete form.dataset.srfmPaymentInFlight; } } diff --git a/assets/js/unminified/validation.js b/assets/js/unminified/validation.js index c022bf7b6..32c5d0ba3 100644 --- a/assets/js/unminified/validation.js +++ b/assets/js/unminified/validation.js @@ -346,8 +346,10 @@ export async function fieldValidation( validateResult = true; } else if ( confirmValue !== inputValue ) { window?.srfm?.toggleErrorState( confirmParent, true ); - confirmError.textContent = - window?.srfm_submit?.messages?.srfm_confirm_email_same; + if ( confirmError ) { + confirmError.textContent = + window?.srfm_submit?.messages?.srfm_confirm_email_same; + } // Set the first error input. setFirstErrorInput( confirmInput, confirmParent ); @@ -474,6 +476,43 @@ export async function fieldValidation( } } + // Textarea minimum character validation. + // Skip rich-text editors — their value is HTML and would inflate the character count. + if ( + container.classList.contains( 'srfm-textarea-block' ) && + ! container.classList.contains( 'srfm-richtext' ) + ) { + const textareaField = container.querySelector( 'textarea' ); + if ( textareaField ) { + const minLength = textareaField.getAttribute( 'data-minlength' ); + const maxLengthAttr = textareaField.getAttribute( 'maxlength' ); + const minLengthNum = Number( minLength ); + const maxLengthNum = Number( maxLengthAttr ); + // Misconfiguration guard — skip when min > max so the form stays submittable. + const minIsValid = + minLength && + minLengthNum > 0 && + ( ! maxLengthAttr || maxLengthNum <= 0 || minLengthNum <= maxLengthNum ); + if ( minIsValid && inputValue !== '' ) { + if ( inputValue.length < minLengthNum ) { + window?.srfm?.toggleErrorState( + textareaField.closest( '.srfm-block' ), + true + ); + if ( errorMessage ) { + errorMessage.textContent = + window?.srfm?.srfmSprintfString( + window?.srfm_submit?.messages?.srfm_textarea_min_chars, + minLength + ); + } + validateResult = true; + setFirstErrorInput( textareaField, container ); + } + } + } + } + //rating field if ( container.classList.contains( 'srfm-rating-block' ) ) { const ratingInput = container.querySelector( '.srfm-input-rating' ); diff --git a/bin/build-zip.sh b/bin/build-zip.sh deleted file mode 100644 index 0bf38a51d..000000000 --- a/bin/build-zip.sh +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/env bash - -# Exit if any command fails. -set -e - -# Enable nicer messaging for build status. -BLUE_BOLD='\033[1;34m'; -GREEN_BOLD='\033[1;32m'; -RED_BOLD='\033[1;31m'; -YELLOW_BOLD='\033[1;33m'; -COLOR_RESET='\033[0m'; -error () { - echo -e "\n${RED_BOLD}$1${COLOR_RESET}\n" -} -status () { - echo -e "\n${BLUE_BOLD}$1${COLOR_RESET}\n" -} -success () { - echo -e "\n${GREEN_BOLD}$1${COLOR_RESET}\n" -} -warning () { - echo -e "\n${YELLOW_BOLD}$1${COLOR_RESET}\n" -} - - -status "💃 Time to build the plugin ZIP file 🕺" - -if [ ! -d "artifact" ]; then - mkdir "artifact" -fi - - -# Copy files for zip. -rsync -rc --delete --exclude-from ".distignore" "./" "artifact/sureforms" - -# Go to directory -cd artifact - -# Create a zip copied files. -zip -r sureforms.zip "./sureforms" - -if [ "no-clean" != "$1" ]; then - # Removed copied files folder. - rm -rf sureforms -fi - -success "Done. Your sureforms zip is ready..! 🎉" diff --git a/bin/checkout-and-build b/bin/checkout-and-build deleted file mode 100755 index c7529e42e..000000000 --- a/bin/checkout-and-build +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash -# Script to checkout a branch and build the project - -# Check if branch name is provided as an argument -if [ -z "$1" ]; then - echo "Error: No branch name provided." - echo "Usage: ./checkout-and-build.sh " - exit 1 -fi - -# Assign the first argument to a variable -branch_name=$1 - -# Checkout the specified branch -git checkout "$branch_name" - -# pull the latest version -git pull origin "$branch_name" - -# Run the build command -npm run build diff --git a/bin/i18n.sh b/bin/i18n.sh deleted file mode 100644 index 357e3aee1..000000000 --- a/bin/i18n.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/bash - -# Run release script -#bash bin/i18n.sh - -# Run textdomain updates and generate the POT file -echo "Running textdomain update and POT file generation..." -npm run makepot - -# Update PO files -echo "Updating PO files..." -npm run i18n:po - -# Translate using GPT-PO for Dutch, French, and more -echo "Translating PO files using GPT-PO..." -npm run i18n:gptpo:nl -npm run i18n:gptpo:fr -npm run i18n:gptpo:de -npm run i18n:gptpo:es -npm run i18n:gptpo:it -npm run i18n:gptpo:pt -npm run i18n:gptpo:pl - -# Update PO files again after translation -echo "Updating PO files again..." -npm run i18n:po - -# Generate MO files -echo "Generating MO files..." -npm run i18n:mo - -# Generate JSON translation files -echo "Generating JSON translation files..." -npm run i18n:json - -echo "All commands executed successfully." diff --git a/inc/abilities/entries/bulk-get-entries.php b/inc/abilities/entries/bulk-get-entries.php index 230c776d3..acb54e885 100644 --- a/inc/abilities/entries/bulk-get-entries.php +++ b/inc/abilities/entries/bulk-get-entries.php @@ -112,7 +112,7 @@ public function get_output_schema() { ], ], 'submission_info' => [ 'type' => 'object' ], - 'user' => [ 'type' => 'object' ], + 'user' => [ 'type' => [ 'object', 'null' ] ], ], ], ], diff --git a/inc/abilities/entries/get-entry.php b/inc/abilities/entries/get-entry.php index 10121d633..b72ebe2b1 100644 --- a/inc/abilities/entries/get-entry.php +++ b/inc/abilities/entries/get-entry.php @@ -99,7 +99,7 @@ public function get_output_schema() { ], ], 'submission_info' => [ 'type' => 'object' ], - 'user' => [ 'type' => 'object' ], + 'user' => [ 'type' => [ 'object', 'null' ] ], ], ]; } diff --git a/inc/abilities/forms/create-form.php b/inc/abilities/forms/create-form.php index 08d8d9100..a4323e686 100644 --- a/inc/abilities/forms/create-form.php +++ b/inc/abilities/forms/create-form.php @@ -316,6 +316,10 @@ public function execute( $input ) { $post_content = Field_Mapping::generate_gutenberg_fields_from_questions( $request ); + if ( is_wp_error( $post_content ) ) { + return $post_content; + } + if ( empty( $post_content ) ) { return new \WP_Error( 'srfm_field_mapping_failed', diff --git a/inc/abilities/forms/update-form.php b/inc/abilities/forms/update-form.php index fd51782bb..997bd958c 100644 --- a/inc/abilities/forms/update-form.php +++ b/inc/abilities/forms/update-form.php @@ -392,6 +392,10 @@ public function execute( $input ) { $post_content = Field_Mapping::generate_gutenberg_fields_from_questions( $request ); + if ( is_wp_error( $post_content ) ) { + return $post_content; + } + if ( ! empty( $post_content ) ) { wp_update_post( [ diff --git a/inc/abilities/settings/update-global-settings.php b/inc/abilities/settings/update-global-settings.php index b751ed8c6..a473db6ba 100644 --- a/inc/abilities/settings/update-global-settings.php +++ b/inc/abilities/settings/update-global-settings.php @@ -67,6 +67,7 @@ class Update_Global_Settings extends Abstract_Ability { 'srfm_valid_url', 'srfm_confirm_email_same', 'srfm_valid_email', + 'srfm_textarea_min_chars', 'srfm_input_min_value', 'srfm_input_max_value', 'srfm_dropdown_min_selections', diff --git a/inc/admin/editor-nudge.php b/inc/admin/editor-nudge.php new file mode 100644 index 000000000..87ae268b8 --- /dev/null +++ b/inc/admin/editor-nudge.php @@ -0,0 +1,269 @@ +is_block_editor() ) { + return false; + } + + // Skip on the SureForms form editor itself. + if ( SRFM_FORMS_POST_TYPE === $screen->post_type ) { + return false; + } + + // Skip if the current post has an active dismissal recorded against it. + // Best-effort — when no post is in scope (e.g. the Site Editor) we + // still enqueue and let the JS layer surface or hide based on live + // editor state. + $post_id = $this->get_current_post_id(); + if ( $post_id > 0 && $this->is_dismissal_active( $post_id ) ) { + return false; + } + + return true; + } + + /** + * Whether the given post has an active dismissal within the expiry window. + * + * Treats any non-numeric / zero / future-timestamp value as inactive, + * and rolls over once the recorded timestamp is older than + * `DISMISS_EXPIRY_SECONDS`. + * + * @since 2.8.2 + * @param int $post_id Post ID to check. + * @return bool + */ + public function is_dismissal_active( $post_id ) { + $dismissed_at = Helper::get_integer_value( get_post_meta( $post_id, self::DISMISS_META_KEY, true ) ); + + if ( $dismissed_at <= 0 ) { + return false; + } + + return time() - $dismissed_at < self::DISMISS_EXPIRY_SECONDS; + } + + /** + * Enqueue the nudge script when allowed. + * + * @since 2.8.2 + * @return void + */ + public function enqueue_scripts() { + if ( ! $this->allow_load() ) { + return; + } + + $handle = SRFM_SLUG . '-editor-nudge'; + $asset_path = SRFM_DIR . 'assets/build/editorNudge.asset.php'; + $asset = file_exists( $asset_path ) + ? include $asset_path + : [ + 'dependencies' => [ 'wp-data', 'wp-i18n', 'wp-dom-ready' ], + 'version' => SRFM_VER, + ]; + + wp_enqueue_script( + $handle, + SRFM_URL . 'assets/build/editorNudge.js', + $asset['dependencies'], + $asset['version'], + true + ); + + $file_prefix = defined( 'SRFM_DEBUG' ) && SRFM_DEBUG ? '' : '.min'; + $dir_name = defined( 'SRFM_DEBUG' ) && SRFM_DEBUG ? 'unminified' : 'minified'; + + wp_enqueue_style( + $handle, + SRFM_URL . 'assets/css/' . $dir_name . '/editor-nudge' . $file_prefix . '.css', + [], + SRFM_VER + ); + + wp_localize_script( + $handle, + 'srfm_editor_nudge', + [ + 'ajax_url' => admin_url( 'admin-ajax.php' ), + 'nonce' => wp_create_nonce( self::NONCE_ACTION ), + 'create_form_url' => admin_url( 'admin.php?page=add-new-form' ), + 'message' => __( 'Hey! It looks like you\'re creating a form. Build a ready-to-use form in under 30 seconds with SureForms AI, with no extra setup required.', 'sureforms' ), + 'button_label' => __( 'Create Form', 'sureforms' ), + 'logo_url' => SRFM_URL . 'admin/assets/sureforms-logo.png', + ] + ); + + Helper::register_script_translations( $handle ); + } + + /** + * AJAX handler to persist the dismissed state for the post being edited. + * + * @since 2.8.2 + * @return void + */ + public function handle_dismiss() { + if ( ! Helper::current_user_can( 'manage_options' ) ) { + wp_send_json_error( + [ 'message' => __( 'You are not allowed to perform this action.', 'sureforms' ) ], + 403 + ); + } + + if ( ! check_ajax_referer( self::NONCE_ACTION, 'nonce', false ) ) { + wp_send_json_error( + [ 'message' => __( 'Invalid security token.', 'sureforms' ) ], + 400 + ); + } + + $post_id = isset( $_POST['post_id'] ) + ? Helper::get_integer_value( sanitize_text_field( wp_unslash( $_POST['post_id'] ) ) ) + : 0; + + $post = $post_id > 0 ? get_post( $post_id ) : null; + if ( ! $post ) { + wp_send_json_error( + [ 'message' => __( 'Invalid post.', 'sureforms' ) ], + 400 + ); + } + + // The nudge never surfaces on the SureForms form CPT, so dismissals + // for it are never legitimate — reject before touching post meta. + if ( SRFM_FORMS_POST_TYPE === $post->post_type ) { + wp_send_json_error( + [ 'message' => __( 'Invalid post.', 'sureforms' ) ], + 400 + ); + } + + // Granular per-post authorization — `manage_options` alone is not + // enough; the requesting user must also be able to edit THIS post. + if ( ! current_user_can( 'edit_post', $post_id ) ) { + wp_send_json_error( + [ 'message' => __( 'You cannot edit this post.', 'sureforms' ) ], + 403 + ); + } + + update_post_meta( $post_id, self::DISMISS_META_KEY, time() ); + + wp_send_json_success(); + } + + /** + * Resolve the post ID being edited on the current admin request. + * + * @since 2.8.2 + * @return int Post ID, or 0 when no post is in scope. + */ + protected function get_current_post_id() { + global $post; + if ( $post instanceof \WP_Post && $post->ID > 0 ) { + return (int) $post->ID; + } + return 0; + } +} diff --git a/inc/ai-form-builder/ai-form-builder.php b/inc/ai-form-builder/ai-form-builder.php index c0130efe1..c4886f2af 100644 --- a/inc/ai-form-builder/ai-form-builder.php +++ b/inc/ai-form-builder/ai-form-builder.php @@ -70,23 +70,54 @@ public function generate_ai_form( $request ) { if ( ! empty( $response['error'] ) ) { // If the response has an error, handle it and report it back. - $message = ''; - if ( ! empty( $response['error']['message'] ) ) { // If any error message received from OpenAI. - $message = $response['error']['message']; - } elseif ( is_string( $response['error'] ) ) { // If any error message received from server. - if ( ! empty( $response['code'] && is_string( $response['code'] ) ) ) { - $message = __( 'The SureForms AI Middleware encountered an error.', 'sureforms' ); - } - $message = ! empty( $message ) ? $message : $response['error']; + // We sanitize before returning so OpenAI / middleware infra details + // (URLs, request IDs, model names, account IDs) do not leak to the + // client; the raw message is preserved in the debug log via + // AI_Helper::sanitize_ai_error_message() when WP_DEBUG[_LOG] is on. + $raw = ''; + if ( is_array( $response['error'] ) && ! empty( $response['error']['message'] ) ) { + // If any error message received from OpenAI. + $raw = $response['error']['message']; + } elseif ( is_string( $response['error'] ) ) { + // If any error message received from the middleware server. + $raw = $response['error']; + } + $message = AI_Helper::sanitize_ai_error_message( $raw, 'generate/form' ); + if ( '' === $message ) { + $message = __( 'The SureForms AI Middleware encountered an error.', 'sureforms' ); } wp_send_json_error( [ 'message' => $message ] ); - } elseif ( is_array( $response['form'] ) && ! empty( $response['form']['formTitle'] ) && is_array( $response['form']['formFields'] ) && ! empty( $response['form']['formFields'] ) ) { - // If the message was sent successfully, send it successfully. - wp_send_json_success( $response ); - } else { - // If you've reached here, then something has definitely gone amuck. Abandon ship. - wp_send_json_error( $response ); - }//end if + } + + // Validate the expected form structure piece by piece so we can return specific errors. + if ( empty( $response['form'] ) || ! is_array( $response['form'] ) ) { + wp_send_json_error( + [ + 'message' => __( 'The AI did not return a form. Please refine your prompt and try again.', 'sureforms' ), + ] + ); + } + + if ( empty( $response['form']['formTitle'] ) ) { + wp_send_json_error( + [ + 'message' => __( 'The AI response is missing a form title. Please try again.', 'sureforms' ), + ] + ); + } + + if ( + empty( $response['form']['formFields'] ) || + ! is_array( $response['form']['formFields'] ) + ) { + wp_send_json_error( + [ + 'message' => __( 'The AI was unable to generate form fields. Please try again.', 'sureforms' ), + ] + ); + } + + wp_send_json_success( $response ); } } diff --git a/inc/ai-form-builder/ai-helper.php b/inc/ai-form-builder/ai-helper.php index 5facdc2a4..28c0fe265 100644 --- a/inc/ai-form-builder/ai-helper.php +++ b/inc/ai-form-builder/ai-helper.php @@ -67,15 +67,11 @@ public static function get_chat_completions_response( $body = [], $extra_args = // Get the response body. $response_body = wp_remote_retrieve_body( $response ); - // If the response body is not a JSON, then abandon ship. - if ( empty( $response_body ) || ! json_decode( $response_body ) ) { - return [ - 'error' => __( 'The SureForms AI Middleware encountered an error.', 'sureforms' ), - ]; - } - - // Return the response body. - return json_decode( $response_body, true ); + return self::decode_json_response( + $response_body, + wp_remote_retrieve_response_code( $response ), + 'generate/form' + ); } /** @@ -142,15 +138,12 @@ public static function get_usage_response() { // Get the response body. $response_body = wp_remote_retrieve_body( $response ); - // If the response body is not a JSON, then abandon ship. - if ( empty( $response_body ) || ! json_decode( $response_body ) ) { - return [ - 'error' => __( 'The SureForms API server encountered an error.', 'sureforms' ), - ]; - } - - // Return the response body. - return json_decode( $response_body, true ); + return self::decode_json_response( + $response_body, + wp_remote_retrieve_response_code( $response ), + 'usage', + __( 'The SureForms API server encountered an error.', 'sureforms' ) + ); } /** @@ -229,6 +222,143 @@ public static function is_pro_license_active() { return $licensing->is_license_active(); } + /** + * Sanitize an upstream error message before returning it to the client. + * + * The OpenAI / SureForms middleware sometimes echoes infrastructure details + * (URLs, request IDs, model names, organization/user IDs, raw API keys) + * inside error messages. The endpoints surfacing these messages are + * capability-gated, but contributors-and-up shouldn't see infra leaks. + * + * Pass-through behaviour is preserved when the message has no sensitive + * tokens — only matched patterns are stripped. Returns an empty string + * if nothing useful remains, so callers can fall back to a canonical + * translated message. + * + * @param mixed $raw Raw upstream message; non-strings are coerced. + * @param string $endpoint Optional endpoint label; when set, the raw input + * is passed through {@see self::log_ai_response_failure()} + * so the unredacted form is preserved server-side + * (subject to the usual WP_DEBUG / WP_DEBUG_LOG gates). + * @param int|string $status_code Optional HTTP status, forwarded to the logger. + * @since 2.8.2 + * @return string Sanitized message safe to return to the client. + */ + public static function sanitize_ai_error_message( $raw, $endpoint = '', $status_code = '' ) { + if ( ! is_string( $raw ) ) { + return ''; + } + $raw = trim( $raw ); + if ( '' === $raw ) { + return ''; + } + + if ( '' !== $endpoint ) { + self::log_ai_response_failure( $endpoint, $status_code, 'upstream_error', $raw ); + } + + $patterns = [ + // URLs (http / https / protocol-relative). + '#https?://\S+#i', + '#(?<=\s)//\S+#i', + // OpenAI-shape opaque IDs: org-/user-/key-/sess-/req-/file-/chatcmpl-/asst-/run-/thread-. + // Both '-' and '_' separators are observed in the wild (e.g. req-… and req_…). + '/\b(?:org|user|key|sess|req|file|chatcmpl|asst|run|thread)[-_][A-Za-z0-9_]{6,}/i', + // Generic "request id: …" / "request-id …" trailers — require a separator and a substantive id. + '/\brequest[_\s-]?id[:\s]+[A-Za-z0-9_-]{4,}/i', + // Bearer / API-key shapes. + '/\bsk-[A-Za-z0-9_-]{12,}/i', + '/\bBearer\s+[A-Za-z0-9._-]+/i', + // Model identifiers that would otherwise leak the underlying provider. + '/\bgpt-[A-Za-z0-9.-]+/i', + ]; + $cleaned = (string) preg_replace( $patterns, '', $raw ); + // Collapse the gaps left by removed tokens. + $cleaned = (string) preg_replace( '/\s+/', ' ', $cleaned ); + return trim( $cleaned, " \t\n\r\0\x0B.,;:" ); + } + + /** + * Decode the response body from the SureForms AI Middleware, returning + * a structured error payload when the body is empty or invalid JSON. + * + * @param string $response_body Raw HTTP response body. + * @param int|string $status_code HTTP status code, used for debug logging. + * @param string $endpoint Short endpoint label, used for debug logging. + * @param string|null $error_fallback Translated fallback message on decode failure. + * @since 2.8.2 + * @return array + */ + protected static function decode_json_response( $response_body, $status_code, $endpoint, $error_fallback = null ) { + if ( null === $error_fallback ) { + $error_fallback = __( 'The SureForms AI Middleware encountered an error.', 'sureforms' ); + } + + if ( '' === $response_body || null === $response_body ) { + self::log_ai_response_failure( $endpoint, $status_code, 'empty_body', '' ); + return [ 'error' => $error_fallback ]; + } + + $decoded = json_decode( $response_body, true ); + + if ( JSON_ERROR_NONE !== json_last_error() ) { + self::log_ai_response_failure( $endpoint, $status_code, 'invalid_json', $response_body ); + return [ 'error' => $error_fallback ]; + } + + if ( ! is_array( $decoded ) ) { + self::log_ai_response_failure( $endpoint, $status_code, 'non_array_json', $response_body ); + return [ 'error' => $error_fallback ]; + } + + return $decoded; + } + + /** + * Log an AI middleware response failure when WP_DEBUG and WP_DEBUG_LOG are both enabled. + * + * Newlines are collapsed to prevent log injection, and known sensitive JSON keys + * (email, token, license_key, prompt, query) are redacted before logging. + * + * @param string $endpoint Short endpoint label. + * @param int|string $status_code HTTP status code. + * @param string $reason Failure reason identifier. + * @param string $body Raw response body (will be truncated). + * @since 2.8.2 + * @return void + */ + protected static function log_ai_response_failure( $endpoint, $status_code, $reason, $body ) { + if ( ! defined( 'WP_DEBUG' ) || ! WP_DEBUG ) { + return; + } + + // Only write to the debug log file when WP_DEBUG_LOG is also enabled. + // Without this guard, error_log() falls back to the host's PHP error log. + if ( ! defined( 'WP_DEBUG_LOG' ) || ! WP_DEBUG_LOG ) { + return; + } + + $snippet = is_string( $body ) ? substr( $body, 0, 500 ) : ''; + // Collapse all whitespace (including CR/LF) to a single space to prevent log injection. + $snippet = (string) preg_replace( '/\s+/', ' ', $snippet ); + // Redact known sensitive keys if echoed in the body. + $snippet = (string) preg_replace( + '/("(?:email|token|license_key|prompt|query)"\s*:\s*")[^"]*"/i', + '$1[redacted]"', + $snippet + ); + + error_log( // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- Debug-only logging behind WP_DEBUG && WP_DEBUG_LOG. + sprintf( + '[SureForms AI] %s %s status=%s body=%s', + $endpoint, + $reason, + (string) $status_code, + $snippet + ) + ); + } + /** * Get the User Token. * diff --git a/inc/ai-form-builder/field-mapping.php b/inc/ai-form-builder/field-mapping.php index 19bc74a38..22f68a867 100644 --- a/inc/ai-form-builder/field-mapping.php +++ b/inc/ai-form-builder/field-mapping.php @@ -10,6 +10,7 @@ use SRFM\Inc\Helper; use SRFM\Inc\Traits\Get_Instance; +use WP_Error; // Exit if accessed directly. if ( ! defined( 'ABSPATH' ) ) { @@ -26,7 +27,7 @@ class Field_Mapping { * Generate Gutenberg Fields from AI data. * * @param \WP_REST_Request $request Full details about the request. - * @return string + * @return string|WP_Error */ public static function generate_gutenberg_fields_from_questions( $request ) { @@ -35,24 +36,39 @@ public static function generate_gutenberg_fields_from_questions( $request ) { // check parama is empty or not and is an array and consist form_data key. if ( empty( $params ) || ! is_array( $params ) || ! isset( $params['form_data'] ) || 0 === count( $params['form_data'] ) ) { - return ''; + return new WP_Error( + 'srfm_ai_mapping_missing_form_data', + __( 'The AI form data is missing. Please try again.', 'sureforms' ), + [ 'status' => 400 ] + ); } // Get questions from form data. $form_data = $params['form_data']; if ( empty( $form_data ) || ! is_array( $form_data ) ) { - return ''; + return new WP_Error( + 'srfm_ai_mapping_invalid_form_data', + __( 'The AI form data is not in the expected format.', 'sureforms' ), + [ 'status' => 400 ] + ); } - $form = $form_data['form']; + $form = $form_data['form'] ?? null; if ( empty( $form ) || ! is_array( $form ) ) { - return ''; + return new WP_Error( + 'srfm_ai_mapping_missing_form', + __( 'The AI response did not include a form. Please try again.', 'sureforms' ), + [ 'status' => 400 ] + ); } - $form_fields = $form['formFields']; - // if questions is empty then return empty string. - if ( empty( $form_fields ) || ! is_array( $form ) ) { - return ''; + $form_fields = $form['formFields'] ?? null; + if ( empty( $form_fields ) || ! is_array( $form_fields ) ) { + return new WP_Error( + 'srfm_ai_mapping_missing_form_fields', + __( 'The AI was unable to generate form fields. Please try again.', 'sureforms' ), + [ 'status' => 400 ] + ); } // Initialize post content string. @@ -69,7 +85,11 @@ public static function generate_gutenberg_fields_from_questions( $request ) { // Check if question is empty then continue to next question. if ( empty( $question ) || ! is_array( $question ) ) { - return ''; + return new WP_Error( + 'srfm_ai_mapping_invalid_field', + __( 'The AI returned a malformed form field. Please try again.', 'sureforms' ), + [ 'status' => 400 ] + ); } // Initialize common attributes. @@ -109,30 +129,109 @@ public static function generate_gutenberg_fields_from_questions( $request ) { case 'payment': // if payment block then map payment specific attributes. if ( 'payment' === $field_type ) { + // Amount-unit convention (do not change without auditing the full + // chain): the AI prompt schema describes fixedAmount / oneTimeFixedAmount + // / subscriptionFixedAmount in MAJOR units (dollars/euros/etc.) using + // dollar-magnitude examples (e.g. 99, 1500). All downstream layers + // agree: block attrs and stored block_config keep the value in major + // units, frontend JS multiplies by 100 only at the boundary when posting + // to create_payment_intent, and the server divides it back via + // Stripe_Helper::amount_from_stripe_format() before validating against + // the stored fixed_amount. Stripe API itself is the only consumer that + // expects minor units and it is fed the JS-multiplied value. Reviewers: + // do not flag a "cents vs dollars ambiguity" here — the convention is + // consistent end-to-end, and adding a unit declaration to the AI schema + // would actually break the existing pipeline. + // + // Default-amount convention (do not change without auditing every + // callsite): the fallback `10` used when the AI omits fixedAmount / + // oneTimeFixedAmount / subscriptionFixedAmount is the same starter + // value that block.json sets when an admin manually adds a payment + // block in the Gutenberg editor. payment-markup.php and + // field-validation.php apply the same default. AI-generated forms + // therefore behave identically to manually-built forms when an amount + // is missing — admin reviews the form preview and adjusts before + // publishing. The schema marks these three amounts as `required`, so + // in practice this fallback only fires for malformed AI responses; + // changing it to 0 would make the manual-editor UX worse without + // closing any real revenue-loss vector. Reviewers: do not flag the + // `10` default here as a hidden charge — it is the project-wide + // payment-block starter value. + // + // Update-flow caveat (pre-existing, not specific to "both" mode): + // generate_gutenberg_fields_from_questions() is also called by the + // update-form ability (inc/abilities/forms/update-form.php) which + // regenerates the entire post_content from the AI's input. There is + // no merge with the form's currently-saved attributes — every field + // type's default-on-omit behavior applies. If an AI partial update + // omits a field attribute (e.g. a previously-saved subscriptionFixedAmount + // of $15), the default kicks in and overwrites the saved value. This + // is a long-standing characteristic of the update flow, affecting all + // fields equally; it is not a regression introduced by the "both" + // payment-type work and should be addressed (if at all) by teaching + // generate_gutenberg_fields_from_questions to merge with existing block + // attrs — a broader refactor outside this scope. Reviewers: do not + // flag this as a payment-specific bug. + // + // Schema "required" scope (sureforms-ai-templates/payment.json): + // the JSON schema lists every payment property — including all 11 + // "both"-mode attrs — in a single flat `required` array applied to + // every payment field, not scoped per paymentType. This is a + // constraint of OpenAI's strict structured output mode: when + // `additionalProperties: false` is set, every property must also + // appear in `required`. The per-property `description` strings tell + // the model to emit empty strings / 0 for inapplicable modes (e.g. + // `oneTimeLabel: ''` when paymentType='one-time'). The mapping below + // only reads those attrs when paymentType='both', so empty values + // for other modes are silently and correctly dropped — there is no + // silent conflict. Reviewers: do not flag the flat `required` list + // as a scoping bug; it is how OpenAI strict mode works. + $amount_types = [ 'fixed', 'variable', 'user-choice' ]; + $intervals = [ 'day', 'week', 'month', 'quarter', 'year' ]; + $merged_attributes['customerNameField'] = isset( $question['customerNameField'] ) ? sanitize_text_field( $question['customerNameField'] ) : ''; $merged_attributes['customerEmailField'] = isset( $question['customerEmailField'] ) ? sanitize_text_field( $question['customerEmailField'] ) : ''; - $merged_attributes['paymentType'] = isset( $question['paymentType'] ) && in_array( $question['paymentType'], [ 'one-time', 'subscription' ], true ) ? sanitize_text_field( $question['paymentType'] ) : 'one-time'; + $merged_attributes['paymentType'] = isset( $question['paymentType'] ) && in_array( $question['paymentType'], [ 'one-time', 'subscription', 'both' ], true ) ? sanitize_text_field( $question['paymentType'] ) : 'one-time'; $merged_attributes['subscriptionPlan'] = isset( $question['subscriptionPlan'] ) && is_array( $question['subscriptionPlan'] ) ? [ 'name' => isset( $question['subscriptionPlan']['name'] ) ? sanitize_text_field( $question['subscriptionPlan']['name'] ) : 'Subscription Plan', - 'interval' => isset( $question['subscriptionPlan']['interval'] ) && in_array( $question['subscriptionPlan']['interval'], [ 'day', 'week', 'month', 'year' ], true ) ? sanitize_text_field( $question['subscriptionPlan']['interval'] ) : 'month', - 'billingCycles' => isset( $question['subscriptionPlan']['billingCycles'] ) ? sanitize_text_field( $question['subscriptionPlan']['billingCycles'] ) : 'ongoing', + 'interval' => isset( $question['subscriptionPlan']['interval'] ) && in_array( $question['subscriptionPlan']['interval'], $intervals, true ) ? sanitize_text_field( $question['subscriptionPlan']['interval'] ) : 'month', + 'billingCycles' => isset( $question['subscriptionPlan']['billingCycles'] ) ? ( is_numeric( $question['subscriptionPlan']['billingCycles'] ) ? intval( $question['subscriptionPlan']['billingCycles'] ) : sanitize_text_field( $question['subscriptionPlan']['billingCycles'] ) ) : 'ongoing', ] : [ 'name' => 'Subscription Plan', 'interval' => 'month', 'billingCycles' => 'ongoing', ]; - $merged_attributes['amountType'] = isset( $question['amountType'] ) && in_array( $question['amountType'], [ 'fixed', 'variable', 'user-choice' ], true ) ? sanitize_text_field( $question['amountType'] ) : 'fixed'; + $merged_attributes['amountType'] = isset( $question['amountType'] ) && in_array( $question['amountType'], $amount_types, true ) ? sanitize_text_field( $question['amountType'] ) : 'fixed'; $merged_attributes['fixedAmount'] = isset( $question['fixedAmount'] ) && is_numeric( $question['fixedAmount'] ) ? floatval( $question['fixedAmount'] ) : 10; $merged_attributes['minimumAmount'] = isset( $question['minimumAmount'] ) && is_numeric( $question['minimumAmount'] ) ? floatval( $question['minimumAmount'] ) : 0; $merged_attributes['amountLabel'] = isset( $question['amountLabel'] ) ? sanitize_text_field( $question['amountLabel'] ) : 'Enter Amount'; $merged_attributes['variableAmountField'] = isset( $question['variableAmountField'] ) ? sanitize_text_field( $question['variableAmountField'] ) : ''; + + // "Both" mode attributes — admins configure one-time AND subscription in the same block. + if ( 'both' === $merged_attributes['paymentType'] ) { + $merged_attributes['oneTimeLabel'] = isset( $question['oneTimeLabel'] ) ? sanitize_text_field( $question['oneTimeLabel'] ) : 'One-Time Payment'; + $merged_attributes['subscriptionLabel'] = isset( $question['subscriptionLabel'] ) ? sanitize_text_field( $question['subscriptionLabel'] ) : 'Subscription'; + $merged_attributes['defaultPaymentChoice'] = isset( $question['defaultPaymentChoice'] ) && in_array( $question['defaultPaymentChoice'], [ 'one-time', 'subscription' ], true ) ? sanitize_text_field( $question['defaultPaymentChoice'] ) : 'one-time'; + $merged_attributes['oneTimeAmountType'] = isset( $question['oneTimeAmountType'] ) && in_array( $question['oneTimeAmountType'], $amount_types, true ) ? sanitize_text_field( $question['oneTimeAmountType'] ) : 'fixed'; + $merged_attributes['oneTimeFixedAmount'] = isset( $question['oneTimeFixedAmount'] ) && is_numeric( $question['oneTimeFixedAmount'] ) ? floatval( $question['oneTimeFixedAmount'] ) : 10; + $merged_attributes['oneTimeMinimumAmount'] = isset( $question['oneTimeMinimumAmount'] ) && is_numeric( $question['oneTimeMinimumAmount'] ) ? floatval( $question['oneTimeMinimumAmount'] ) : 0; + $merged_attributes['oneTimeVariableAmountField'] = isset( $question['oneTimeVariableAmountField'] ) ? sanitize_text_field( $question['oneTimeVariableAmountField'] ) : ''; + $merged_attributes['subscriptionAmountType'] = isset( $question['subscriptionAmountType'] ) && in_array( $question['subscriptionAmountType'], $amount_types, true ) ? sanitize_text_field( $question['subscriptionAmountType'] ) : 'fixed'; + $merged_attributes['subscriptionFixedAmount'] = isset( $question['subscriptionFixedAmount'] ) && is_numeric( $question['subscriptionFixedAmount'] ) ? floatval( $question['subscriptionFixedAmount'] ) : 10; + $merged_attributes['subscriptionMinimumAmount'] = isset( $question['subscriptionMinimumAmount'] ) && is_numeric( $question['subscriptionMinimumAmount'] ) ? floatval( $question['subscriptionMinimumAmount'] ) : 0; + $merged_attributes['subscriptionVariableAmountField'] = isset( $question['subscriptionVariableAmountField'] ) ? sanitize_text_field( $question['subscriptionVariableAmountField'] ) : ''; + } } // Handle specific attributes for certain fields. if ( 'dropdown' === $field_type && ! empty( $question['fieldOptions'] ) && is_array( $question['fieldOptions'] ) && ! empty( $question['fieldOptions'][0]['label'] ) ) { - $merged_attributes['options'] = $question['fieldOptions']; + // Defense-in-depth: although the upstream middleware is + // trusted and these endpoints are capability-gated, + // strings flow into Gutenberg block markup so we run + // the user-facing fields through sanitize_text_field. + $merged_attributes['options'] = self::sanitize_field_options( $question['fieldOptions'] ); if ( isset( $question['showValues'] ) ) { $merged_attributes['showValues'] = filter_var( $question['showValues'], FILTER_VALIDATE_BOOLEAN ); @@ -159,7 +258,9 @@ public static function generate_gutenberg_fields_from_questions( $request ) { // Set options if they are valid. if ( ! empty( $question['fieldOptions'][0]['optionTitle'] ) ) { - $merged_attributes['options'] = $question['fieldOptions']; + // Same defense-in-depth sanitization as the + // dropdown branch above. + $merged_attributes['options'] = self::sanitize_field_options( $question['fieldOptions'] ); } // Determine vertical layout based on icons. @@ -326,4 +427,36 @@ static function( $type ) { return apply_filters( 'srfm_ai_form_builder_post_content', $post_content, $is_conversational, $form_type ); } + /** + * Sanitize the user-facing strings on each entry of the AI-generated + * fieldOptions array before they are merged into block attributes. + * + * Defense-in-depth: the middleware is trusted today, but these strings + * are serialized into Gutenberg block markup. Running each string field + * through sanitize_text_field() prevents stored-content injection if + * the upstream ever returns reflected user content. Non-string fields + * (icon class names, booleans) are left untouched. + * + * @param array> $options Raw fieldOptions array. + * @since 2.8.2 + * @return array> Sanitized options. + */ + private static function sanitize_field_options( $options ) { + if ( ! is_array( $options ) ) { + return []; + } + $sanitizable_keys = [ 'label', 'value', 'optionTitle' ]; + foreach ( $options as $key => $option ) { + if ( ! is_array( $option ) ) { + continue; + } + foreach ( $sanitizable_keys as $field ) { + if ( isset( $option[ $field ] ) && is_string( $option[ $field ] ) ) { + $options[ $key ][ $field ] = sanitize_text_field( $option[ $field ] ); + } + } + } + return $options; + } + } diff --git a/inc/blocks/payment/block.json b/inc/blocks/payment/block.json index 4fa213e87..4335dc40f 100644 --- a/inc/blocks/payment/block.json +++ b/inc/blocks/payment/block.json @@ -104,6 +104,50 @@ "paymentDescription": { "type": "string", "default": "" + }, + "oneTimeLabel": { + "type": "string", + "default": "One-Time Payment" + }, + "subscriptionLabel": { + "type": "string", + "default": "Subscription" + }, + "defaultPaymentChoice": { + "type": "string", + "default": "one-time" + }, + "oneTimeAmountType": { + "type": "string", + "default": "fixed" + }, + "oneTimeFixedAmount": { + "type": "number", + "default": 10 + }, + "oneTimeMinimumAmount": { + "type": "number", + "default": 0 + }, + "oneTimeVariableAmountField": { + "type": "string", + "default": "" + }, + "subscriptionAmountType": { + "type": "string", + "default": "fixed" + }, + "subscriptionFixedAmount": { + "type": "number", + "default": 10 + }, + "subscriptionMinimumAmount": { + "type": "number", + "default": 0 + }, + "subscriptionVariableAmountField": { + "type": "string", + "default": "" } } } diff --git a/inc/blocks/textarea/block.json b/inc/blocks/textarea/block.json index cb9870c08..c2d7e9e56 100644 --- a/inc/blocks/textarea/block.json +++ b/inc/blocks/textarea/block.json @@ -46,6 +46,10 @@ "type": "string", "default": "" }, + "minLength": { + "type": "number", + "default": "" + }, "maxLength": { "type": "number", "default": "" diff --git a/inc/create-new-form.php b/inc/create-new-form.php index 946938350..b662aa5cd 100644 --- a/inc/create-new-form.php +++ b/inc/create-new-form.php @@ -8,6 +8,7 @@ namespace SRFM\Inc; +use SRFM\Inc\AI_Form_Builder\AI_Helper; use SRFM\Inc\Traits\Get_Instance; use WP_Error; use WP_REST_Response; @@ -145,29 +146,48 @@ public static function create_form( $data ) { 'meta_input' => $post_metas, 'post_status' => 'draft', 'post_type' => 'sureforms_form', - ] + ], + true ); - if ( ! empty( $post_id ) ) { - - /** - * Update _srfm_is_ai_generated meta to true. - * If the request is coming here then the form is AI generated. - */ - update_post_meta( $post_id, '_srfm_is_ai_generated', true ); - + if ( is_wp_error( $post_id ) ) { + // Pass the raw WP_Error through the shared sanitizer so any URLs, + // request IDs, or model names injected by a filter on + // wp_insert_post don't leak via the REST response. The raw message + // is still logged server-side (gated on WP_DEBUG / WP_DEBUG_LOG). + $sanitized = AI_Helper::sanitize_ai_error_message( $post_id->get_error_message(), 'wp_insert_post' ); + if ( '' === $sanitized ) { + $sanitized = __( 'Error creating SureForms Form.', 'sureforms' ); + } return new WP_REST_Response( [ - 'message' => __( 'SureForms Form created successfully.', 'sureforms' ), - 'id' => $post_id, - ] + 'message' => $sanitized, + ], + 500 ); } - wp_send_json_error( + + if ( ! is_int( $post_id ) || $post_id <= 0 ) { + return new WP_REST_Response( [ - 'message' => __( 'Error creating SureForms Form, ', 'sureforms' ), - ] + 'message' => __( 'Error creating SureForms Form.', 'sureforms' ), + ], + 500 ); + } + + /** + * Update _srfm_is_ai_generated meta to true. + * If the request is coming here then the form is AI generated. + */ + update_post_meta( $post_id, '_srfm_is_ai_generated', true ); + + return new WP_REST_Response( + [ + 'message' => __( 'SureForms Form created successfully.', 'sureforms' ), + 'id' => $post_id, + ] + ); } } diff --git a/inc/field-validation.php b/inc/field-validation.php index 8dd1312ef..dd555f24f 100644 --- a/inc/field-validation.php +++ b/inc/field-validation.php @@ -67,6 +67,9 @@ public static function add_block_config( $blocks, $form_id ) { case 'srfm/number': $processed_config = self::process_number_block( $block['attrs'] ); break; + case 'srfm/textarea': + $processed_config = self::process_textarea_block( $block['attrs'] ); + break; } // If block was processed, store its configuration. @@ -91,9 +94,14 @@ public static function add_block_config( $blocks, $form_id ) { } } - // Only update meta if we have processed configurations. + // Sync the meta on every save. When $block_config is empty (e.g. a textarea + // whose minLength was cleared, with no other blocks needing per-block + // validation), we must clear the stored meta — otherwise the previously + // saved values keep being used by the validator. if ( ! empty( $block_config ) ) { update_post_meta( $form_id, '_srfm_block_config', $block_config ); + } else { + delete_post_meta( $form_id, '_srfm_block_config' ); } } @@ -273,6 +281,20 @@ public static function validate_form_data( $form_data, $current_form_id ) { $not_valid_fields[ $key ] = $field_validated['error'] ?? __( 'Field is not valid.', 'sureforms' ); } } + + // Textarea minimum character server-side validation. + if ( 'srfm-textarea' === $get_field_name && is_string( $value ) && '' !== $value ) { + $block_config = isset( $get_form_config[ $extracted_id ] ) && is_array( $get_form_config[ $extracted_id ] ) ? $get_form_config[ $extracted_id ] : []; + $min_length = isset( $block_config['min_length'] ) ? absint( $block_config['min_length'] ) : 0; + if ( $min_length > 0 && mb_strlen( $value ) < $min_length ) { + $dynamic_messages = Translatable::dynamic_validation_messages(); + $min_chars_message = isset( $dynamic_messages['srfm_textarea_min_chars'] ) && is_string( $dynamic_messages['srfm_textarea_min_chars'] ) && '' !== $dynamic_messages['srfm_textarea_min_chars'] + ? $dynamic_messages['srfm_textarea_min_chars'] + /* translators: %s represents the minimum number of characters required */ + : __( 'Please enter at least %s characters.', 'sureforms' ); + $not_valid_fields[ $key ] = sprintf( $min_chars_message, $min_length ); + } + } } // Return the array of invalid fields and their error messages. @@ -294,6 +316,22 @@ private static function process_payment_block( $attrs, $blocks ) { // Extract payment type (single or subscription). $payment_config['payment_type'] = isset( $attrs['paymentType'] ) && is_string( $attrs['paymentType'] ) ? sanitize_text_field( $attrs['paymentType'] ) : 'one-time'; + // Persist subscription plan (interval + billing cycles) for any form that + // has a subscription path. The admin picks a single value for each in the + // editor; the server uses these stored values as the source of truth on + // submit so a tampered interval/cycles in form data cannot redirect Stripe + // to a different billing cadence. + if ( in_array( $payment_config['payment_type'], [ 'subscription', 'both' ], true ) && isset( $attrs['subscriptionPlan'] ) && is_array( $attrs['subscriptionPlan'] ) ) { + if ( isset( $attrs['subscriptionPlan']['interval'] ) && is_string( $attrs['subscriptionPlan']['interval'] ) ) { + $payment_config['subscription_interval'] = sanitize_text_field( $attrs['subscriptionPlan']['interval'] ); + } + if ( isset( $attrs['subscriptionPlan']['billingCycles'] ) ) { + // billingCycles is either an integer count or the string 'ongoing'. + $cycles_raw = $attrs['subscriptionPlan']['billingCycles']; + $payment_config['subscription_billing_cycles'] = is_numeric( $cycles_raw ) ? intval( $cycles_raw ) : sanitize_text_field( (string) $cycles_raw ); + } + } + // Extract amount type (fixed or minimum). $payment_config['amount_type'] = isset( $attrs['amountType'] ) && is_string( $attrs['amountType'] ) ? sanitize_text_field( $attrs['amountType'] ) : 'fixed'; @@ -317,6 +355,44 @@ private static function process_payment_block( $attrs, $blocks ) { } } + // BOTH MODE: store per-type amount configs so server-side validation can + // use the correct config based on which flow the user actually chose. + if ( 'both' === $payment_config['payment_type'] ) { + $payment_config['one_time_amount_type'] = isset( $attrs['oneTimeAmountType'] ) && is_string( $attrs['oneTimeAmountType'] ) ? sanitize_text_field( $attrs['oneTimeAmountType'] ) : 'fixed'; + $payment_config['one_time_fixed_amount'] = isset( $attrs['oneTimeFixedAmount'] ) ? floatval( $attrs['oneTimeFixedAmount'] ) : 10; + $payment_config['one_time_minimum_amount'] = isset( $attrs['oneTimeMinimumAmount'] ) ? floatval( $attrs['oneTimeMinimumAmount'] ) : 0; + + if ( isset( $attrs['oneTimeVariableAmountField'] ) ) { + $ot_slug = sanitize_text_field( $attrs['oneTimeVariableAmountField'] ); + $payment_config['one_time_variable_amount_field'] = $ot_slug; + if ( ! empty( $ot_slug ) && is_array( $blocks ) ) { + foreach ( $blocks as $block ) { + if ( isset( $block['attrs']['slug'] ) && $block['attrs']['slug'] === $ot_slug ) { + $payment_config['one_time_variable_amount_field_block_name'] = $block['blockName']; + break; + } + } + } + } + + $payment_config['subscription_amount_type'] = isset( $attrs['subscriptionAmountType'] ) && is_string( $attrs['subscriptionAmountType'] ) ? sanitize_text_field( $attrs['subscriptionAmountType'] ) : 'fixed'; + $payment_config['subscription_fixed_amount'] = isset( $attrs['subscriptionFixedAmount'] ) ? floatval( $attrs['subscriptionFixedAmount'] ) : 10; + $payment_config['subscription_minimum_amount'] = isset( $attrs['subscriptionMinimumAmount'] ) ? floatval( $attrs['subscriptionMinimumAmount'] ) : 0; + + if ( isset( $attrs['subscriptionVariableAmountField'] ) ) { + $sub_slug = sanitize_text_field( $attrs['subscriptionVariableAmountField'] ); + $payment_config['subscription_variable_amount_field'] = $sub_slug; + if ( ! empty( $sub_slug ) && is_array( $blocks ) ) { + foreach ( $blocks as $block ) { + if ( isset( $block['attrs']['slug'] ) && $block['attrs']['slug'] === $sub_slug ) { + $payment_config['subscription_variable_amount_field_block_name'] = $block['blockName']; + break; + } + } + } + } + } + return $payment_config; } @@ -420,6 +496,33 @@ private static function process_multichoice_block( $attrs ) { return $multichoice_config; } + /** + * Process textarea block configuration. + * + * @param array $attrs Block attributes. + * @return array Processed textarea configuration. + * @since 2.8.2 + */ + private static function process_textarea_block( $attrs ) { + // Always emit a min_length key so a cleared/invalid value overwrites any + // previously stored config on save instead of falling back to stale data. + // Rich-text editors submit HTML markup which would skew mb_strlen counts, + // so they're treated as "no min-length validation". + if ( ! empty( $attrs['isRichText'] ) ) { + return [ 'min_length' => 0 ]; + } + + $min_length = isset( $attrs['minLength'] ) && is_numeric( $attrs['minLength'] ) ? absint( $attrs['minLength'] ) : 0; + $max_length = isset( $attrs['maxLength'] ) && is_numeric( $attrs['maxLength'] ) ? absint( $attrs['maxLength'] ) : 0; + + // Misconfiguration guard — drop min when it exceeds max so the form stays submittable. + if ( $max_length > 0 && $min_length > $max_length ) { + $min_length = 0; + } + + return [ 'min_length' => $min_length ]; + } + /** * Process number block configuration. * diff --git a/inc/fields/email-markup.php b/inc/fields/email-markup.php index a8303a921..f6b845fa3 100644 --- a/inc/fields/email-markup.php +++ b/inc/fields/email-markup.php @@ -134,6 +134,7 @@ public function markup() { $this->placeholder_attr = ' placeholder="' . esc_attr( $placeholder ) . '" '; } + $confirm_error_markup = Helper::generate_common_form_markup( $this->form_id, 'error', '', '', $this->block_id, boolval( $this->required ), '', $this->error_msg, false, '', true ); ?>
@@ -143,7 +144,7 @@ public function markup() { data-required="data_require_attr ); ?>" aria-required="data_require_attr ); ?>" value="default ); ?>" placeholder_attr ); ?> read_only ? 'readonly' : ''; ?> />
- error_msg_markup ); ?> +
diff --git a/inc/fields/payment-markup.php b/inc/fields/payment-markup.php index b8dff5b7c..c9010d4e3 100644 --- a/inc/fields/payment-markup.php +++ b/inc/fields/payment-markup.php @@ -8,6 +8,7 @@ namespace SRFM\Inc\Fields; +use SRFM\Inc\Helper; use SRFM\Inc\Payments\Payment_Helper; use SRFM\Inc\Payments\Stripe\Stripe_Helper; @@ -141,6 +142,58 @@ class Payment_Markup extends Base { */ protected $payment_description; + // BOTH MODE: start — admin-configurable dual-mode attributes. + /** + * Original payment type as configured in the editor (one-time / subscription / both). + * While rendering we may rewrite $this->payment_type to the resolved default-choice, + * so we keep the original intent here for conditionals. + * + * @var string + * @since 2.8.2 + */ + protected $original_payment_type; + + /** + * Label shown next to the "one-time" radio choice in both mode. + * + * @var string + * @since 2.8.2 + */ + protected $one_time_label; + + /** + * Label shown next to the "subscription" radio choice in both mode. + * + * @var string + * @since 2.8.2 + */ + protected $subscription_label; + + /** + * Default radio selection in both mode ("one-time" or "subscription"). + * + * @var string + * @since 2.8.2 + */ + protected $default_payment_choice; + + /** + * One-time amount configuration (used only in both mode). + * + * @var array + * @since 2.8.2 + */ + protected $one_time_config = []; + + /** + * Subscription amount configuration (used only in both mode). + * + * @var array + * @since 2.8.2 + */ + protected $subscription_config = []; + // BOTH MODE: end. + /** * Constructor for the Payment Markup class. * @@ -187,6 +240,44 @@ public function __construct( $attributes ) { // Set variable amount field mapping. $this->variable_amount_field = $attributes['variableAmountField'] ?? ''; + // BOTH MODE: start — capture original intent and dual-mode configuration. + $this->original_payment_type = $this->payment_type; + + $this->one_time_label = $attributes['oneTimeLabel'] ?? __( 'One-Time Payment', 'sureforms' ); + $this->subscription_label = $attributes['subscriptionLabel'] ?? __( 'Subscription', 'sureforms' ); + $this->default_payment_choice = $attributes['defaultPaymentChoice'] ?? 'one-time'; + if ( ! in_array( $this->default_payment_choice, [ 'one-time', 'subscription' ], true ) ) { + $this->default_payment_choice = 'one-time'; + } + + $this->one_time_config = [ + 'amount_type' => $attributes['oneTimeAmountType'] ?? 'fixed', + 'fixed_amount' => isset( $attributes['oneTimeFixedAmount'] ) ? (float) $attributes['oneTimeFixedAmount'] : 10.0, + 'minimum_amount' => isset( $attributes['oneTimeMinimumAmount'] ) ? (float) $attributes['oneTimeMinimumAmount'] : 0.0, + 'variable_field' => $attributes['oneTimeVariableAmountField'] ?? '', + ]; + + $this->subscription_config = [ + 'amount_type' => $attributes['subscriptionAmountType'] ?? 'fixed', + 'fixed_amount' => isset( $attributes['subscriptionFixedAmount'] ) ? (float) $attributes['subscriptionFixedAmount'] : 10.0, + 'minimum_amount' => isset( $attributes['subscriptionMinimumAmount'] ) ? (float) $attributes['subscriptionMinimumAmount'] : 0.0, + 'variable_field' => $attributes['subscriptionVariableAmountField'] ?? '', + ]; + + // When rendering the "both" block, the visible amount + Stripe mode is driven by + // the default choice. Rewrite the scalar properties so the existing rendering + // logic below continues to work with zero changes. + if ( 'both' === $this->original_payment_type ) { + $active_config = 'subscription' === $this->default_payment_choice ? $this->subscription_config : $this->one_time_config; + $this->amount_type = $active_config['amount_type']; + $this->fixed_amount = $active_config['fixed_amount']; + $this->minimum_amount = $active_config['minimum_amount']; + $this->variable_amount_field = $active_config['variable_field']; + // $this->payment_type now represents the *active* rendering type, not the admin-set value. + $this->payment_type = $this->default_payment_choice; + } + // BOTH MODE: end. + // Set payment methods from block attributes, default to 'stripe' for backward compatibility. $this->payment_methods = $attributes['paymentMethods'] ?? [ 'stripe' ]; @@ -245,9 +336,15 @@ public function markup() { 'data-selected-method' => $first_method_id, ]; - if ( 'subscription' === $this->payment_type && ! empty( $this->subscription_plan ) ) { - $data_input_attributes['data-subscription-plan-name'] = $this->subscription_plan['name'] ?? __( 'Subscription Plan', 'sureforms' ); - $data_input_attributes['data-subscription-interval'] = $this->subscription_plan['interval'] ?? 'month'; + // Subscription plan attributes are emitted when subscription is the active type + // OR when "both" mode allows it as a possible end-user choice. + $has_subscription_path = 'subscription' === $this->payment_type || 'both' === $this->original_payment_type; + if ( $has_subscription_path && ! empty( $this->subscription_plan ) ) { + // Defense-in-depth: coerce to scalar before output. A malformed REST + // save could store these as arrays, which would otherwise emit notices + // or empty strings through esc_attr() downstream. + $data_input_attributes['data-subscription-plan-name'] = (string) ( $this->subscription_plan['name'] ?? __( 'Subscription Plan', 'sureforms' ) ); + $data_input_attributes['data-subscription-interval'] = (string) ( $this->subscription_plan['interval'] ?? 'month' ); $data_input_attributes['data-subscription-billing-cycles'] = $this->subscription_plan['billingCycles'] ?? 0; } @@ -259,106 +356,110 @@ public function markup() { $data_input_attributes['data-variable-amount-field'] = $this->variable_amount_field; } + // BOTH MODE: ensure data-variable-amount-field is emitted at page load if + // EITHER type uses variable amount. listenAmountChanges() runs once at init + // and queries [data-variable-amount-field] — without this, the listener is + // never wired when the default choice is fixed but the other type is variable. + if ( 'both' === $this->original_payment_type && 'variable' !== $this->amount_type ) { + $other_config = 'subscription' === $this->default_payment_choice + ? $this->one_time_config + : $this->subscription_config; + if ( 'variable' === $other_config['amount_type'] && ! empty( $other_config['variable_field'] ) ) { + $data_input_attributes['data-variable-amount-field'] = $other_config['variable_field']; + } + } + // If minimum amount is greater than 0, add it to the data input attributes. if ( $this->minimum_amount > 0 ) { $data_input_attributes['data-minimum-amount'] = $this->minimum_amount; } + // BOTH MODE: start — emit per-type configuration for the JS chooser to read. + if ( 'both' === $this->original_payment_type ) { + $data_input_attributes['data-original-payment-type'] = 'both'; + $data_input_attributes['data-default-payment-choice'] = $this->default_payment_choice; + + $data_input_attributes['data-one-time-amount-type'] = $this->one_time_config['amount_type']; + $data_input_attributes['data-one-time-fixed-amount'] = $this->one_time_config['fixed_amount']; + $data_input_attributes['data-one-time-minimum-amount'] = $this->one_time_config['minimum_amount']; + if ( 'variable' === $this->one_time_config['amount_type'] ) { + $data_input_attributes['data-one-time-variable-amount-field'] = $this->one_time_config['variable_field']; + } + + $data_input_attributes['data-subscription-amount-type'] = $this->subscription_config['amount_type']; + $data_input_attributes['data-subscription-fixed-amount'] = $this->subscription_config['fixed_amount']; + $data_input_attributes['data-subscription-minimum-amount'] = $this->subscription_config['minimum_amount']; + if ( 'variable' === $this->subscription_config['amount_type'] ) { + $data_input_attributes['data-subscription-variable-amount-field'] = $this->subscription_config['variable_field']; + } + } + // BOTH MODE: end. + ob_start(); ?>
label_markup ); ?> help_markup ); ?>
- amount_type ) { ?> - -
- - payment_type && ! empty( $this->subscription_plan ) ) { - $interval = $this->subscription_plan['interval'] ?? 'month'; - $billing_cycles = $this->subscription_plan['billingCycles'] ?? 0; - $interval_label = $this->get_interval_label( $interval ); - - // Build subscription text. - if ( 'ongoing' === $billing_cycles ) { - echo esc_html( - sprintf( - /* translators: 1: Amount with currency, 2: Interval (day/week/month/quarter/year) */ - __( '%1$s per %2$s (until cancelled)', 'sureforms' ), - $this->format_currency( $this->fixed_amount, $this->currency ), - $interval_label - ) - ); - } elseif ( $billing_cycles > 0 ) { - echo esc_html( - sprintf( - /* translators: 1: Amount with currency, 2: Interval (day/week/month/quarter/year), 3: Number of billing cycles */ - __( '%1$s per %2$s (%3$s payments)', 'sureforms' ), - $this->format_currency( $this->fixed_amount, $this->currency ), - $interval_label, - $billing_cycles - ) - ); - } else { - echo esc_html( - sprintf( - /* translators: 1: Amount with currency, 2: Interval (day/week/month/quarter/year) */ - __( '%1$s per %2$s', 'sureforms' ), - $this->format_currency( $this->fixed_amount, $this->currency ), - $interval_label - ) - ); - } - } else { - echo esc_html( $this->format_currency( $this->fixed_amount, $this->currency ) ); - } - ?> - + original_payment_type ) { + echo $this->render_payment_type_chooser(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + } + // BOTH MODE: end. + + if ( 'both' === $this->original_payment_type ) { + // BOTH MODE: render two amount displays, one per choice. JS toggles visibility. + $is_one_time_default = 'one-time' === $this->default_payment_choice; + ?> +
+ > + render_amount_display( + 'one-time', + Helper::get_string_value( $this->one_time_config['amount_type'] ?? 'fixed' ), + is_numeric( $this->one_time_config['fixed_amount'] ?? null ) ? (float) $this->one_time_config['fixed_amount'] : 0.0, + is_numeric( $this->one_time_config['minimum_amount'] ?? null ) ? (float) $this->one_time_config['minimum_amount'] : 0.0 + ); + // phpcs:enable WordPress.Security.EscapeOutput.OutputNotEscaped + ?>
- - -
-
- payment_type && ! empty( $this->subscription_plan ) ) { - $interval = $this->subscription_plan['interval'] ?? 'month'; - $billing_cycles = $this->subscription_plan['billingCycles'] ?? 0; - $interval_label = $this->get_interval_label( $interval ); - - // Build message format based on billing cycles. - if ( 'ongoing' === $billing_cycles ) { - /* translators: 1: Amount with currency placeholder, 2: Interval (day/week/month/quarter/year) */ - $message_format = sprintf( __( '{amount} per %s (until cancelled)', 'sureforms' ), $interval_label ); - } elseif ( $billing_cycles > 0 ) { - /* translators: 1: Amount with currency placeholder, 2: Interval (day/week/month/quarter/year), 3: Number of billing cycles */ - $message_format = sprintf( __( '{amount} per %1$s (%2$s payments)', 'sureforms' ), $interval_label, $billing_cycles ); - } else { - /* translators: 1: Amount with currency placeholder, 2: Interval (day/week/month/quarter/year) */ - $message_format = sprintf( __( '{amount} per %s', 'sureforms' ), $interval_label ); - } - } - ?> - - -
- minimum_amount > 0 ) { ?> - - format_currency( $this->minimum_amount, $this->currency ) - ) - ); - ?> - - +
+ > + render_amount_display( + 'subscription', + Helper::get_string_value( $this->subscription_config['amount_type'] ?? 'fixed' ), + is_numeric( $this->subscription_config['fixed_amount'] ?? null ) ? (float) $this->subscription_config['fixed_amount'] : 0.0, + is_numeric( $this->subscription_config['minimum_amount'] ?? null ) ? (float) $this->subscription_config['minimum_amount'] : 0.0 + ); + // phpcs:enable WordPress.Security.EscapeOutput.OutputNotEscaped + ?>
- + render_amount_display( + $this->payment_type, + $this->amount_type, + $this->fixed_amount, + $this->minimum_amount + ); + // phpcs:enable WordPress.Security.EscapeOutput.OutputNotEscaped + } + ?> payment_mode ) { @@ -428,6 +529,231 @@ private function get_registered_payment_methods() { return $methods; } + // BOTH MODE: start — helper renderers for the dual-mode chooser and amount displays. + + /** + * Render the one-time / subscription radio chooser shown only in "both" mode. + * + * @return string Chooser markup. + * @since 2.8.2 + */ + private function render_payment_type_chooser() { + $chooser_name = 'srfm-payment-type-choice-' . $this->block_id; + $is_one_time = 'one-time' === $this->default_payment_choice; + + $options = [ + [ + 'value' => 'one-time', + 'label' => $this->one_time_label, + 'checked' => $is_one_time, + ], + [ + 'value' => 'subscription', + 'label' => $this->subscription_label, + 'checked' => ! $is_one_time, + ], + ]; + + ob_start(); + ?> +
+ block_id . '-' . $opt['value']; + $panel_id = 'srfm-payment-amount-' . $this->block_id . '-' . $opt['value']; + // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped -- render_radio_pill handles its own escaping. + echo $this->render_radio_pill( + [ + 'wrapper_class' => 'srfm-payment-type-choice srfm-payment-type-choice--' . $opt['value'], + 'radio_id' => $radio_id, + 'name' => $chooser_name, + 'value' => $opt['value'], + 'label' => $opt['label'], + 'checked' => $opt['checked'], + 'radio_class' => 'srfm-payment-type-choice-radio', + 'aria_controls' => $panel_id, + 'data_attrs' => [ 'data-payment-type' => $opt['value'] ], + ] + ); + // phpcs:enable WordPress.Security.EscapeOutput.OutputNotEscaped + } + ?> +
+ } $args Pill config. + * @return string Pill markup. + * @since 2.8.2 + */ + private function render_radio_pill( $args ) { + $check_svg = Helper::fetch_svg( 'circle-checked', 'srfm-payment-icon', 'aria-hidden="true"' ); + $unchecked_svg = Helper::fetch_svg( 'circle-unchecked', 'srfm-payment-icon-unchecked', 'aria-hidden="true"' ); + + $data_attrs_html = ''; + if ( ! empty( $args['data_attrs'] ) && is_array( $args['data_attrs'] ) ) { + foreach ( $args['data_attrs'] as $key => $val ) { + $data_attrs_html .= ' ' . esc_attr( $key ) . '="' . esc_attr( $val ) . '"'; + } + } + + ob_start(); + ?> + + + +
+ + subscription_plan ) ) { + $interval = $this->subscription_plan['interval'] ?? 'month'; + $billing_cycles = $this->subscription_plan['billingCycles'] ?? 0; + $interval_label = $this->get_interval_label( $interval ); + + if ( 'ongoing' === $billing_cycles ) { + echo esc_html( + sprintf( + /* translators: 1: Amount with currency, 2: Interval (day/week/month/quarter/year) */ + __( '%1$s per %2$s (until cancelled)', 'sureforms' ), + $this->format_currency( $fixed_amount, $this->currency ), + $interval_label + ) + ); + } elseif ( $billing_cycles > 0 ) { + echo esc_html( + sprintf( + /* translators: 1: Amount with currency, 2: Interval (day/week/month/quarter/year), 3: Number of billing cycles */ + __( '%1$s per %2$s (%3$s payments)', 'sureforms' ), + $this->format_currency( $fixed_amount, $this->currency ), + $interval_label, + $billing_cycles + ) + ); + } else { + echo esc_html( + sprintf( + /* translators: 1: Amount with currency, 2: Interval (day/week/month/quarter/year) */ + __( '%1$s per %2$s', 'sureforms' ), + $this->format_currency( $fixed_amount, $this->currency ), + $interval_label + ) + ); + } + } else { + echo esc_html( $this->format_currency( $fixed_amount, $this->currency ) ); + } + ?> + +
+ subscription_plan ) ) { + $interval = $this->subscription_plan['interval'] ?? 'month'; + $billing_cycles = $this->subscription_plan['billingCycles'] ?? 0; + $interval_label = $this->get_interval_label( $interval ); + + if ( 'ongoing' === $billing_cycles ) { + /* translators: 1: Amount with currency placeholder, 2: Interval (day/week/month/quarter/year) */ + $message_format = sprintf( __( '{amount} per %s (until cancelled)', 'sureforms' ), $interval_label ); + } elseif ( $billing_cycles > 0 ) { + /* translators: 1: Amount with currency placeholder, 2: Interval (day/week/month/quarter/year), 3: Number of billing cycles */ + $message_format = sprintf( __( '{amount} per %1$s (%2$s payments)', 'sureforms' ), $interval_label, $billing_cycles ); + } else { + /* translators: 1: Amount with currency placeholder, 2: Interval (day/week/month/quarter/year) */ + $message_format = sprintf( __( '{amount} per %s', 'sureforms' ), $interval_label ); + } + } + ?> + +
+
+ +
+ 0 ) { ?> + + format_currency( $minimum_amount, $this->currency ) + ) + ); + ?> + + +
+ payment_type ) { + // BOTH MODE: subscription is a possible end-user choice, so name field is also required. + if ( 'subscription' === $this->original_payment_type || 'both' === $this->original_payment_type ) { if ( empty( $this->customer_name_field ) ) { return false; } diff --git a/inc/fields/textarea-markup.php b/inc/fields/textarea-markup.php index 8b9553edb..5bf7f6d49 100644 --- a/inc/fields/textarea-markup.php +++ b/inc/fields/textarea-markup.php @@ -20,6 +20,22 @@ * @since 0.0.1 */ class Textarea_Markup extends Base { + /** + * Minimum length of text required for the textarea. + * + * @var string + * @since 2.8.2 + */ + protected $min_length; + + /** + * HTML attribute string for the minimum length. + * + * @var string + * @since 2.8.2 + */ + protected $min_length_attr; + /** * Maximum length of text allowed for the textarea. * @@ -94,21 +110,33 @@ public function __construct( $attributes ) { $this->set_properties( $attributes ); $this->set_input_label( __( 'Textarea', 'sureforms' ) ); $this->set_error_msg( $attributes, 'srfm_textarea_block_required_text' ); - $this->slug = 'textarea'; + $this->slug = 'textarea'; + $this->is_richtext = $attributes['isRichText'] ?? false; + // Min-length only applies to plain textareas; the rich-text submission contains HTML markup. + $this->min_length = $this->is_richtext ? '' : ( $attributes['minLength'] ?? '' ); $this->max_length = $attributes['maxLength'] ?? ''; - $this->rows = $attributes['rows'] ?? ''; - $this->read_only = ! empty( trim( $this->default ) ) && $attributes['readOnly']; + // Misconfiguration guard — if min exceeds max, drop min so the form stays submittable. + // The editor already warns the form-builder when this happens. + if ( + '' !== $this->min_length && + '' !== $this->max_length && + (int) $this->min_length > (int) $this->max_length + ) { + $this->min_length = ''; + } + $this->rows = $attributes['rows'] ?? ''; + $this->read_only = ! empty( trim( $this->default ) ) && $attributes['readOnly']; // html attributes. + $this->min_length_attr = $this->min_length ? ' data-minlength="' . esc_attr( $this->min_length ) . '" ' : ''; $this->max_length_attr = $this->max_length ? ' maxLength="' . esc_attr( $this->max_length ) . '" ' : ''; $this->rows_attr = $this->rows ? ' rows="' . esc_attr( $this->rows ) . '" ' : ''; $this->max_length_html = '' !== $this->max_length ? '0/' . $this->max_length : ''; $this->random_id = wp_rand( 1000, 9999 ); $this->set_unique_slug(); $this->set_field_name( $this->unique_slug ); - $this->set_markup_properties( $this->input_label . '-' . $this->random_id ); + $this->set_markup_properties( $this->input_label . '-' . $this->random_id, ! empty( $this->min_length ) ); $this->set_aria_described_by(); $this->set_label_as_placeholder( $this->input_label ); - $this->is_richtext = $attributes['isRichText'] ?? false; } /** @@ -143,7 +171,7 @@ class="srfm-input-common srfm-input-slug ); ?>" name="field_name ); ?>" id="" aria_described_by ) ? "aria-describedby='" . esc_attr( trim( $this->aria_described_by ) ) . "'" : ''; ?> - data-required="data_require_attr ); ?>" aria-required="data_require_attr ); ?>" max_length_attr . '' . $this->rows_attr ); ?> placeholder_attr ); ?> + data-required="data_require_attr ); ?>" aria-required="data_require_attr ); ?>" min_length_attr . $this->max_length_attr . $this->rows_attr ); ?> placeholder_attr ); ?> is_richtext ? 'data-is-richtext="true"' : ''; ?> read_only ? 'readonly' : ''; ?> >default ); ?> diff --git a/inc/form-restriction.php b/inc/form-restriction.php index 29a50d9e0..a293a1b53 100644 --- a/inc/form-restriction.php +++ b/inc/form-restriction.php @@ -132,6 +132,28 @@ public static function has_entries_limit_reached( $form_id, $form_restriction = $entries_count = 0; // Ensure entries count is a non-negative integer. } + /** + * Filter the count of entries used to evaluate the Maximum Number of Entries + * cap. Allows extensions (e.g. SureForms Pro's Recurring Entry Limit) to + * substitute a window-scoped count — entries since the start of today / + * the current week / month / year — in place of the lifetime count. + * + * Returning a value greater than `$entries_count` will trip the cap sooner; + * returning a smaller value will defer it. Non-integer return values are + * coerced back to a non-negative integer. + * + * @param int $entries_count Lifetime entry count for the form. + * @param int $form_id The ID of the form. + * @param array $form_restriction The form restriction settings. + * @since 2.8.2 + */ + $entries_count = apply_filters( 'srfm_form_restriction_entries_count', $entries_count, $form_id, $form_restriction ); + + // Always coerce to a non-negative integer — covers both non-int returns + // from a misbehaving extension AND negative-int returns that would + // otherwise silently disable the cap (e.g. -5 >= 100 is false). + $entries_count = max( 0, (int) $entries_count ); + return $entries_count >= $max_entries; } diff --git a/inc/global-settings/global-settings.php b/inc/global-settings/global-settings.php index 1d782ab93..2b1022ef8 100644 --- a/inc/global-settings/global-settings.php +++ b/inc/global-settings/global-settings.php @@ -213,6 +213,7 @@ public static function srfm_save_general_settings_dynamic_opt( $setting_options 'srfm_valid_url', 'srfm_confirm_email_same', 'srfm_valid_email', + 'srfm_textarea_min_chars', 'srfm_input_min_value', 'srfm_input_max_value', 'srfm_dropdown_min_selections', diff --git a/inc/payments/front-end.php b/inc/payments/front-end.php index 1c7e91a1e..df9f8878e 100644 --- a/inc/payments/front-end.php +++ b/inc/payments/front-end.php @@ -9,6 +9,7 @@ namespace SRFM\Inc\Payments; use SRFM\Inc\Database\Tables\Payments; +use SRFM\Inc\Field_Validation; use SRFM\Inc\Payments\Stripe\Stripe_Helper; use SRFM\Inc\Submit_Token; use SRFM\Inc\Traits\Get_Instance; @@ -97,7 +98,8 @@ public function create_payment_intent() { wp_send_json_error( __( 'Invalid form configuration.', 'sureforms' ) ); } - $validation_result = Payment_Helper::validate_payment_amount( $amount_processed_with_currency, $currency, $form_id, $block_id ); + // BOTH MODE: pass 'one-time' so the validator uses the correct per-type amount config. + $validation_result = Payment_Helper::validate_payment_amount( $amount_processed_with_currency, $currency, $form_id, $block_id, 'one-time' ); if ( ! $validation_result['valid'] ) { wp_send_json_error( $validation_result['message'] ); } @@ -218,14 +220,17 @@ public function create_payment_intent() { } // Store payment intent metadata in transient for verification. + // active_type binds this intent to the one-time flow so a tampered + // submission cannot replay it through the subscription submit path. Payment_Helper::store_payment_intent_metadata( $block_id, $payment_intent['id'], [ - 'form_id' => $form_id, - 'block_id' => $block_id, - 'amount' => $amount_processed_with_currency, - 'currency' => strtolower( $currency ), + 'form_id' => $form_id, + 'block_id' => $block_id, + 'amount' => $amount_processed_with_currency, + 'currency' => strtolower( $currency ), + 'active_type' => 'one-time', ] ); @@ -298,7 +303,8 @@ public function create_subscription_intent() { wp_send_json_error( __( 'Invalid form configuration.', 'sureforms' ) ); } - $validation_result = Payment_Helper::validate_payment_amount( $amount_processed_with_currency, $currency, $form_id, $block_id ); + // BOTH MODE: pass 'subscription' so the validator uses the correct per-type amount config. + $validation_result = Payment_Helper::validate_payment_amount( $amount_processed_with_currency, $currency, $form_id, $block_id, 'subscription' ); if ( ! $validation_result['valid'] ) { wp_send_json_error( $validation_result['message'] ); } @@ -309,11 +315,25 @@ public function create_subscription_intent() { } // Validate interval like simple-stripe-subscriptions. - $valid_intervals = [ 'day', 'week', 'month', 'year' ]; + // BOTH MODE: 'quarter' is a valid editor option but was missing from the allow-list, + // causing Quarterly subscriptions to be rejected at submit time. + $valid_intervals = [ 'day', 'week', 'month', 'quarter', 'year' ]; if ( ! in_array( $subscription_interval, $valid_intervals, true ) ) { wp_send_json_error( __( 'Invalid billing interval', 'sureforms' ) ); } + // Reject when the submitted interval does not match what the admin saved in + // the form's stored block config. Admin picks a single interval in the editor; + // the end user has no chooser. So a divergence here is always tampering — the + // data attribute the server itself rendered has been altered before submit. + $stored_block_config = Field_Validation::get_or_migrate_block_config_for_legacy_form( $form_id ); + if ( is_array( $stored_block_config ) && isset( $stored_block_config[ $block_id ] ) && is_array( $stored_block_config[ $block_id ] ) ) { + $stored_interval = $stored_block_config[ $block_id ]['subscription_interval'] ?? ''; + if ( ! empty( $stored_interval ) && $stored_interval !== $subscription_interval ) { + wp_send_json_error( __( 'Billing interval does not match the form configuration.', 'sureforms' ) ); + } + } + try { // Validate Stripe connection. if ( ! Stripe_Helper::is_stripe_connected() ) { @@ -412,6 +432,8 @@ public function create_subscription_intent() { } // Store subscription metadata in transient for verification. + // active_type binds this intent to the subscription flow so a tampered + // submission cannot replay it through the one-time submit path. Payment_Helper::store_payment_intent_metadata( $block_id, $payment_intent_id, @@ -421,6 +443,7 @@ public function create_subscription_intent() { 'amount' => $amount_processed_with_currency, 'currency' => strtolower( $currency ), 'subscription_id' => $subscription_id, + 'active_type' => 'subscription', ] ); @@ -586,7 +609,8 @@ public function verify_stripe_subscription_intent_and_save( $subscription_value, $setup_intent_id = ! empty( $subscription_value['setupIntent'] ) && is_string( $subscription_value['setupIntent'] ) ? $subscription_value['setupIntent'] : ''; // Verify payment intent with comprehensive validation including form data. - $verification_result = Payment_Helper::verify_payment_intent( $block_id, $setup_intent_id, $form_data ); + // BOTH MODE: pass 'subscription' so per-type amount config is used for verification. + $verification_result = Payment_Helper::verify_payment_intent( $block_id, $setup_intent_id, $form_data, 'subscription' ); if ( false === $verification_result['valid'] ) { return [ @@ -638,6 +662,25 @@ public function verify_stripe_subscription_intent_and_save( $subscription_value, 'collection_method' => 'charge_automatically', ]; + // Override interval + billing cycles with the values stored in the + // form's block config. These come from the data attributes the + // server itself rendered, so they cannot legitimately diverge from + // the admin's saved subscriptionPlan. Trusting the submitted values + // would let an attacker DevTools-flip cancel_at to 'ongoing'. + $form_id_for_config = isset( $form_data['form-id'] ) && is_numeric( $form_data['form-id'] ) ? intval( $form_data['form-id'] ) : 0; + if ( $form_id_for_config > 0 && ! empty( $block_id ) ) { + $stored_block_config = Field_Validation::get_or_migrate_block_config_for_legacy_form( $form_id_for_config ); + if ( is_array( $stored_block_config ) && isset( $stored_block_config[ $block_id ] ) && is_array( $stored_block_config[ $block_id ] ) ) { + $stored_payment_config = $stored_block_config[ $block_id ]; + if ( isset( $stored_payment_config['subscription_interval'] ) ) { + $subscription_value['subscriptionInterval'] = $stored_payment_config['subscription_interval']; + } + if ( isset( $stored_payment_config['subscription_billing_cycles'] ) ) { + $subscription_value['subscriptionBillingCycles'] = $stored_payment_config['subscription_billing_cycles']; + } + } + } + // Calculate cancel_at timestamp based on billing cycles and interval. $cancel_at = $this->prepare_cancel_at( $subscription_value ); if ( ! empty( $cancel_at ) ) { @@ -1101,7 +1144,8 @@ private function verify_stripe_payment_intent_and_save( $payment_value, $payment } // Verify payment intent with comprehensive validation including form data. - $verification_result = Payment_Helper::verify_payment_intent( $block_id, $payment_id, $form_data ); + // BOTH MODE: pass 'one-time' so per-type amount config is used for verification. + $verification_result = Payment_Helper::verify_payment_intent( $block_id, $payment_id, $form_data, 'one-time' ); if ( false === $verification_result['valid'] ) { return [ diff --git a/inc/payments/payment-helper.php b/inc/payments/payment-helper.php index b8376d736..13843f38e 100644 --- a/inc/payments/payment-helper.php +++ b/inc/payments/payment-helper.php @@ -575,7 +575,8 @@ public static function get_error_message_by_key( $key ) { * @param int|float $amount Amount in smallest currency unit (e.g., cents for USD). * @param string $currency Currency code (e.g., 'usd', 'eur'). * @param int $form_id WordPress post ID of the form. - * @param string $block_id Block identifier for the payment block. + * @param string $block_id Block identifier for the payment block. + * @param string $active_type Optional. 'one-time' or 'subscription' for "both" mode resolution. * @return array { * Validation result. * @@ -583,7 +584,7 @@ public static function get_error_message_by_key( $key ) { * @type string $message Error message if validation failed, empty if valid. * } */ - public static function validate_payment_amount( $amount, $currency, $form_id, $block_id ) { + public static function validate_payment_amount( $amount, $currency, $form_id, $block_id, $active_type = '' ) { // Retrieve block configuration from post meta. $block_config = Field_Validation::get_or_migrate_block_config_for_legacy_form( $form_id ); @@ -614,13 +615,31 @@ public static function validate_payment_amount( $amount, $currency, $form_id, $b ]; } + // Reject when the requested flow (one-time vs subscription) is not allowed by + // the form's stored payment_type. "both" mode allows either flow; pure modes + // allow only their matching flow. Without this guard, an attacker could call + // the wrong intent-creation route on a pure-subscription form and pay once for + // what should be a recurring charge (or vice versa). + $payment_type = isset( $payment_config['payment_type'] ) && is_string( $payment_config['payment_type'] ) ? $payment_config['payment_type'] : 'one-time'; + if ( ! empty( $active_type ) && 'both' !== $payment_type && $active_type !== $payment_type ) { + return [ + 'valid' => false, + 'message' => __( 'Payment type does not match the form configuration.', 'sureforms' ), + ]; + } + + // BOTH MODE: when payment_type is 'both', resolve the correct per-type + // config (amount_type, fixed_amount, minimum_amount, variable_amount_field) + // based on which flow the user actually chose (one-time vs subscription). + $resolved_config = self::resolve_payment_config_for_active_type( $payment_config, $active_type ); + // Get amount type (fixed or minimum). - $amount_type = $payment_config['amount_type'] ?? 'fixed'; + $amount_type = $resolved_config['amount_type'] ?? 'fixed'; // Validate based on amount type. if ( 'fixed' === $amount_type ) { // Fixed amount validation - must match exactly. - $configured_amount = isset( $payment_config['fixed_amount'] ) ? floatval( $payment_config['fixed_amount'] ) : 10.00; + $configured_amount = isset( $resolved_config['fixed_amount'] ) ? floatval( $resolved_config['fixed_amount'] ) : 10.00; // Allow small floating point difference (0.01) due to rounding. if ( abs( $amount - $configured_amount ) > 0.01 ) { @@ -632,7 +651,7 @@ public static function validate_payment_amount( $amount, $currency, $form_id, $b } } elseif ( 'variable' === $amount_type ) { // Minimum amount validation - must be >= minimum. - $minimum_amount = isset( $payment_config['minimum_amount'] ) ? floatval( $payment_config['minimum_amount'] ) : 0; + $minimum_amount = isset( $resolved_config['minimum_amount'] ) ? floatval( $resolved_config['minimum_amount'] ) : 0; if ( $amount < $minimum_amount ) { return [ @@ -644,7 +663,7 @@ public static function validate_payment_amount( $amount, $currency, $form_id, $b // Validate dynamic amount from dropdown/multi-choice field. $dynamic_amount_validation = self::validate_dynamic_amount_field( - $payment_config, + $resolved_config, $block_config, $amount, $currency @@ -699,6 +718,7 @@ public static function store_payment_intent_metadata( $block_id, $payment_intent * @param string $block_id Block identifier. * @param string $payment_intent_id Payment intent ID from Stripe. * @param array $form_data Submitted form data. + * @param string $active_type Optional. 'one-time' or 'subscription' for "both" mode resolution. * @return array { * Verification result. * @@ -706,7 +726,7 @@ public static function store_payment_intent_metadata( $block_id, $payment_intent * @type string $message Error message if verification failed, empty if valid. * } */ - public static function verify_payment_intent( $block_id, $payment_intent_id, $form_data ) { + public static function verify_payment_intent( $block_id, $payment_intent_id, $form_data, $active_type = '' ) { // Get form ID from form data for verification. $form_id = isset( $form_data['form-id'] ) && ! empty( $form_data['form-id'] ) && is_numeric( $form_data['form-id'] ) ? intval( $form_data['form-id'] ) : 0; @@ -729,10 +749,22 @@ public static function verify_payment_intent( $block_id, $payment_intent_id, $fo ]; } + // Reject when the submit path's active_type does not match the type that + // was validated at intent-creation time. Prevents an attacker from passing + // a one-time intent_id through the subscription submit path (or vice versa) + // to replay a small one-time charge in place of a recurring subscription. + $stored_active_type = isset( $metadata['active_type'] ) && is_string( $metadata['active_type'] ) ? $metadata['active_type'] : ''; + if ( ! empty( $active_type ) && ! empty( $stored_active_type ) && $active_type !== $stored_active_type ) { + return [ + 'valid' => false, + 'message' => __( 'Payment verification failed. Payment type mismatch.', 'sureforms' ), + ]; + } + $payment_amount = isset( $metadata['amount'] ) && ! empty( $metadata['amount'] ) && is_numeric( $metadata['amount'] ) ? floatval( $metadata['amount'] ) : 0; // Validate payment amount matches configuration. - $amount_validation = self::validate_payment_intent_amount( $block_id, $form_id, $form_data, $payment_amount ); + $amount_validation = self::validate_payment_intent_amount( $block_id, $form_id, $form_data, $payment_amount, $active_type ); if ( false === $amount_validation['valid'] ) { return $amount_validation; @@ -788,6 +820,63 @@ public static function get_currency_sign_position() { * @return array|null Validation result array or null if validation passes. * @since 2.3.0 */ + /** + * BOTH MODE: resolve the correct amount config keys from the payment block + * config based on which flow (one-time or subscription) the user chose. + * + * For pure one-time / subscription blocks, the config already has the correct + * scalar keys (amount_type, fixed_amount, minimum_amount, etc.) so this method + * returns them unchanged. For "both" blocks, it remaps the per-type keys + * (one_time_* or subscription_*) into the scalar positions the validation + * functions expect. + * + * @param array $payment_config Full block config from _srfm_block_config. + * @param string $active_type 'one-time' or 'subscription' — which flow is active. + * @return array Config array with amount_type, fixed_amount, minimum_amount, + * variable_amount_field, variable_amount_field_block_name resolved + * for the active type. + * @since 2.8.2 + */ + private static function resolve_payment_config_for_active_type( $payment_config, $active_type ) { + // Only remap when the block is in "both" mode and the caller told us the active type. + if ( 'both' !== ( $payment_config['payment_type'] ?? '' ) || empty( $active_type ) ) { + return $payment_config; + } + + $prefix = 'subscription' === $active_type ? 'subscription_' : 'one_time_'; + + $resolved = $payment_config; // Keep all original keys as fallback. + + if ( isset( $payment_config[ $prefix . 'amount_type' ] ) ) { + $resolved['amount_type'] = $payment_config[ $prefix . 'amount_type' ]; + } + if ( isset( $payment_config[ $prefix . 'fixed_amount' ] ) ) { + $resolved['fixed_amount'] = (float) $payment_config[ $prefix . 'fixed_amount' ]; + } + if ( isset( $payment_config[ $prefix . 'minimum_amount' ] ) ) { + $resolved['minimum_amount'] = (float) $payment_config[ $prefix . 'minimum_amount' ]; + } + if ( isset( $payment_config[ $prefix . 'variable_amount_field' ] ) ) { + $resolved['variable_amount_field'] = $payment_config[ $prefix . 'variable_amount_field' ]; + } + if ( isset( $payment_config[ $prefix . 'variable_amount_field_block_name' ] ) ) { + $resolved['variable_amount_field_block_name'] = $payment_config[ $prefix . 'variable_amount_field_block_name' ]; + } + + return $resolved; + } + + /** + * Validate that a submitted dynamic amount matches one of the options configured + * on a linked dropdown/multi-choice block (when single-selection is enabled). + * + * @since 2.8.2 + * @param array $payment_config Resolved payment block config (active for current mode). + * @param array $block_config All form block configs keyed by block_id. + * @param float $submitted_amount_decimal Submitted amount as a decimal (not smallest unit). + * @param string $currency ISO currency code. + * @return array|null Validation result array with 'valid' + 'message', or null when no validation is required. + */ private static function validate_dynamic_amount_field( $payment_config, $block_config, $submitted_amount_decimal, $currency ) { // Check if variable amount field is from dropdown or multi-choice block. $dynamic_amount_field_block_name = $payment_config['variable_amount_field_block_name'] ?? ''; @@ -878,6 +967,7 @@ private static function validate_dynamic_amount_field( $payment_config, $block_c * @param int $form_id Form post ID. * @param array $form_data Submitted form data. * @param int|float $payment_amount Payment amount from Stripe (in smallest currency unit). + * @param string $active_type Optional. 'one-time' or 'subscription' for "both" mode resolution. * @return array { * Validation result. * @@ -885,7 +975,7 @@ private static function validate_dynamic_amount_field( $payment_config, $block_c * @type string $message Error message if validation failed, empty if valid. * } */ - private static function validate_payment_intent_amount( $block_id, $form_id, $form_data, $payment_amount ) { + private static function validate_payment_intent_amount( $block_id, $form_id, $form_data, $payment_amount, $active_type = '' ) { // Get block configuration. $block_config = Field_Validation::get_or_migrate_block_config_for_legacy_form( $form_id ); @@ -897,12 +987,13 @@ private static function validate_payment_intent_amount( $block_id, $form_id, $fo ]; } - $payment_config = $block_config[ $block_id ]; - $amount_type = $payment_config['amount_type'] ?? 'fixed'; + $payment_config = $block_config[ $block_id ]; + $resolved_config = self::resolve_payment_config_for_active_type( $payment_config, $active_type ); + $amount_type = $resolved_config['amount_type'] ?? 'fixed'; // For fixed amounts, validate against configured amount. if ( 'fixed' === $amount_type ) { - $configured_amount = isset( $payment_config['fixed_amount'] ) ? floatval( $payment_config['fixed_amount'] ) : 0; + $configured_amount = isset( $resolved_config['fixed_amount'] ) ? floatval( $resolved_config['fixed_amount'] ) : 0; // Allow small floating point difference (0.01) due to rounding. if ( abs( $payment_amount - $configured_amount ) > 0.01 ) { @@ -922,8 +1013,8 @@ private static function validate_payment_intent_amount( $block_id, $form_id, $fo // For variable amounts, validate based on source field. if ( 'variable' === $amount_type ) { // Check if variable amount comes from dropdown/multi-choice. - $dynamic_amount_field_block_name = $payment_config['variable_amount_field_block_name'] ?? ''; - $variable_amount_field_slug = $payment_config['variable_amount_field'] ?? ''; + $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. if ( empty( $dynamic_amount_field_block_name ) || empty( $variable_amount_field_slug ) ) { @@ -1000,10 +1091,32 @@ private static function validate_payment_intent_amount( $block_id, $form_id, $fo 'message' => sprintf( __( 'Payment amount mismatch. Expected %1$s, received %2$s.', 'sureforms' ), $converted_payment_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; + + if ( $expected_amount <= 0 ) { + return [ + 'valid' => false, + 'message' => __( 'Variable amount field value is required.', '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 ), + ]; + } } - // For other variable amount sources (e.g., number field), validate minimum amount. - $minimum_amount = isset( $payment_config['minimum_amount'] ) ? floatval( $payment_config['minimum_amount'] ) : 0; + // All variable amount sources (number, hidden) 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; if ( $payment_amount < $minimum_amount ) { return [ @@ -1158,6 +1271,8 @@ private static function get_form_submitted_value_by_slug_and_block_name( $variab $block_name = 'srfm-input-multi-choice'; } elseif ( 'srfm/number' === $dynamic_amount_field_block_name ) { $block_name = 'srfm-number'; + } elseif ( 'srfm/hidden' === $dynamic_amount_field_block_name ) { + $block_name = 'srfm-hidden'; } // Now we need to get the submitted value. diff --git a/inc/translatable.php b/inc/translatable.php index 631489c9d..7506e8faa 100644 --- a/inc/translatable.php +++ b/inc/translatable.php @@ -90,6 +90,9 @@ public static function dynamic_messages() { 'srfm_confirm_email_same' => __( 'Confirmation email does not match.', 'sureforms' ), 'srfm_valid_email' => __( 'Enter a valid email address.', 'sureforms' ), + /* translators: %s represents the minimum number of characters required */ + 'srfm_textarea_min_chars' => __( 'Please enter at least %s characters.', 'sureforms' ), + /* translators: %s represents the minimum acceptable value */ 'srfm_input_min_value' => __( 'Minimum value is %s.', 'sureforms' ), diff --git a/internal-docs/README.md b/internal-docs/README.md deleted file mode 100644 index 9a933cae0..000000000 --- a/internal-docs/README.md +++ /dev/null @@ -1,160 +0,0 @@ -# SureForms Internal Documentation - -**Version:** 2.5.0 -**Last Updated:** February 2026 -**Target Audience:** Developers, AI Agents, Technical Team - ---- - -## Welcome - -This is the internal documentation for **SureForms Free** and **SureForms Pro** - WordPress form builder plugins used by 300,000+ websites. - -**SureForms Free:** AI-powered form builder with payments (Stripe), native WordPress blocks, 16+ fields -**SureForms Pro:** Advanced features - conversational forms, multi-step, conditional logic, PayPal, 24+ integrations - ---- - -## Quick Start - -### For New Developers (1 Hour) - -1. **Install locally:** - ```bash - cd /path/to/wordpress/wp-content/plugins - git clone https://github.com/brainstormforce/sureforms.git - git clone https://github.com/brainstormforce/sureforms-pro.git - cd sureforms && npm install && npm run build - cd ../sureforms-pro && npm install && npm run build - ``` - -2. **Activate plugins:** - - SureForms Free (required) - - SureForms Pro (optional, requires Free) - -3. **Create first form:** - - Dashboard → SureForms → Add New - - Try AI form builder or blank form - - Add fields from block inserter - - Publish and test submission - -4. **Read these docs:** - - [Architecture](architecture.md) - System design - - [Codebase Map](codebase-map.md) - Where is what - - [APIs](apis.md) - REST, AJAX, hooks - -### For AI Agents - -Start with [ai-agent-guide.md](ai-agent-guide.md) for codebase conventions, patterns, and agent-specific guidance. - ---- - -## Key Files & Directories - -| Path | Purpose | -|------|---------| -| `sureforms/inc/` | Core PHP logic | -| `sureforms/inc/blocks/` | Gutenberg block PHP | -| `sureforms/src/` | React components (admin UI) | -| `sureforms/inc/payments/` | Stripe payment processing | -| `sureforms/inc/ai-form-builder/` | AI form generation | -| `sureforms-pro/inc/business/` | Pro features (PayPal, registration, PDF) | -| `sureforms-pro/inc/pro/native-integrations/` | 24+ service integrations | - ---- - -## Build System - -**SureForms Free:** -```bash -npm run build # Full build (webpack + sass + grunt) -npm run start # Dev mode (watch) -npm run lint-js:fix # Fix JS linting -npm run makepot # Generate translation files -``` - -**SureForms Pro:** -```bash -npm run build # Full build -npm run package # Create distributable zip -``` - -Both use: -- **@wordpress/scripts** (webpack 5, Babel, ESLint) -- **Grunt** (minification, compression) -- **Sass** for CSS compilation - ---- - -## Database Tables - -Custom tables (via `inc/database/`): - -| Table | Purpose | -|-------|---------| -| `wp_sureforms_entries` | Form submissions | -| `wp_sureforms_payments` | Payment transactions (Stripe/PayPal) | -| `wp_sureforms_integrations` | Native integration credentials (encrypted) | -| `wp_sureforms_save_resume` | Draft form state (Pro) | - ---- - -## Testing - -**Unit Tests:** -```bash -composer test # PHPUnit -npm run test:unit # Jest (JS) -``` - -**E2E Tests:** -```bash -npm run play:up # Start wp-env -npm run play:run # Run Playwright tests -``` - -**Code Quality:** -```bash -composer lint # PHP_CodeSniffer -composer phpstan # Static analysis -npm run lint-js # ESLint -``` - ---- - -## Release Process - -**Free (WordPress.org):** -1. Update version in `sureforms.php` and `package.json` -2. Run `npm run build && grunt release` -3. Files excluded via `.distignore` -4. SVN commit to WordPress.org repo - -**Pro (Custom Distribution):** -1. Update version in `sureforms-pro.php` -2. Run `npm run build && npm run package` -3. Generates `sureforms-pro.zip` -4. Deploy to licensing server - ---- - -## Support & Resources - -- **GitHub (Free):** https://github.com/brainstormforce/sureforms -- **GitHub (Pro):** https://github.com/brainstormforce/sureforms-pro -- **Documentation:** https://sureforms.com/docs/ -- **Bug Bounty:** https://brainstormforce.com/bug-bounty-program/ -- **Support:** support@brainstormforce.com - ---- - -## Next Steps - -- **Product Vision:** [product-vision.md](product-vision.md) - Understand goals and personas -- **Architecture:** [architecture.md](architecture.md) - System design and data flow -- **Onboarding:** [onboarding.md](onboarding.md) - 1-hour, 1-day, 1-week learning paths - ---- - -**Maintained by:** SureForms Engineering Team -**Contact:** engineering@brainstormforce.com diff --git a/internal-docs/ai-agent-guide.md b/internal-docs/ai-agent-guide.md deleted file mode 100644 index 867f3c7ea..000000000 --- a/internal-docs/ai-agent-guide.md +++ /dev/null @@ -1,459 +0,0 @@ -# AI Agent Guide - -**Version:** 2.5.0 -**For:** AI Coding Agents & LLMs - ---- - -## Overview - -This guide helps AI agents understand SureForms codebase conventions, make safe changes, and avoid common pitfalls. - ---- - -## Core Principles - -1. **Security First:** Sanitize inputs, escape outputs, use prepared statements -2. **WordPress Standards:** Follow WP coding standards, use WP functions -3. **Backward Compatibility:** Don't break existing forms/entries -4. **Performance:** Avoid N+1 queries, cache when possible -5. **Testing:** Write tests, run existing tests before committing - ---- - -## File Modification Guidelines - -### ✅ Safe to Modify - -**Add features (low risk):** -- New blocks: `inc/blocks/new-block/` -- New integrations (Pro): `inc/pro/native-integrations/integrations/new-service/` -- New validation rules: Add to `inc/field-validation.php` -- New hooks: Add filters/actions (don't remove existing) - -**Extend existing:** -- Add sanitization functions to `inc/helper.php` -- Add validation methods to `inc/field-validation.php` -- Add utility functions to helper classes - -### ⚠️ Modify with Caution - -**Database schema changes:** -- Requires migration script -- Must handle existing data -- Version increments in `inc/database/tables/*.php` - -**Payment processing:** -- `inc/payments/stripe/stripe-webhook.php` -- `inc/business/payments/pay-pal/webhook-listener.php` -- **Risk:** Financial impact if broken - -**Form submission pipeline:** -- `inc/form-submit.php` -- **Risk:** Could break all forms - -### 🚫 High Risk - Avoid Unless Necessary - -**Core WordPress integration:** -- `plugin-loader.php` -- `sureforms.php` / `sureforms-pro.php` - -**Database base class:** -- `inc/database/base.php` (inherited by all tables) - -**Critical security:** -- Nonce verification logic -- Capability checks -- Encryption (Pro): `inc/pro/native-integrations/encryption.php` - ---- - -## Common Patterns - -### Adding a New Field Type - -1. **Create block:** - ``` - inc/blocks/my-field/block.php - src/blocks/my-field/ - ``` - -2. **Register block:** - ```php - // inc/blocks/my-field/block.php - namespace SRFM\Inc\Blocks\My_Field; - - class Block extends \SRFM\Inc\Blocks\Base { - public static function register() { - register_block_type( - 'sureforms/my-field', - [ - 'render_callback' => [__CLASS__, 'render'], - 'attributes' => [/* schema */], - ] - ); - } - - public static function render($attributes) { - // Return HTML - } - } - ``` - -3. **Add to block registry:** - ```php - // inc/blocks/register.php - My_Field\Block::register(); - ``` - -4. **Add sanitization:** - ```php - // inc/helper.php - public static function sanitize_by_field_type($type, $value) { - switch ($type) { - case 'my-field': - return sanitize_text_field($value); - } - } - ``` - -### Adding a REST Endpoint - -```php -// inc/rest-api.php or new file -public function register_routes() { - register_rest_route( - 'sureforms/v1', - '/my-endpoint', - [ - 'methods' => 'POST', - 'callback' => [$this, 'handle_request'], - 'permission_callback' => [$this, 'check_permissions'], - ] - ); -} - -public function check_permissions() { - // CRITICAL: Always verify permissions - return current_user_can('manage_options'); -} - -public function handle_request($request) { - // CRITICAL: Always verify nonce - $nonce = $request->get_header('X-WP-Nonce'); - if (!wp_verify_nonce($nonce, 'wp_rest')) { - return new \WP_Error('invalid_nonce', 'Invalid nonce', ['status' => 403]); - } - - // Sanitize inputs - $data = $request->get_params(); - $clean_data = Helper::sanitize_array_recursively($data); - - // Process... - - return ['success' => true]; -} -``` - -### Adding an Integration (Pro) - -1. **Create integration folder:** - ``` - inc/pro/native-integrations/integrations/myservice/ - ├── config.json - └── actions/ - └── send-data.php - ``` - -2. **config.json:** - ```json - { - "name": "MyService", - "slug": "myservice", - "auth_method": "api_key", - "api_endpoint": "https://api.myservice.com/v1/", - "actions": [ - { - "name": "Send Data", - "slug": "send-data", - "endpoint": "contacts" - } - ] - } - ``` - -3. **actions/send-data.php:** - ```php - namespace SRFM_PRO\Inc\Pro\Native_Integrations\Integrations\Myservice\Actions; - - class Send_Data { - public function execute($integration_data, $form_data) { - $api_key = $integration_data['api_key']; - $response = wp_remote_post( - 'https://api.myservice.com/v1/contacts', - [ - 'headers' => ['Authorization' => 'Bearer ' . $api_key], - 'body' => json_encode($form_data), - ] - ); - - if (is_wp_error($response)) { - return ['success' => false, 'error' => $response->get_error_message()]; - } - - return ['success' => true, 'response' => wp_remote_retrieve_body($response)]; - } - } - ``` - ---- - -## Security Patterns - -### Input Sanitization - -```php -// Text -$name = sanitize_text_field( wp_unslash( $_POST['name'] ?? '' ) ); - -// Email -$email = sanitize_email( wp_unslash( $_POST['email'] ?? '' ) ); - -// Number -$id = absint( $_POST['id'] ?? 0 ); - -// Array (recursive) -$data = Helper::sanitize_array_recursively( $_POST['data'] ?? [] ); - -// Textarea -$message = Helper::sanitize_textarea( wp_unslash( $_POST['message'] ?? '' ) ); -``` - -### Output Escaping - -```php -// HTML content -echo esc_html( $user_name ); - -// Attributes -echo '
'; - -// URLs -echo ''; - -// Rich text (allows safe HTML) -echo wp_kses_post( $content ); -``` - -### Database Queries - -```php -global $wpdb; - -// ✅ Good - Prepared statement -$results = $wpdb->get_results( - $wpdb->prepare( - "SELECT * FROM {$wpdb->prefix}sureforms_entries WHERE form_id = %d AND status = %s", - $form_id, - $status - ) -); - -// ❌ Bad - SQL injection risk -$results = $wpdb->query("DELETE FROM {$wpdb->prefix}sureforms_entries WHERE id = $_POST[id]"); -``` - ---- - -## Testing Your Changes - -### Before Committing - -```bash -# 1. Lint PHP -composer lint - -# 2. Run PHP tests -composer test - -# 3. Lint JavaScript -npm run lint-js - -# 4. Run JS tests -npm run test:unit - -# 5. Build assets -npm run build - -# 6. Test in browser -# - Create form -# - Submit form -# - Check entries -# - Verify no console errors -``` - -### E2E Testing - -```bash -# Start environment -npm run play:up - -# Run tests -npm run play:run - -# Interactive mode (with browser) -npm run play:run:interactive -``` - ---- - -## Database Queries - Common Patterns - -### Get Entries - -```php -use SRFM\Inc\Database\Tables\Entries; - -// Get all for form -$entries = Entries::get_all([ - 'where' => [ - ['key' => 'form_id', 'value' => 123, 'compare' => '='] - ], - 'orderby' => 'created_at', - 'order' => 'DESC', -]); - -// With pagination -$entries = Entries::get_all([ - 'where' => [['key' => 'form_id', 'value' => 123, 'compare' => '=']], - 'limit' => 20, - 'offset' => 40 // Page 3 (20 per page) -]); - -// Count entries -$count = Entries::get_count([ - 'where' => [['key' => 'status', 'value' => 'published', 'compare' => '=']] -]); -``` - -### Get Payments - -```php -use SRFM\Inc\Database\Tables\Payments; - -// Get completed payments -$payments = Payments::get_all([ - 'where' => [ - ['key' => 'status', 'value' => 'completed', 'compare' => '='] - ] -]); - -// Get payment by transaction ID -$payment = Payments::get_by_transaction_id('ch_xxxxx', 'stripe'); -``` - ---- - -## Hooks - When to Use - -### Modify Data Before Save - -```php -// Filter entry data before save -add_filter('sureforms_submit_form_data', function($data, $form_id) { - // Add custom field - $data['custom_timestamp'] = current_time('mysql'); - return $data; -}, 10, 2); -``` - -### Trigger External Action - -```php -// Action after entry save -add_action('sureforms_after_entry_save', function($entry_id, $form_id, $data) { - // Send to external CRM - send_to_crm($data); -}, 10, 3); -``` - -### Modify Email - -```php -// Filter email template -add_filter('sureforms_email_template', function($html, $entry_id) { - // Add custom header - return '
...
' . $html; -}, 10, 2); -``` - ---- - -## Debugging Tips - -### Enable Debug Mode - -```php -// wp-config.php -define('WP_DEBUG', true); -define('WP_DEBUG_LOG', true); -define('WP_DEBUG_DISPLAY', false); -``` - -### Check Debug Log - -```bash -tail -f wp-content/debug.log -``` - -### JavaScript Console - -```javascript -// Check for errors -// Open browser DevTools → Console - -// SureForms global -console.log(window.sureforms); -``` - -### Database Queries - -```php -// Install Query Monitor plugin -// Shows all queries, slow queries, errors -``` - ---- - -## Common Pitfalls to Avoid - -1. **Don't bypass sanitization:** "It's internal, it's safe" → Still sanitize -2. **Don't skip nonce checks:** Every AJAX/REST endpoint needs verification -3. **Don't use `$_POST` directly:** Always sanitize first -4. **Don't concatenate SQL:** Use `$wpdb->prepare()` -5. **Don't echo user data raw:** Use `esc_html()`, `esc_attr()`, etc. -6. **Don't modify database schema without migration:** Breaks existing sites -7. **Don't remove existing hooks:** Other plugins may depend on them -8. **Don't hardcode `wp_` prefix:** Use `$wpdb->prefix` - ---- - -## Getting Help - -**Documentation:** -- This folder: All internal docs -- WordPress Codex: https://codex.wordpress.org/ -- React Docs: https://react.dev/ - -**Code Search:** -- Use Glob/Grep tools to find patterns -- Example: `grep -r "sanitize_text_field" inc/` → See how sanitization is used - -**Ask Before:** -- Breaking changes -- Database schema changes -- Removing existing functionality - ---- - -**Next:** [Troubleshooting](troubleshooting.md) - Common problems and solutions diff --git a/internal-docs/apis.md b/internal-docs/apis.md deleted file mode 100644 index 0a7a16ec7..000000000 --- a/internal-docs/apis.md +++ /dev/null @@ -1,418 +0,0 @@ -# APIs - -Complete API reference for SureForms Free & Pro. - ---- - -## REST API Endpoints - -### Free (`/sureforms/v1/`) - -**Form Management:** -```http -POST /sureforms/v1/generate-form -GET /sureforms/v1/forms -GET /sureforms/v1/forms/{id} -DELETE /sureforms/v1/forms/{id} -``` - -**Form Submission:** -```http -POST /sureforms/v1/submit-form -``` -**Body:** `{ form_id, nonce, field_data... }` -**Response:** `{ success, message, entry_id }` - -**Entries:** -```http -GET /sureforms/v1/entries/list -GET /sureforms/v1/entries/{id} -DELETE /sureforms/v1/entries/{id} -POST /sureforms/v1/entries/export -``` - -**Payments:** -```http -GET /sureforms/v1/payments/list -GET /sureforms/v1/payments/{id} -``` - -**Stripe Webhooks:** -```http -POST /sureforms/webhook_test # Stripe webhooks -POST /sureforms/webhook_live -``` - -**Settings:** -```http -GET /sureforms/v1/settings -POST /sureforms/v1/settings/update -``` - -### Pro (`/sureforms-pro/v1/`) - -**OAuth:** -```http -POST /sureforms-pro/v1/oauth/authorize -POST /sureforms-pro/v1/oauth/callback -``` - -**PayPal Webhooks:** -```http -POST /sureforms-pro/paypal-test-webhook -POST /sureforms-pro/paypal-live-webhook -``` - -**User Registration:** -```http -POST /sureforms-pro/v1/login -POST /sureforms-pro/v1/lost-password -POST /sureforms-pro/v1/reset-password -``` - ---- - -## AJAX Handlers - -### Free (30 handlers) - -**Admin:** -```php -'srfm_admin_action' # Generic admin handler -'srfm_get_forms' # Fetch forms list -'srfm_delete_form' # Delete form -'srfm_duplicate_form' # Duplicate form -'srfm_export_entries' # Export CSV -``` - -**Payments (Public):** -```php -'wp_ajax_srfm_create_payment_intent' # Stripe payment -'wp_ajax_nopriv_srfm_create_payment_intent' -'wp_ajax_srfm_create_subscription_intent' # Stripe subscription -'wp_ajax_nopriv_srfm_create_subscription_intent' -``` - -**Admin Stripe:** -```php -'srfm_stripe_cancel_subscription' # Cancel subscription -'srfm_stripe_pause_subscription' # Pause subscription -``` - -**Admin Payments:** -```php -'srfm_create_payment_refund' # Create refund -``` - -**Form Validation (Public):** -```php -'wp_ajax_srfm_field_unique_validation' # Check unique fields -'wp_ajax_nopriv_srfm_field_unique_validation' -``` - -### Pro (22 handlers) - -**PayPal (Public):** -```php -'wp_ajax_srfm_pro_create_paypal_order' -'wp_ajax_nopriv_srfm_pro_create_paypal_order' -'wp_ajax_srfm_pro_create_paypal_subscription' -'wp_ajax_nopriv_srfm_pro_create_paypal_subscription' -``` - -**PayPal Admin:** -```php -'srfm_pro_paypal_cancel_subscription' -'srfm_pro_paypal_pause_subscription' -``` - -**PDF:** -```php -'srfm_pro_generate_pdf' # Generate PDF from entry -'srfm_pro_download_pdf' # Download PDF -``` - -**Licensing:** -```php -'srfm_pro_activate_license' -'srfm_pro_deactivate_license' -``` - -**Entries:** -```php -'sureforms_pro_entry_delete_file' # Delete uploaded file -``` - ---- - -## WordPress Hooks - -### Actions (Form Submission) - -```php -// Before entry save -do_action('sureforms_before_entry_save', $form_id, $entry_data); - -// After entry save -do_action('sureforms_after_entry_save', $entry_id, $form_id, $entry_data); - -// After payment completed -do_action('sureforms_payment_completed', $payment_id, $entry_id, $gateway); - -// After integration success -do_action('sureforms_integration_success', $integration_type, $response); - -// Before email send -do_action('sureforms_before_email_send', $to, $subject, $message); - -// After form submission (success) -do_action('sureforms_form_submitted', $entry_id, $form_id); -``` - -### Filters (Data Modification) - -```php -// Modify form data before save -$entry_data = apply_filters('sureforms_submit_form_data', $entry_data, $form_id); - -// Modify payment amount -$amount = apply_filters('sureforms_payment_amount', $amount, $form_id, $entry_data); - -// Modify email template -$html = apply_filters('sureforms_email_template', $html, $entry_id, $form_id); - -// Modify email subject -$subject = apply_filters('sureforms_email_subject', $subject, $form_id); - -// Modify email recipients -$to = apply_filters('sureforms_email_recipients', $to, $entry_id, $form_id); - -// Modify confirmation message -$message = apply_filters('sureforms_confirmation_message', $message, $entry_id); - -// Modify field validation -$is_valid = apply_filters('sureforms_validate_field', $is_valid, $field, $value); - -// Modify sanitized value -$value = apply_filters("sureforms_sanitize_{$field_type}", $value, $field); -``` - -### Integration Hooks (Pro) - -```php -// Before integration request -do_action('sureforms_pro_before_integration', $integration, $data); - -// After integration request -do_action('sureforms_pro_after_integration', $integration, $response); - -// Integration error -do_action('sureforms_pro_integration_error', $integration, $error); -``` - ---- - -## JavaScript APIs - -### Global Objects - -```javascript -// Form settings -window.sureforms = { - ajaxUrl: '/wp-admin/admin-ajax.php', - nonce: 'xxx', - formId: 123, - settings: {...} -}; - -// Block editor -window.sureformsBlocks = { - registerBlock: (name, settings) => {...}, - getBlock: (name) => {...} -}; -``` - -### Custom Events - -```javascript -// Form submitted -document.addEventListener('sureforms-form-submitted', (e) => { - console.log('Entry ID:', e.detail.entryId); -}); - -// Payment completed -document.addEventListener('sureforms-payment-completed', (e) => { - console.log('Payment ID:', e.detail.paymentId); -}); - -// Validation error -document.addEventListener('sureforms-validation-error', (e) => { - console.log('Field:', e.detail.field, 'Error:', e.detail.message); -}); -``` - ---- - -## Database APIs - -### Entry Operations - -```php -use SRFM\Inc\Database\Tables\Entries; - -// Get all entries for a form -$entries = Entries::get_all([ - 'where' => [ - ['key' => 'form_id', 'value' => 123, 'compare' => '='] - ], - 'orderby' => 'created_at', - 'order' => 'DESC', - 'limit' => 20, - 'offset' => 0 -]); - -// Get single entry -$entry = Entries::get_by_id(456); - -// Insert entry -$entry_id = Entries::insert([ - 'form_id' => 123, - 'entry_data' => json_encode($data), - 'status' => 'published' -]); - -// Update entry -Entries::update(456, ['status' => 'trash']); - -// Delete entry -Entries::delete(456); -``` - -### Payment Operations - -```php -use SRFM\Inc\Database\Tables\Payments; - -// Get payments -$payments = Payments::get_all_main_payments([ - 'where' => [ - ['key' => 'status', 'value' => 'completed', 'compare' => '='] - ] -]); - -// Create payment -$payment_id = Payments::insert([ - 'entry_id' => 456, - 'transaction_id' => 'ch_xxx', - 'gateway' => 'stripe', - 'status' => 'pending', - 'total_amount' => 99.99, - 'currency' => 'USD' -]); - -// Update payment status -Payments::update($payment_id, ['status' => 'completed']); -``` - ---- - -## Helper APIs - -### Sanitization - -```php -use SRFM\Inc\Helper; - -// Sanitize by field type -$clean = Helper::sanitize_by_field_type('email', $value); -$clean = Helper::sanitize_by_field_type('textarea', $value); -$clean = Helper::sanitize_by_field_type('number', $value); - -// Email-specific -$email = Helper::sanitize_email_header($raw_email); - -// Recursive sanitization -$clean_array = Helper::sanitize_array_recursively($array); -``` - -### Validation - -```php -use SRFM\Inc\Field_Validation; - -// Validate field -$result = Field_Validation::validate_field($field_config, $value); -// Returns: ['valid' => true/false, 'message' => 'Error message'] - -// Validate entire form -$result = Field_Validation::validate_form_data($form_id, $data); -``` - -### Payment Helpers - -```php -use SRFM\Inc\Payments\Payment_Helper; - -// Validate amount against form config -$result = Payment_Helper::validate_payment_amount($amount, $currency, $form_id, $block_id); - -// Get currency -$currency = Payment_Helper::get_currency(); -``` - ---- - -## Encryption API (Pro) - -```php -use SRFM_PRO\Inc\Pro\Native_Integrations\Encryption; - -$enc = new Encryption(); - -// Encrypt sensitive data -$encrypted = $enc->encrypt('oauth_token_12345'); - -// Decrypt -$decrypted = $enc->decrypt($encrypted); - -// Storage: wp_sureforms_integrations.data column -``` - -**Algorithm:** AES-256-CTR -**Key:** `SRFM_ENCRYPTION_KEY` constant or `LOGGED_IN_KEY` - ---- - -## Integration Workflow API (Pro) - -```php -use SRFM_PRO\Inc\Pro\Native_Integrations\Services\Workflow_Processor; - -// Execute integration workflow -$processor = new Workflow_Processor(); -$result = $processor->execute_workflow($integration_config, $entry_data); - -// Returns: ['success' => true/false, 'response' => API response] -``` - ---- - -## Rate Limiting - -**Note:** No built-in rate limiting. Implementations should add: - -```php -// Example pattern (not in core) -$key = 'form_submit_' . $user_ip; -$attempts = get_transient($key) ?: 0; - -if ($attempts >= 5) { - wp_send_json_error('Too many submissions', 429); -} - -set_transient($key, $attempts + 1, 15 * MINUTE_IN_SECONDS); -``` - ---- - -**Next:** [Coding Standards](coding-standards.md) - PHP/JS conventions diff --git a/internal-docs/architecture.md b/internal-docs/architecture.md deleted file mode 100644 index 9e59e0b81..000000000 --- a/internal-docs/architecture.md +++ /dev/null @@ -1,329 +0,0 @@ -# Architecture - -**Version:** 2.5.0 - ---- - -## System Overview - -SureForms is a WordPress form builder with a **Free + Pro** plugin architecture: - -``` -WordPress Site -├── SureForms Free (Required) -│ ├── Core form functionality -│ ├── Stripe payments -│ ├── AI form builder -│ └── Entry management -└── SureForms Pro (Optional Extension) - ├── Advanced features (conditional logic, multi-step) - ├── PayPal payments - ├── User registration/login - └── 24+ native integrations -``` - ---- - -## High-Level Architecture - -``` -┌─────────────────────────────────────────────────────────┐ -│ WordPress Admin │ -│ ┌──────────────────────────────────────────────────┐ │ -│ │ React Admin UI (src/) │ │ -│ │ - Form Builder (Gutenberg Blocks) │ │ -│ │ - Entry Dashboard │ │ -│ │ - Settings Panels │ │ -│ └──────────────────────────────────────────────────┘ │ -└─────────────────────────────────────────────────────────┘ - ↕ -┌─────────────────────────────────────────────────────────┐ -│ REST API Layer │ -│ - /sureforms/v1/* (Free) │ -│ - /sureforms-pro/v1/* (Pro) │ -│ - AJAX handlers (wp_ajax_*) │ -└─────────────────────────────────────────────────────────┘ - ↕ -┌─────────────────────────────────────────────────────────┐ -│ Business Logic (inc/) │ -│ ┌──────────┬──────────┬──────────┬──────────────────┐ │ -│ │ Forms │ Payments │ AI │ Integrations │ │ -│ │ Submit │ Stripe │ Builder │ (Pro: 24+) │ │ -│ │ Validate │ PayPal │ Field │ Mailchimp, etc │ │ -│ │ Store │ Webhooks │ Mapping │ │ │ -│ └──────────┴──────────┴──────────┴──────────────────┘ │ -└─────────────────────────────────────────────────────────┘ - ↕ -┌─────────────────────────────────────────────────────────┐ -│ Data Layer │ -│ ┌──────────────┬────────────────┬──────────────────┐ │ -│ │ WP Options │ Custom Tables │ Encrypted Data │ │ -│ │ Form configs │ Entries │ OAuth tokens │ │ -│ │ Settings │ Payments │ API keys │ │ -│ └──────────────┴────────────────┴──────────────────┘ │ -└─────────────────────────────────────────────────────────┘ - ↕ -┌─────────────────────────────────────────────────────────┐ -│ Frontend Rendering │ -│ - Gutenberg Blocks (PHP + JS) │ -│ - Form submission (AJAX) │ -│ - reCAPTCHA/Turnstile │ -│ - Real-time validation │ -└─────────────────────────────────────────────────────────┘ -``` - ---- - -## Component Breakdown - -### 1. Block System (Gutenberg) - -**Free Blocks (16):** -- Input types: Text, Email, Number, Phone, URL, Textarea, Dropdown -- Special: Address, Checkbox, Multiple Choice, GDPR, Payment -- Layout: Separator, Heading, Image, Icon, Custom Button - -**Pro Blocks (8):** -- Input: Date Picker, Time Picker, Rating, Slider, Hidden, Password -- Advanced: File Upload, HTML, Page Break (multi-step) -- User Registration: Login, Register, Lost Password, Reset Password - -**Location:** `inc/blocks/*/block.php` and `src/blocks/*/` - -### 2. Form Submission Pipeline - -``` -User Submits Form - ↓ -1. Nonce Verification (inc/form-submit.php:91-95) - ↓ -2. Field Validation (inc/field-validation.php) - - Type validation (email, URL, number) - - Required fields - - Min/max constraints - - Custom regex - ↓ -3. Sanitization (inc/helper.php:258-274) - - Per-field type sanitization - - XSS prevention (wp_kses_post) - - SQL injection prevention - ↓ -4. CAPTCHA Validation (inc/form-submit.php:317-386) - - reCAPTCHA v2/v3 - - Cloudflare Turnstile - - hCaptcha - ↓ -5. Business Logic (Pro: Conditional Logic) - ↓ -6. Payment Processing (if enabled) - - Stripe: Create PaymentIntent - - PayPal: Create Order - ↓ -7. Entry Storage (inc/database/tables/entries.php) - ↓ -8. Integrations (Pro: Send to external services) - ↓ -9. Email Notifications (inc/email/email-template.php) - ↓ -10. Confirmation/Redirect -``` - -### 3. Payment Processing - -**Stripe (Free):** -- Location: `inc/payments/stripe/` -- Flow: - 1. Frontend creates PaymentIntent (AJAX) - 2. User completes payment on Stripe - 3. Webhook updates payment status - 4. Entry marked as paid - -**PayPal (Pro):** -- Location: `inc/business/payments/pay-pal/` -- Flow: - 1. Frontend creates Order via API - 2. User redirected to PayPal - 3. Webhook confirms payment - 4. Entry status updated - -**Database:** `wp_sureforms_payments` table - -### 4. AI Form Builder - -**Location:** `inc/ai-form-builder/` - -**Flow:** -``` -User Prompt ("Create a contact form") - ↓ -AI Middleware (SRFM_AI_MIDDLEWARE) - ↓ -Field Mapping (field-mapping.php) - ↓ -Gutenberg Block Generation - ↓ -Form Preview -``` - -**API:** `https://credits.startertemplates.com/sureforms/` - -### 5. Native Integrations (Pro) - -**Location:** `inc/pro/native-integrations/` - -**Supported Services (24+):** -- Email: Mailchimp, Brevo, Constant Contact -- CRM: HubSpot, Salesforce, Zoho -- Messaging: Telegram, Slack, Discord -- Marketing: FluentCRM, MailerPress -- Booking: LatePoint -- Automation: Zapier, OttoKit - -**Architecture:** -``` -Generic Provider Base Class - ↓ -Integration-Specific Classes -(inc/pro/native-integrations/integrations/*/actions/) - ↓ -OAuth Handler (oauth-handler.php) - ↓ -Encrypted Storage (encryption.php - AES-256-CTR) - ↓ -Workflow Processor (services/workflow-processor.php) -``` - -### 6. Database Schema - -**Custom Tables:** - -```sql --- Entries -wp_sureforms_entries -- id (INT, PK) -- form_id (INT) -- entry_data (LONGTEXT, JSON) -- created_at (DATETIME) -- updated_at (DATETIME) -- status (VARCHAR - 'published', 'trash') -- user_agent (TEXT) -- ip_address (VARCHAR) - --- Payments -wp_sureforms_payments -- id (INT, PK) -- entry_id (INT, FK) -- transaction_id (VARCHAR) -- gateway (ENUM 'stripe', 'paypal') -- status (ENUM 'pending', 'completed', 'failed', 'refunded') -- total_amount (DECIMAL) -- refunded_amount (DECIMAL) -- currency (VARCHAR) - --- Integrations (Pro) -wp_sureforms_integrations -- id (INT, PK) -- type (VARCHAR - 'mailchimp', 'hubspot', etc.) -- data (LONGTEXT, encrypted JSON) -- status (ENUM 'active', 'inactive') - --- Save & Resume (Pro) -wp_sureforms_save_resume -- id (INT, PK) -- form_id (INT) -- token (VARCHAR, unique) -- form_data (LONGTEXT, JSON) -- expires_at (DATETIME) -``` - ---- - -## Security Architecture - -**Input Validation:** -- Nonce verification on all AJAX/REST requests -- Sanitization via `sanitize_*` functions -- Type casting (absint, floatval) - -**Output Escaping:** -- `esc_html()`, `esc_attr()`, `esc_url()` throughout -- `wp_kses_post()` for rich text - -**SQL Security:** -- `$wpdb->prepare()` for all queries -- No direct SQL concatenation - -**Payment Security:** -- Webhook signature verification (Stripe, PayPal) -- Server-side amount validation -- PCI-DSS compliant (payments handled by Stripe/PayPal) - -**Encryption (Pro):** -- AES-256-CTR for OAuth tokens -- Key derivation: `SRFM_ENCRYPTION_KEY` constant or `LOGGED_IN_KEY` -- Storage: `wp_sureforms_integrations.data` (encrypted JSON) - ---- - -## Performance Optimizations - -1. **Lazy Loading:** React components loaded on-demand -2. **Asset Minification:** Grunt uglifies JS/CSS -3. **Database Indexing:** Indexes on `form_id`, `entry_id`, `status` -4. **Caching:** Transients for integration API calls -5. **Query Optimization:** `SELECT` only needed columns - ---- - -## Extensibility - -**Hooks (Filters):** -- `sureforms_submit_form_data` - Modify data before save -- `sureforms_email_template` - Customize email HTML -- `sureforms_payment_amount` - Modify payment amount - -**Hooks (Actions):** -- `sureforms_after_entry_save` - Trigger after entry created -- `sureforms_payment_completed` - After successful payment -- `sureforms_integration_success` - After integration sends data - -**Developer APIs:** -- REST: `/sureforms/v1/*` -- PHP: `SRFM\Inc\Helper` class -- JavaScript: `window.sureforms.*` globals - ---- - -## Technology Stack - -| Layer | Technologies | -|-------|-------------| -| Frontend (Admin) | React 18, @wordpress/components, TanStack Query | -| Frontend (Public) | Vanilla JS, DOMPurify, intl-tel-input | -| Backend | PHP 7.4+, WordPress 6.4+ | -| Build | webpack 5, Babel, Sass, Grunt | -| Testing | PHPUnit, Jest, Playwright | -| Database | MySQL 5.7+, MariaDB 10.3+ | - ---- - -## Deployment Architecture - -``` -Developer Machine - ↓ -Git Commit → GitHub Actions CI - ↓ -Automated Tests (PHPUnit, Playwright) - ↓ -Build Assets (npm run build) - ↓ -Free: WordPress.org SVN -Pro: Licensing Server (ZIP) - ↓ -End User WordPress Sites (300,000+) -``` - ---- - -**Next:** [Codebase Map](codebase-map.md) for detailed folder structure diff --git a/internal-docs/codebase-map.md b/internal-docs/codebase-map.md deleted file mode 100644 index 9d85000c2..000000000 --- a/internal-docs/codebase-map.md +++ /dev/null @@ -1,303 +0,0 @@ -# Codebase Map - -**Version:** 2.5.0 - -Complete folder-by-folder guide to both plugins. - ---- - -## SureForms Free (`sureforms/`) - -### Root Files - -| File | Purpose | -|------|---------| -| `sureforms.php` | Main plugin file, defines constants, loads `plugin-loader.php` | -| `plugin-loader.php` | Bootstraps plugin, registers hooks, loads dependencies | -| `composer.json` | PHP dependencies (nps-survey, bsf-analytics, astra-notices) | -| `package.json` | JS dependencies, build scripts | -| `Gruntfile.js` | Grunt tasks (minify, compress, release) | - -### `admin/` - WordPress Admin UI - -| File | Purpose | -|------|---------| -| `admin.php` | Admin page registration, AJAX handlers for admin actions | -| `analytics.php` | Usage analytics, event tracking | -| `notice-manager.php` | Admin notices, dismissible alerts | - -### `inc/` - Core PHP Logic - -#### `inc/blocks/` - Gutenberg Block Definitions (PHP) - -Each block has a `block.php` with: -- Block registration (`register_block_type`) -- Server-side rendering callback -- Attribute schema -- Enqueue scripts/styles - -**Blocks (16):** -- `address/`, `checkbox/`, `dropdown/`, `email/`, `gdpr/`, `inlinebutton/` -- `input/`, `multichoice/`, `number/`, `payment/`, `phone/`, `sform/`, `textarea/`, `url/` -- `base.php` - Base block class - -#### `inc/fields/` - Field Markup Generation - -Mirrors `blocks/` - generates HTML markup for each field type. - -**Pattern:** -```php -*-markup.php files: -- render_field() method -- Outputs escaped HTML -- Handles field attributes, validation states -``` - -#### `inc/payments/` - Payment Processing - -**Core Files:** -| File | Purpose | -|------|---------| -| `front-end.php` | Public AJAX handlers (`srfm_create_payment_intent`, `srfm_create_subscription_intent`) | -| `payment-helper.php` | Utility functions, amount validation, currency formatting | - -**`payments/stripe/`:** -| File | Purpose | -|------|---------| -| `stripe-webhook.php` | Webhook handler (charge, refund, subscription events) | -| `stripe-helper.php` | Stripe API wrapper, PaymentIntent creation | -| `admin-stripe-handler.php` | Admin AJAX for subscription management | -| `payments-settings.php` | Stripe connection settings, API keys | - -**`payments/admin/`:** -| File | Purpose | -|------|---------| -| `admin-handler.php` | Admin AJAX for refunds, payment management | - -#### `inc/ai-form-builder/` - AI Form Generation - -| File | Purpose | -|------|---------| -| `ai-form-builder.php` | Main AI form builder class, API integration | -| `ai-auth.php` | Middleware authentication | -| `ai-helper.php` | Helper functions, prompt processing | -| `field-mapping.php` | Maps AI response to Gutenberg blocks | - -**API:** `SRFM_AI_MIDDLEWARE` - `https://credits.startertemplates.com/sureforms/` - -#### `inc/database/` - Custom Database Tables - -| File | Purpose | -|------|---------| -| `base.php` | Abstract base class for all table classes (CRUD operations) | -| `register.php` | Table registration, schema creation | -| `tables/entries.php` | `wp_sureforms_entries` table (1,300+ lines) | -| `tables/payments.php` | `wp_sureforms_payments` table (1,200+ lines) | - -**Key Methods:** -- `get_all()`, `get_by_id()`, `insert()`, `update()`, `delete()` -- `get_all_main_payments()` - Payment queries with filtering - -#### Other `inc/` Files - -| File | Purpose | Lines | -|------|---------|-------| -| `form-submit.php` | Form submission handler (AJAX + REST) | 1,280 | -| `helper.php` | Utility functions (sanitization, escaping, validation) | 1,500+ | -| `field-validation.php` | Server-side field validation | 800+ | -| `rest-api.php` | REST API registration (`/sureforms/v1/*`) | 800 | -| `entries.php` | Entry management (list, view, export) | 1,000+ | -| `email/email-template.php` | Email notification templates | 400 | -| `frontend-assets.php` | Enqueue public scripts/styles | 300 | - -### `src/` - React Admin UI - -**Structure:** -``` -src/ -├── admin/ # Main admin app -│ ├── components/ # Reusable React components -│ ├── pages/ # Page-level components -│ └── index.js # Entry point -├── blocks/ # Block editor components -│ ├── address/ # Block-specific React -│ ├── email/ -│ └── ... -└── common/ # Shared utilities - ├── api.js # API client (wp.apiFetch) - └── utils.js # Helper functions -``` - -**Build:** webpack via `@wordpress/scripts` - ---- - -## SureForms Pro (`sureforms-pro/`) - -### Root Files - -| File | Purpose | -|------|---------| -| `sureforms-pro.php` | Main plugin file, requires Free plugin | -| `plugin-loader.php` | Bootstraps Pro features | - -### `inc/business/` - Pro Business Features - -#### `inc/business/payments/pay-pal/` - PayPal Integration - -| File | Purpose | Lines | -|------|---------|-------| -| `webhook-listener.php` | PayPal webhook handler (orders, refunds, subscriptions) | 1,173 | -| `frontend.php` | Public AJAX for PayPal orders, subscriptions | 1,100 | -| `api-payments.php` | PayPal API wrapper (create order, capture, refund) | 178 | -| `helper.php` | PayPal utilities, amount formatting | 520 | -| `settings.php` | PayPal connection settings | AJAX | - -#### `inc/business/user-registration/` - Login & Registration - -| File | Purpose | Lines | -|------|---------|-------| -| `init.php` | REST API registration, login/password endpoints | 600+ | -| `processor.php` | Registration processing, `wp_insert_user()` | 1,000+ | -| `login/block.php` | Login block definition | | -| `register/block.php` | Registration block | | -| `lost-password/block.php` | Lost password block | | -| `reset-password/block.php` | Reset password block | | - -**⚠️ Security Note:** Registration processor creates WordPress users from form submissions. - -#### `inc/business/pdf/` - PDF Generation - -| File | Purpose | -|------|---------| -| `pdf.php` | PDF generation API, AJAX handlers | -| `document.php` | PDF document builder (uses TCPDF or similar) | -| `utils.php` | PDF utilities | - -#### `inc/business/custom-app/` - Custom Application Builder - -| File | Purpose | -|------|---------| -| `load.php` | Custom post type forms, standalone applications | -| `utils.php` | App utilities | - -#### `inc/business/custom-post-type/` - Custom Post Type Integration - -Allows forms to create/update custom post types. - -### `inc/pro/native-integrations/` - 24+ Service Integrations - -**Core:** -| File | Purpose | Lines | -|------|---------|-------| -| `native-integrations.php` | Main integration manager | | -| `encryption.php` | AES-256-CTR encryption for OAuth tokens | 200 | -| `oauth-handler.php` | OAuth authorization flow | 400+ | -| `generic-provider.php` | Base provider class | | -| `integration-provider.php` | Provider interface | | - -**`inc/pro/native-integrations/integrations/`:** - -Each integration has its own folder: -``` -mailchimp/ -├── config.json # API endpoints, auth method -└── actions/ - ├── add-contact.php # Action: Add subscriber - └── remove-contact.php - -hubspot/ -├── config.json -└── actions/ - └── create-contact.php - -...24+ integrations -``` - -**Supported:** -- Email: Mailchimp, Brevo, Constant Contact -- CRM: HubSpot, Salesforce, Zoho -- Messaging: Telegram, Slack, Discord -- WP: FluentCRM, MailerPress, MailPoet -- Booking: LatePoint -- Automation: Zapier, OttoKit - -**Encryption:** OAuth tokens encrypted via `encryption.php` before storage in `wp_sureforms_integrations`. - -### `inc/pro/database/tables/` - Pro Database Tables - -| File | Purpose | -|------|---------| -| `integrations.php` | `wp_sureforms_integrations` table | -| `save-resume.php` | `wp_sureforms_save_resume` table (draft forms) | - -### `inc/extensions/` - Pro Extensions - -| File | Purpose | -|------|---------| -| `conditional-logic.php` | Show/hide fields based on conditions | -| `conditional-emails.php` | Conditional email notifications | -| `conditional-confirmations.php` | Conditional redirects | -| `field-validation.php` | Extended validation (file uploads, MIME types) | -| `entries-management.php` | Enhanced entry features (edit, delete files) | -| `page-break.php` | Multi-step form logic | - -### `inc/blocks/` - Pro Blocks (8) - -- `date-picker/`, `time-picker/`, `rating/`, `slider/` -- `upload/`, `hidden/`, `html/`, `page-break/` - ---- - -## Key Patterns & Conventions - -### Naming Conventions - -**Functions:** -- Public: `srfm_function_name()` -- Internal: `_srfm_internal_function()` - -**Classes:** -- Namespaced: `SRFM\Inc\ClassName` -- Pro: `SRFM_PRO\Inc\ClassName` - -**Hooks:** -- Actions: `sureforms_action_name` -- Filters: `sureforms_filter_name` - -**Database:** -- Tables: `wp_sureforms_table_name` -- Options: `sureforms_option_name` - -### File Organization - -``` -feature/ -├── block.php # Block registration -├── feature-markup.php # HTML generation -├── api-handler.php # AJAX/REST handlers -└── helper.php # Utilities -``` - -### REST API Convention - -**Free:** `/sureforms/v1/endpoint` -**Pro:** `/sureforms-pro/v1/endpoint` - ---- - -## Where to Find Things - -**Need to:** -- **Add a new field type?** → `inc/blocks/` + `inc/fields/` + `src/blocks/` -- **Modify form submission?** → `inc/form-submit.php` -- **Change email template?** → `inc/email/email-template.php` -- **Add payment gateway?** → `inc/payments/` (copy Stripe/PayPal pattern) -- **Add integration?** → `inc/pro/native-integrations/integrations/new-service/` -- **Debug entries?** → `inc/database/tables/entries.php` -- **Fix validation?** → `inc/field-validation.php` -- **Customize admin UI?** → `src/admin/` - ---- - -**Next:** [APIs](apis.md) - REST endpoints, AJAX handlers, hooks diff --git a/internal-docs/coding-standards.md b/internal-docs/coding-standards.md deleted file mode 100644 index 0b746674c..000000000 --- a/internal-docs/coding-standards.md +++ /dev/null @@ -1,312 +0,0 @@ -# Coding Standards - -**Version:** 2.5.0 - ---- - -## PHP Standards - -**WordPress Coding Standards:** https://developer.wordpress.org/coding-standards/wordpress-coding-standards/php/ - -### Code Style - -- **PSR-12 inspired** but follows WordPress conventions -- **Tabs for indentation** (not spaces) -- **Yoda conditions:** `if ( 'value' === $variable )` -- **Braces:** Required for all control structures - -```php -// ✅ Good -if ( $condition ) { - do_something(); -} - -// ❌ Bad -if ($condition) do_something(); -``` - -### Naming Conventions - -**Functions:** -```php -srfm_public_function() // Public functions -_srfm_private_function() // Internal (leading underscore) -``` - -**Classes:** -```php -namespace SRFM\Inc; -class Form_Submit { } // Underscores in class names - -namespace SRFM_PRO\Inc\Business; -class PayPal_Helper { } -``` - -**Variables:** -```php -$snake_case_variable = 'value'; // Lowercase with underscores -``` - -**Constants:** -```php -define( 'SRFM_CONSTANT', 'value' ); -``` - -### Security - -**Always:** -- Sanitize input: `sanitize_text_field()`, `absint()`, `sanitize_email()` -- Validate: Check types, ranges, allowed values -- Escape output: `esc_html()`, `esc_attr()`, `esc_url()` -- Use nonces: `wp_verify_nonce()` for AJAX/forms -- Use `$wpdb->prepare()` for SQL queries -- Check capabilities: `current_user_can()` - -**Example:** -```php -// Input -$email = sanitize_email( wp_unslash( $_POST['email'] ?? '' ) ); - -// Database -$results = $wpdb->get_results( - $wpdb->prepare( - "SELECT * FROM {$wpdb->prefix}sureforms_entries WHERE form_id = %d", - $form_id - ) -); - -// Output -echo '
' . esc_html( $user_name ) . '
'; -``` - -### Documentation - -**PHPDoc blocks:** -```php -/** - * Short description. - * - * Longer description if needed. - * - * @since 2.5.0 - * - * @param int $form_id Form ID. - * @param array $data Entry data. - * @return int|false Entry ID on success, false on failure. - */ -function srfm_create_entry( $form_id, $data ) { - // Implementation -} -``` - ---- - -## JavaScript Standards - -**WordPress JavaScript Coding Standards:** https://developer.wordpress.org/coding-standards/wordpress-coding-standards/javascript/ - -### Code Style (ESLint) - -**Config:** `@wordpress/eslint-plugin` - -```javascript -// ✅ Good - ES6+, const/let, arrow functions -const handleSubmit = (event) => { - event.preventDefault(); - const formData = new FormData(event.target); - // ... -}; - -// ❌ Bad - var, function expressions -var handleSubmit = function(event) { - event.preventDefault(); -}; -``` - -### React Conventions - -**Functional components with hooks:** -```jsx -import { useState, useEffect } from '@wordpress/element'; - -function FormBuilder({ formId }) { - const [fields, setFields] = useState([]); - - useEffect(() => { - fetchFields(formId).then(setFields); - }, [formId]); - - return ( -
- {fields.map(field => )} -
- ); -} -``` - -**Naming:** -- Components: `PascalCase` -- Hooks: `useCamelCase` -- Functions: `camelCase` -- Constants: `UPPER_SNAKE_CASE` - ---- - -## CSS/SCSS Standards - -**BEM-inspired naming:** -```scss -.srfm-form { - &__field { - // Field styles - } - - &__field--error { - // Error state - } -} -``` - -**Prefix:** All classes start with `srfm-` to avoid conflicts. - ---- - -## Database Standards - -### Table Names - -```php -$wpdb->prefix . 'sureforms_entries' -$wpdb->prefix . 'sureforms_payments' -``` - -**Always use `$wpdb->prefix`**, never hardcode `wp_`. - -### Queries - -**Always use prepared statements:** -```php -// ✅ Good -$wpdb->get_results( - $wpdb->prepare( - "SELECT * FROM {$wpdb->prefix}sureforms_entries WHERE id = %d", - $entry_id - ) -); - -// ❌ Bad -$wpdb->query( "DELETE FROM wp_sureforms_entries WHERE id = $entry_id" ); -``` - ---- - -## Git Commit Messages - -**Format:** -``` -type(scope): brief description - -Longer explanation if needed. - -Co-Authored-By: Name -``` - -**Types:** -- `feat`: New feature -- `fix`: Bug fix -- `docs`: Documentation -- `style`: Formatting, no code change -- `refactor`: Code restructuring -- `test`: Adding tests -- `chore`: Build/tooling - -**Example:** -``` -feat(payments): add PayPal subscription support - -- Implement PayPal billing agreement API -- Add webhook handler for subscription events -- Update admin UI for PayPal subscriptions - -Co-Authored-By: Claude Sonnet 4.5 -``` - ---- - -## File Organization - -**One class per file:** -``` -inc/payments/stripe/stripe-helper.php → class Stripe_Helper -``` - -**Group related functionality:** -``` -inc/payments/ -├── payment-helper.php # Shared utilities -├── front-end.php # Public AJAX handlers -├── stripe/ -│ ├── stripe-helper.php -│ ├── stripe-webhook.php -│ └── admin-stripe-handler.php -└── admin/ - └── admin-handler.php -``` - ---- - -## Testing Standards - -**PHPUnit:** -```php -class Test_Form_Submit extends WP_UnitTestCase { - public function test_form_submission_saves_entry() { - $entry_id = srfm_submit_form( $data ); - $this->assertIsInt( $entry_id ); - } -} -``` - -**Playwright:** -```javascript -test('form submission works', async ({ page }) => { - await page.goto('/test-form/'); - await page.fill('[name="email"]', 'test@example.com'); - await page.click('button[type="submit"]'); - await expect(page.locator('.success-message')).toBeVisible(); -}); -``` - ---- - -## Code Review Checklist - -Before submitting PR: - -- [ ] Code follows WordPress/project standards -- [ ] All inputs sanitized -- [ ] All outputs escaped -- [ ] SQL queries use `prepare()` -- [ ] Nonces verified for AJAX/forms -- [ ] Capabilities checked for admin actions -- [ ] PHPDoc blocks added -- [ ] No PHP/JS errors in console -- [ ] Tested in latest WordPress version -- [ ] Tests pass: `composer test && npm run test:unit` -- [ ] Linting passes: `composer lint && npm run lint-js` - ---- - -**Automated Checks:** - -```bash -# PHP linting -composer lint # PHP_CodeSniffer - -# JS linting -npm run lint-js # ESLint - -# Auto-fix -composer format # phpcbf -npm run lint-js:fix # ESLint --fix -``` diff --git a/internal-docs/faq.md b/internal-docs/faq.md deleted file mode 100644 index 8e174c45f..000000000 --- a/internal-docs/faq.md +++ /dev/null @@ -1,1003 +0,0 @@ -# Frequently Asked Questions - -**Version:** 2.5.0 - ---- - -## General Questions - -### What is SureForms? - -SureForms is an AI-powered WordPress form builder that uses Gutenberg blocks. - -**Key features:** -- AI form generation (describe in plain language, get complete form) -- Built-in payments (Stripe in Free, PayPal in Pro) -- Mobile-first design -- Native WordPress (no proprietary builder) -- Custom database tables (not post meta) - -**Target users:** Website owners, designers, developers who need forms without complexity. - ---- - -### What's the difference between Free and Pro? - -**Free (sureforms):** -- Unlimited forms & submissions -- All 15+ field types -- Stripe payments (one-time & subscriptions) -- Email notifications -- Spam protection (reCAPTCHA, Honeypot) -- Form analytics -- CSV export - -**Pro (sureforms-pro):** -- **All Free features, plus:** -- PayPal payments -- 24+ native integrations (Mailchimp, HubSpot, Salesforce, etc.) -- Conditional logic -- Multi-step & conversational forms -- User registration & login -- PDF generation -- File upload fields -- Priority support (< 24hr response) - -**Pricing:** -- Free: $0 (WordPress.org) -- Pro: $99-$299/year (3 sites to unlimited) - ---- - -### Can I use SureForms on multiple sites? - -**Free:** Yes, unlimited sites. - -**Pro:** Depends on license: -- Essential ($99/year): 3 sites -- Plus ($199/year): 20 sites -- Agency ($299/year): Unlimited sites - -**License activation:** -- Enter license key in SureForms → Settings → License -- Deactivate from one site to move to another -- All sites must be owned by you (not for client sites unless Agency plan) - ---- - -### Is SureForms GDPR compliant? - -**Yes.** SureForms provides tools for GDPR compliance: - -**Features:** -- GDPR checkbox field (explicit consent) -- Data export (users can request their data) -- Data deletion (users can request deletion) -- No third-party data sharing (unless you enable integrations) -- Privacy policy link support - -**What you must do:** -1. Add GDPR checkbox to forms collecting personal data -2. Link to your privacy policy -3. Honor data export/deletion requests -4. Configure data retention policies - -**Data storage:** -- Submissions stored in your WordPress database -- No data sent to SureForms servers (AI calls go through middleware but don't store data) -- Payment data stored encrypted (PCI-compliant) - ---- - -### Does SureForms work with my theme? - -**Yes.** SureForms is designed to work with any properly-coded WordPress theme. - -**Tested with:** -- Astra -- GeneratePress -- Kadence -- Neve -- Blocksy -- Twenty Twenty-Three/Four -- Page builder themes (Elementor, Divi, Beaver Builder) - -**If you experience styling conflicts:** -1. Check [troubleshooting guide](troubleshooting.md#form-breaks-after-theme-update) -2. Use SureForms → Settings → Custom CSS to override -3. Contact support with theme name - ---- - -### Can I use SureForms with page builders? - -**Yes.** SureForms works with: -- **Gutenberg** (native, best experience) -- **Elementor** (via shortcode or WordPress widget) -- **Divi** (via shortcode or code module) -- **Beaver Builder** (via WordPress widget) -- **Bricks** (via shortcode or WordPress element) - -**How to add:** - -**Elementor:** -1. Add "Shortcode" widget -2. Paste: `[sureforms id="123"]` -3. Replace 123 with your form ID - -**Divi:** -1. Add "Code" module -2. Paste shortcode -3. Save - -**Beaver Builder:** -1. Add "WordPress Widget" module -2. Select "SureForms" widget -3. Choose form - ---- - -## Technical Questions - -### What are the system requirements? - -**Minimum:** -- WordPress 6.4+ -- PHP 7.4+ -- MySQL 5.6+ or MariaDB 10.1+ -- HTTPS (for payments) - -**Recommended:** -- WordPress 6.6+ -- PHP 8.1+ -- MySQL 8.0+ or MariaDB 10.6+ -- 256MB PHP memory limit -- Object caching (Redis or Memcached) - -**Browser support:** -- Chrome 90+ -- Firefox 88+ -- Safari 14+ -- Edge 90+ - ---- - -### Does SureForms slow down my site? - -**No.** SureForms is optimized for performance: - -**Impact on page load:** -- Additional CSS: ~15KB (minified) -- Additional JS: ~25KB (minified, deferred) -- Total: ~40KB additional assets - -**Database queries:** -- Form render: 2-3 queries (cached) -- Form submission: 4-5 queries (optimized with indexes) -- No N+1 query issues - -**Performance features:** -- Lazy loading for non-critical assets -- Custom database tables (not post meta) -- Query optimization (indexed columns) -- Minified & concatenated assets -- CDN-friendly (versioned static files) - -**Benchmarks:** -- Lighthouse score: 95+ (with proper hosting) -- Time to Interactive: < 2 seconds on 3G -- Form submission latency: < 500ms - ---- - -### Can I export my data? - -**Yes.** Multiple export options: - -**Entries export:** -1. Go to SureForms → Entries -2. Select entries (or "Select All") -3. Click "Export to CSV" -4. Download file - -**Format:** CSV with all fields as columns - -**Form export:** -- Export form as JSON (Settings → Export) -- Import on another site (Settings → Import) - -**Database export:** -```bash -# Export all SureForms data -wp db export sureforms-backup.sql --tables=wp_sureforms_entries,wp_sureforms_payments,wp_sureforms_integrations -``` - ---- - -### How do I migrate forms to another site? - -**Method 1: Export/Import (Recommended)** - -**On old site:** -1. Go to SureForms → Forms -2. Hover over form → "Export" -3. Download JSON file - -**On new site:** -1. Install SureForms (same version) -2. Go to SureForms → Import -3. Upload JSON file -4. Map any dependencies (integrations, etc.) - -**Method 2: Database migration** - -```bash -# On old site -wp db export sureforms-data.sql --tables=wp_sureforms_entries,wp_sureforms_payments - -# Transfer file to new site - -# On new site -wp db import sureforms-data.sql - -# Update URLs in entries (if domain changed) -wp search-replace 'https://oldsite.com' 'https://newsite.com' wp_sureforms_entries -``` - ---- - -### Can I use SureForms offline / localhost? - -**Yes, with limitations:** - -**Works offline:** -- Form creation -- Form editing -- Local submissions (saved to database) - -**Requires internet:** -- AI form generation (external API) -- Payment processing (Stripe/PayPal API) -- Native integrations (Mailchimp, HubSpot, etc.) -- Google Fonts (if used) -- reCAPTCHA (if enabled) - -**Development setup:** -```bash -# Use Local by Flywheel or similar -# Or manual setup: -cd ~/Sites/my-wordpress-site -wp core download -wp core config --dbname=sureforms_dev --dbuser=root -wp core install --url=http://localhost:8080 --title="Dev Site" -wp plugin install sureforms --activate -``` - ---- - -## Payment Questions - -### Which payment gateways are supported? - -**Free plugin:** -- Stripe (one-time payments & subscriptions) - -**Pro plugin:** -- Stripe (one-time payments & subscriptions) -- PayPal (one-time payments & subscriptions) - -**Coming soon:** -- Razorpay (India) -- Mollie (Europe) - -**Not planned:** -- WooCommerce (use WooCommerce for full e-commerce) -- Square (low demand) -- Bitcoin/crypto (regulatory complexity) - ---- - -### How do I test payments before going live? - -**Stripe test mode:** - -1. Get test API keys: - - Go to https://dashboard.stripe.com/test/apikeys - - Copy "Publishable key" (pk_test_...) - - Copy "Secret key" (sk_test_...) - -2. In SureForms: - - Go to Settings → Payments → Stripe - - Enable "Test Mode" - - Paste test keys - - Save - -3. Test with card: - - Card number: `4242 4242 4242 4242` - - Expiry: Any future date (e.g., 12/28) - - CVC: Any 3 digits (e.g., 123) - -4. Verify in Stripe dashboard: - - Go to Payments → Test Mode - - See your test payment - -**PayPal sandbox (Pro):** - -1. Create sandbox account: - - Go to https://developer.paypal.com/ - - Sign in with PayPal account - - Create sandbox business & buyer accounts - -2. Get sandbox credentials: - - Apps & Credentials → Sandbox - - Copy Client ID & Secret - -3. In SureForms: - - Settings → Payments → PayPal - - Enable "Sandbox Mode" - - Paste credentials - - Save - -4. Test with sandbox buyer account - ---- - -### How are payment fees handled? - -**SureForms fees:** $0 (we charge nothing) - -**Gateway fees:** - -**Stripe:** -- Standard: 2.9% + $0.30 per transaction -- International cards: +1.5% -- Currency conversion: +1% -- (Varies by country, see Stripe pricing) - -**PayPal:** -- Standard: 2.9% + $0.30 per transaction -- International: +1.5% -- (Varies by country, see PayPal pricing) - -**Who pays fees:** -- Fees deducted from amount received -- Example: $100 charge → You receive ~$97 - -**Passing fees to customer:** -- Not built-in (would require payment gateway approval) -- Workaround: Add fee as separate amount field - ---- - -### Can I accept subscriptions? - -**Yes** (both Stripe and PayPal). - -**Setup:** - -1. Create form with Payment block -2. Payment block settings: - - Payment Type: ● Subscription - - Interval: Monthly/Yearly/Weekly - - Amount: [price] - -3. Customer pays once, charged automatically recurring - -**Management:** - -**Stripe:** -- View subscriptions: Stripe Dashboard → Subscriptions -- Cancel: Click subscription → "Cancel subscription" -- Refund: Not automatic, manual refund in Stripe - -**PayPal (Pro):** -- View subscriptions: PayPal Dashboard → Subscriptions -- Cancel: Click subscription → "Cancel" - -**Customer cancellation:** -- Customers can cancel in Stripe/PayPal customer portal -- You can provide link in confirmation email - ---- - -## AI & Form Generation Questions - -### How does AI form generation work? - -**Technical flow:** - -``` -User enters prompt ("job application form") - ↓ -SureForms sends to AI middleware - ↓ -Middleware calls GPT-4 API - ↓ -GPT-4 returns structured JSON (field types, labels, validations) - ↓ -Middleware sends back to SureForms - ↓ -SureForms creates Gutenberg blocks from JSON - ↓ -Form appears in editor, ready to customize -``` - -**What data is sent:** -- Your prompt ("create a contact form") -- Form context (if modifying existing form) -- No user data, no submissions, no PII - -**What data is stored:** -- None. AI responses are not logged. -- Form configuration stored in WordPress database only - -**Privacy:** -- AI calls routed through SureForms middleware (not direct to OpenAI) -- No data retention -- No training on your data - ---- - -### Can I use AI without internet? - -**No.** AI requires external API call to GPT-4. - -**Offline alternatives:** -- Create forms manually (no AI) -- Use templates (no AI needed) -- Import pre-made forms - ---- - -### What languages does AI support? - -**Prompts:** Any language GPT-4 supports (100+ languages) - -**Field labels:** Generated in same language as prompt - -**Example:** -- Prompt (Spanish): "formulario de contacto" -- Result: Fields with Spanish labels ("Nombre", "Correo electrónico", etc.) - -**Limitations:** -- Some languages better than others (English, Spanish, French, German excellent) -- Less common languages may have lower quality - ---- - -## Integration Questions (Pro) - -### What integrations are available? - -**24+ native integrations:** - -**Email Marketing:** -- Mailchimp -- Brevo (Sendinblue) -- ActiveCampaign -- ConvertKit -- MailerLite - -**CRM:** -- HubSpot -- Salesforce -- Zoho CRM -- Pipedrive - -**Communication:** -- Slack -- Telegram -- Discord (coming soon) - -**Productivity:** -- Google Sheets -- Airtable (coming soon) -- Notion (coming soon) - -**WordPress Plugins:** -- FluentCRM (native) -- OttoKit (SureTriggers) - -**Webhooks:** -- Custom webhooks (POST to any URL) - -**Not included:** -- Zapier (use webhooks instead) -- Make/Integromat (use webhooks) - ---- - -### How do I connect Mailchimp? - -**Setup (OAuth):** - -1. Go to SureForms → Settings → Integrations -2. Click "Mailchimp" → "Connect" -3. Redirected to Mailchimp → "Allow access" -4. Redirected back, connection confirmed - -**Use in form:** - -1. Edit form -2. Settings → Actions → "Add Action" -3. Select "Mailchimp" -4. Choose audience (list) -5. Map fields: - - Email field → Mailchimp EMAIL - - Name field → Mailchimp FNAME -6. Save - -**On form submission:** -- Contact added to Mailchimp list automatically -- Tags applied (if configured) -- Double opt-in email sent (if enabled in Mailchimp) - ---- - -### Can I send form data to custom webhook? - -**Yes** (Pro feature). - -**Setup:** - -1. Form settings → Actions → "Add Action" -2. Select "Webhook" -3. Configure: - - URL: `https://yourapi.com/endpoint` - - Method: POST (or GET, PUT) - - Headers: (optional, e.g., `Authorization: Bearer token`) -4. Save - -**Payload format:** - -```json -{ - "form_id": 123, - "entry_id": 456, - "fields": { - "email": "user@example.com", - "name": "John Doe", - "message": "Hello!" - }, - "meta": { - "submitted_at": "2026-02-12 10:30:00", - "user_ip": "192.168.1.1", - "user_agent": "Mozilla/5.0..." - } -} -``` - -**Retry logic:** -- Failed webhooks retried 3 times -- Exponential backoff (1s, 5s, 25s) -- After 3 failures, logged as error - ---- - -## Security & Privacy Questions - -### Is SureForms secure? - -**Yes.** Security is a core priority. - -**Security measures:** - -**Input sanitization:** -- All user input sanitized before storage -- WordPress functions: `sanitize_text_field()`, `sanitize_email()`, etc. -- Custom sanitization for complex fields - -**Output escaping:** -- All output escaped before rendering -- `esc_html()`, `esc_attr()`, `esc_url()` used throughout -- Prevents XSS attacks - -**SQL injection prevention:** -- All database queries use `$wpdb->prepare()` -- No direct SQL concatenation -- Custom database class with built-in protection - -**CSRF protection:** -- Nonce verification on all AJAX/REST endpoints -- `wp_verify_nonce()` checked before state-changing operations - -**Authorization:** -- Capability checks: `current_user_can()` -- Admin actions require `manage_options` capability -- User-specific data access controlled - -**Payment security:** -- PCI DSS compliant (no card storage) -- Stripe/PayPal handle sensitive data -- API credentials encrypted at rest (AES-256) - -**File uploads (Pro):** -- MIME type validation (server-side) -- File size limits enforced -- Path traversal prevention -- Disallowed file types: `.php`, `.js`, `.exe`, etc. - ---- - -### Where is my data stored? - -**Form submissions:** -- Your WordPress database -- Table: `wp_sureforms_entries` -- No data sent to SureForms servers - -**Payment data:** -- Stripe: Stored in Stripe (not in WordPress) -- PayPal: Stored in PayPal (not in WordPress) -- WordPress stores: Transaction ID, amount, status only - -**Integration credentials (Pro):** -- WordPress database -- Table: `wp_sureforms_integrations` -- Encrypted with AES-256 -- Encryption key in `wp-config.php` (recommended) - -**AI prompts:** -- Sent to AI middleware → OpenAI GPT-4 -- Not stored or logged -- Not used for training - ---- - -### Can users delete their data? - -**Yes** (GDPR requirement). - -**Manual deletion:** - -1. User requests deletion via email -2. Admin finds submissions by email -3. Delete from SureForms → Entries - -**Automatic (Pro):** -- Data retention policy: Auto-delete entries after X days -- Settings → Privacy → Data Retention -- Configure per form or globally - -**What gets deleted:** -- Entry data (all fields) -- Entry metadata (IP, user agent) -- File uploads (if any) - -**What's preserved:** -- Form configuration (for re-use) -- Analytics (anonymized counts only) - ---- - -## Troubleshooting Questions - -### My forms aren't showing on the frontend. Why? - -**Common causes:** - -**1. Form not published:** -- Check form status in SureForms → Forms -- Must be "Published" not "Draft" - -**2. Form not embedded:** -- Add SureForms block to page -- Select your form from dropdown -- Or use shortcode: `[sureforms id="123"]` - -**3. Theme conflict:** -- Try default theme: `wp theme activate twentytwentythree` -- If works → Theme issue, contact theme developer - -**4. JavaScript disabled:** -- Check browser console for errors -- Disable other plugins to find conflict - -**Debug:** -```bash -# Enable debugging -wp config set WP_DEBUG true --raw -wp config set WP_DEBUG_LOG true --raw - -# Check debug log -tail -f wp-content/debug.log -``` - -See [troubleshooting guide](troubleshooting.md) for more. - ---- - -### Form submissions aren't saving. What's wrong? - -**Check:** - -**1. Database tables exist:** -```bash -wp db query "SHOW TABLES LIKE '%sureforms%';" -``` - -Should show `wp_sureforms_entries` table. - -**2. Database permissions:** -```bash -wp db query "SHOW GRANTS;" -``` - -User must have INSERT privilege. - -**3. Nonce verification:** -- If using caching, exclude AJAX endpoints -- WP Super Cache: Exclude `/wp-admin/admin-ajax.php` - -**4. Debug log:** -```bash -tail -f wp-content/debug.log -# Submit form, watch for errors -``` - -See [troubleshooting: submissions not saving](troubleshooting.md#form-submissions-not-saving) - ---- - -### Email notifications aren't sending. Help! - -**Diagnose:** - -```bash -# Test WordPress mail function -wp eval "wp_mail('your@email.com', 'Test', 'Testing');" -``` - -If no email received → Server mail() disabled. - -**Fix:** - -**Install SMTP plugin:** -```bash -wp plugin install wp-mail-smtp --activate -``` - -**Configure with:** -- Gmail -- SendGrid -- Mailgun -- Amazon SES - -**Check spam folder:** -- Default WordPress sender: `wordpress@yourdomain.com` -- Often flagged as spam -- SMTP fixes this - -See [troubleshooting: emails not sending](troubleshooting.md#email-notifications-not-sending) - ---- - -## Customization Questions - -### Can I customize form styling? - -**Yes.** Multiple options: - -**Option 1: Settings panel (no code):** -1. Edit form -2. Settings sidebar → Design -3. Customize: - - Colors (background, text, buttons) - - Typography (fonts, sizes) - - Spacing (padding, margins) - - Border radius - -**Option 2: Custom CSS:** -1. SureForms → Settings → Custom CSS -2. Add your styles: -```css -.srfm-form { - background: #f9f9f9; - padding: 30px; - border-radius: 8px; -} - -.srfm-form input { - border: 2px solid #333; -} -``` - -**Option 3: Theme stylesheet:** - -Add to `style.css`: -```css -.srfm-form { /* Your styles */ } -``` - -**Option 4: Page builder:** - -Use page builder's CSS editor (if using Elementor/Divi). - ---- - -### Can I add custom fields? - -**Yes** (requires development). - -**Process:** - -1. Create block folder: `inc/blocks/my-field/` -2. Register block: `block.php` -3. Create React component: `src/blocks/my-field/edit.js` -4. Add sanitization: `inc/helper.php` -5. Add validation: `inc/field-validation.php` - -**Example:** See [onboarding guide](onboarding.md#step-2-create-block-structure) - -**Pre-built custom fields (Pro):** -- Star rating -- Signature -- File upload -- Date/time picker - ---- - -### Can I change the submit button text? - -**Yes.** - -**Per form:** -1. Edit form -2. Click submit button block -3. Settings sidebar → Button Text -4. Change text -5. Update form - -**Globally:** - -Add to `functions.php`: -```php -add_filter('sureforms_submit_button_text', function($text) { - return __('Send Message', 'sureforms'); -}); -``` - ---- - -## Business & Licensing Questions - -### Can I use SureForms on client sites? - -**Free:** Yes, unlimited sites. - -**Pro:** -- **Agency license required** ($299/year, unlimited sites) -- Essential ($99/year, 3 sites) - only for your own sites -- Plus ($199/year, 20 sites) - only for your own sites - -**License terms:** -- You must own the sites (not client-owned sites with Essential/Plus) -- Agency license allows client sites -- Each site needs separate activation - ---- - -### Can I white-label SureForms? - -**Not officially.** - -**What you can do:** -- Remove branding from admin (CSS) -- Custom email footer (replace "Powered by SureForms") -- Custom confirmation messages - -**What you can't do:** -- Remove copyright notices from code -- Rebrand and resell as your own product -- Remove attribution from free plugin - -**Enterprise white-label:** -- Contact sales for custom licensing -- Available for high-volume agencies - ---- - -### What's your refund policy? - -**14-day money-back guarantee** (Pro licenses) - -**Refund eligibility:** -- Purchased within last 14 days -- Tried to use but encountered issues -- Support unable to resolve - -**Not eligible:** -- After 14 days -- Changed mind (not technical issue) -- Purchased wrong license (can upgrade instead) - -**Process:** -1. Contact support: support@sureforms.com -2. Describe issue (we'll try to help first) -3. If unresolved, refund processed within 3-5 business days - ---- - -### How long do I get updates? - -**Free:** Lifetime updates. - -**Pro:** -- Updates: For duration of license (1 year) -- Renewals: Discounted renewal price after year 1 -- If license expires: Plugin continues working, no new updates - -**Version compatibility:** -- Major updates: Included -- Security updates: Prioritized -- Feature updates: Based on roadmap - ---- - -## Developer Questions - -### Is the code open source? - -**Free plugin:** Yes. -- License: GPL v2 or later -- GitHub: https://github.com/brainstormforce/sureforms - -**Pro plugin:** No. -- Proprietary license -- Source code visible but not redistributable - ---- - -### Can I contribute to SureForms? - -**Yes!** We welcome contributions. - -**How to contribute:** - -1. Fork repo: https://github.com/brainstormforce/sureforms -2. Create branch: `git checkout -b feat/my-feature` -3. Make changes -4. Run tests: `composer test && npm run test:unit` -5. Submit PR - -**Contribution guidelines:** -- Follow [coding standards](coding-standards.md) -- Add tests for new features -- Update docs if needed -- Sign off commits: `Co-Authored-By: Your Name ` - ---- - -### Where can I find the API documentation? - -**API docs:** [apis.md](apis.md) - -**Key resources:** -- REST endpoints: [apis.md#rest-api](apis.md#rest-api) -- Hooks & filters: [apis.md#hooks--filters](apis.md#hooks--filters) -- JavaScript APIs: [apis.md#javascript-apis](apis.md#javascript-apis) -- Database APIs: [apis.md#database-apis](apis.md#database-apis) - -**Code examples:** [ai-agent-guide.md](ai-agent-guide.md) - ---- - -## Need More Help? - -**Documentation:** -- [README.md](README.md) - Quick start -- [Troubleshooting](troubleshooting.md) - Common problems -- [Onboarding](onboarding.md) - Developer guide -- [Glossary](glossary.md) - Technical terms - -**Support:** -- **Free users:** WordPress.org forum, GitHub issues -- **Pro users:** https://support.brainstormforce.com/ (< 24hr response) - -**Community:** -- Facebook: https://www.facebook.com/groups/surecart -- GitHub Discussions: https://github.com/brainstormforce/sureforms/discussions - ---- - -**Next:** [Glossary](glossary.md) diff --git a/internal-docs/glossary.md b/internal-docs/glossary.md deleted file mode 100644 index 440e34b70..000000000 --- a/internal-docs/glossary.md +++ /dev/null @@ -1,723 +0,0 @@ -# Glossary - -**Version:** 2.5.0 - ---- - -## A - -### AJAX (Asynchronous JavaScript and XML) -Technique for updating parts of a page without full reload. Used in SureForms for form submissions, payment processing, and file uploads. - -**Example:** -```javascript -// AJAX request to submit form -wp.ajax.post('srfm_submit_form', { data: formData }); -``` - -### API (Application Programming Interface) -Set of functions and methods for interacting with software. SureForms provides REST API, database API, and JavaScript API. - -**Types in SureForms:** -- **REST API:** HTTP endpoints for external access -- **Database API:** Methods to query entries/payments -- **JavaScript API:** Frontend form manipulation - -### Attribute (Gutenberg) -Data stored with a block. In SureForms, attributes define field configuration (label, required, placeholder, etc.). - -**Example:** -```json -{ - "label": "Email", - "required": true, - "placeholder": "name@example.com" -} -``` - ---- - -## B - -### Block (Gutenberg) -Reusable component in WordPress editor. SureForms forms are composed of blocks (Email block, Textarea block, Submit button block, etc.). - -**Types:** -- **Static blocks:** Rendered client-side (React) -- **Dynamic blocks:** Rendered server-side (PHP) - -### Block Editor -WordPress's editing interface (formerly called "Gutenberg"). Native to WordPress 5.0+. - -**Why SureForms uses it:** -- Users already familiar -- No proprietary builder to learn -- Future-proof (WordPress core) - ---- - -## C - -### Capability -WordPress permission level. SureForms checks capabilities before allowing admin actions. - -**Common capabilities:** -- `manage_options` - Admin settings access -- `edit_posts` - Create forms (default) -- `read` - View forms (logged-in users) - -**Example:** -```php -if (current_user_can('manage_options')) { - // Allow admin action -} -``` - -### Conditional Logic (Pro) -Show or hide form fields based on user answers. Example: Show "Dietary restrictions" only if user selects "Yes" to "Will you attend?" - -**Types:** -- **Show when:** Display field if condition matches -- **Hide when:** Hide field if condition matches -- **AND/OR logic:** Multiple conditions combined - -### Conversational Form (Pro) -Form that displays one question at a time, like a chat conversation. Increases engagement and completion rates. - -**Benefits:** -- Less overwhelming than long forms -- Higher completion rate (3x vs single-page) -- Better mobile experience - -### CSRF (Cross-Site Request Forgery) -Attack where malicious site tricks user into submitting request to your site. SureForms prevents with nonce verification. - -**Example attack (prevented):** -```html - -
- - -
- -``` - -### CSV (Comma-Separated Values) -File format for spreadsheet data. SureForms can export form entries as CSV. - -**Example:** -``` -Name,Email,Message -John Doe,john@example.com,Hello! -Jane Smith,jane@example.com,Question about... -``` - ---- - -## D - -### Database Table -MySQL table storing structured data. SureForms uses 4 custom tables: -- `wp_sureforms_entries` - Form submissions -- `wp_sureforms_payments` - Payment records -- `wp_sureforms_integrations` - OAuth credentials -- `wp_sureforms_save_resume` - Draft submissions (Pro) - -**Why custom tables?** -- Faster queries (indexed columns) -- More efficient than post meta -- Easier to export - -### Dynamic Block -Gutenberg block rendered server-side (PHP). Most SureForms field blocks are dynamic for security (server-side validation). - -**Example:** -```php -register_block_type('sureforms/email', [ - 'render_callback' => 'render_email_field' -]); -``` - ---- - -## E - -### Encryption -Converting data to unreadable format. SureForms encrypts OAuth credentials and API keys. - -**Algorithm:** AES-256-CTR - -**Example:** -```php -$encrypted = Encryption::encrypt($api_key); -// Stored in database: "base64encodedIV.encryptedData" -``` - -### Entry -Single form submission. Stored in `wp_sureforms_entries` table. - -**Contains:** -- Form ID -- User ID (if logged in) -- Field values (JSON) -- Metadata (IP, user agent, timestamp) -- Status (published, spam, trash) - -### Escaping (Output Escaping) -Converting special characters to prevent XSS. SureForms escapes all user data before display. - -**Functions:** -- `esc_html()` - For HTML content -- `esc_attr()` - For HTML attributes -- `esc_url()` - For URLs -- `esc_js()` - For JavaScript strings - -**Example:** -```php -echo '
' . esc_html($user_input) . '
'; -``` - ---- - -## F - -### Field Type -Type of input field (email, text, number, etc.). SureForms has 15+ field types. - -**Common types:** -- Text, Email, URL, Textarea -- Number, Phone -- Multiple Choice, Checkbox, Dropdown -- Address, Upload (Pro) - -### Filter (WordPress Hook) -Function that modifies data. SureForms provides 30+ filters for customization. - -**Example:** -```php -add_filter('sureforms_email_subject', function($subject, $form_id) { - return "[Form $form_id] $subject"; -}, 10, 2); -``` - ---- - -## G - -### GDPR (General Data Protection Regulation) -European privacy law. SureForms provides GDPR-compliance features (consent checkbox, data export/deletion). - -**Requirements:** -- Explicit consent for data collection -- Right to access data (export) -- Right to deletion -- Privacy policy link - -### Gutenberg -WordPress's block editor (officially called "Block Editor"). Named after Johannes Gutenberg, inventor of printing press. - -**Why "Gutenberg"?** -- Revolutionized content creation (like printing press) -- Blocks are reusable components - ---- - -## H - -### Honeypot -Anti-spam technique using hidden field. Bots fill all fields (including hidden), revealing themselves. - -**How it works:** -```html - - -``` - -**SureForms logic:** -```php -if (!empty($_POST['srfm-honeypot'])) { - // Spam detected -} -``` - -### Hook (WordPress) -Point where developers can inject custom code. Two types: actions and filters. - -**SureForms hooks:** -- 50+ action hooks (e.g., `sureforms_after_entry_save`) -- 30+ filter hooks (e.g., `sureforms_email_template`) - ---- - -## I - -### Integration (Native Integration) -Connection to third-party service. SureForms Pro has 24+ native integrations (Mailchimp, HubSpot, etc.). - -**Types:** -- **OAuth:** User authorizes connection (Mailchimp, Google) -- **API Key:** User provides key from service -- **Webhook:** SureForms sends POST request to URL - -### Instant Form -SureForms feature allowing forms to be published with unique URL (no embedding needed). - -**Example URL:** -``` -https://yoursite.com/?srfm_form=abc123 -``` - -**Use cases:** -- Email signatures -- Social media links -- QR codes - ---- - -## J - -### JSON (JavaScript Object Notation) -Data format for structured information. SureForms stores entry data and block attributes as JSON. - -**Example entry data:** -```json -{ - "email": "john@example.com", - "name": "John Doe", - "message": "Hello!" -} -``` - ---- - -## L - -### Localization (l10n) -Adapting software for specific language/region. SureForms supports translation. - -**Files:** -- `languages/sureforms-{locale}.po` - Translation strings -- `languages/sureforms-{locale}.mo` - Compiled translations - -**Functions:** -```php -__('Email', 'sureforms'); // Translate string -_e('Submit', 'sureforms'); // Translate and echo -``` - ---- - -## M - -### Middleware -Intermediate server between client and API. SureForms uses middleware for AI form generation (client → middleware → OpenAI). - -**Why middleware?** -- Hides API keys from client -- Rate limiting -- Request logging -- Caching - -### Multi-Step Form (Pro) -Form split into multiple pages/steps. Improves completion rate by reducing cognitive load. - -**Example:** -``` -Step 1: Personal Information (name, email) -Step 2: Address Details -Step 3: Payment Information -``` - ---- - -## N - -### Namespace -PHP feature to organize code and prevent name conflicts. SureForms uses namespaces. - -**Example:** -```php -namespace SRFM\Inc\Database\Tables; - -class Entries { - // ... -} -``` - -### Native Integration -Integration built into SureForms (not requiring Zapier or external connector). - -**Examples:** -- Mailchimp (OAuth) -- HubSpot (OAuth) -- Slack (Webhook URL) - -### Nonce (Number Used Once) -Security token to verify request came from your site. SureForms verifies nonces on all AJAX/REST requests. - -**Example:** -```php -// Generate nonce -$nonce = wp_create_nonce('srfm_submit_form'); - -// Verify nonce -if (!wp_verify_nonce($_POST['nonce'], 'srfm_submit_form')) { - die('Invalid nonce'); -} -``` - ---- - -## O - -### OAuth (Open Authorization) -Protocol for secure authorization. Used by SureForms integrations (Mailchimp, HubSpot, etc.). - -**Flow:** -1. User clicks "Connect to Mailchimp" -2. Redirected to Mailchimp login -3. User approves access -4. Mailchimp redirects back with token -5. SureForms stores encrypted token - ---- - -## P - -### Payment Gateway -Service that processes credit card payments. SureForms supports Stripe and PayPal. - -**Comparison:** -- **Stripe:** 2.9% + $0.30, better for US/Europe -- **PayPal:** 2.9% + $0.30, more global recognition - -### Payment Intent (Stripe) -Stripe object representing payment attempt. Created before customer enters card details. - -**States:** -- `requires_payment_method` - Awaiting card -- `requires_confirmation` - Card entered, needs confirm -- `succeeded` - Payment successful -- `canceled` - Payment canceled - -### PCI DSS (Payment Card Industry Data Security Standard) -Security standard for handling credit card data. SureForms is PCI-compliant (never stores card data). - -**Compliance:** -- Card data sent directly to Stripe/PayPal -- SureForms only stores transaction ID -- No PAN (Primary Account Number) stored - -### Placeholder -Example text shown in empty input field. Disappears when user types. - -**Example:** -```html - -``` - -**Accessibility note:** Never use placeholder as label (screen readers may miss it). - -### Post Meta -WordPress method for storing additional data with posts. SureForms **doesn't** use post meta (uses custom tables instead). - -**Why not post meta?** -- Slow queries (no indexes) -- Hard to search -- Not optimized for large datasets - -### Post Type (Custom Post Type) -WordPress content type. SureForms forms are stored as custom post type `sureforms_form`. - -**Advantages:** -- Uses WordPress admin UI -- Revision history -- Trash/restore functionality - ---- - -## R - -### reCAPTCHA -Google anti-spam service. SureForms supports reCAPTCHA v2 and v3. - -**Versions:** -- **v2:** "I'm not a robot" checkbox -- **v3:** Invisible, scores user behavior (0-1) - -**Setup:** -1. Get API keys from Google reCAPTCHA admin -2. Add to SureForms → Settings → Security -3. Enable on forms - -### REST API -HTTP API for accessing SureForms data. Used by frontend, mobile apps, integrations. - -**Base URL:** `/wp-json/sureforms/v1/` - -**Example endpoints:** -- `POST /submit-form` - Submit form -- `GET /forms/{id}` - Get form data -- `POST /generate-form` - AI form generation - -### RTL (Right-to-Left) -Text direction for languages like Arabic, Hebrew. SureForms supports RTL. - -**CSS:** -```css -.srfm-field { - margin-inline-start: 10px; /* Not margin-left */ -} -``` - ---- - -## S - -### Sanitization (Input Sanitization) -Cleaning user input to prevent attacks. SureForms sanitizes all input before storage. - -**Functions:** -- `sanitize_text_field()` - Remove HTML/PHP -- `sanitize_email()` - Validate email format -- `sanitize_url()` - Validate URL format -- `absint()` - Force integer - -**Example:** -```php -$email = sanitize_email($_POST['email']); -$id = absint($_POST['id']); -``` - -### Schema (Database Schema) -Structure of database table (columns, types, indexes). - -**Example (wp_sureforms_entries):** -```sql -CREATE TABLE wp_sureforms_entries ( - id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, - form_id BIGINT UNSIGNED NOT NULL, - user_id BIGINT UNSIGNED, - entry_data LONGTEXT NOT NULL, - status VARCHAR(20) DEFAULT 'published', - created_at DATETIME NOT NULL, - INDEX idx_form_id (form_id), - INDEX idx_created_at (created_at) -); -``` - -### Shortcode -WordPress feature for embedding content. SureForms forms can be embedded via shortcode. - -**Syntax:** -``` -[sureforms id="123"] -``` - -**Parameters:** -- `id` - Form ID (required) -- `title` - Show title (true/false) -- `description` - Show description (true/false) - -### SQL Injection -Attack injecting malicious SQL into queries. SureForms prevents with `$wpdb->prepare()`. - -**Vulnerable code (DON'T DO THIS):** -```php -$id = $_GET['id']; -$wpdb->query("DELETE FROM table WHERE id = $id"); -// Attack: ?id=1 OR 1=1 (deletes all records!) -``` - -**Safe code:** -```php -$id = absint($_GET['id']); -$wpdb->query($wpdb->prepare("DELETE FROM table WHERE id = %d", $id)); -``` - -### Subscription -Recurring payment. SureForms supports subscriptions via Stripe and PayPal. - -**Intervals:** -- Daily -- Weekly -- Monthly -- Yearly - ---- - -## T - -### Template (Form Template) -Pre-built form configuration. SureForms provides 100+ templates (contact, registration, survey, etc.). - -**Structure:** -```json -{ - "name": "Contact Form", - "fields": [ - { "type": "text", "label": "Name" }, - { "type": "email", "label": "Email" }, - { "type": "textarea", "label": "Message" } - ] -} -``` - -### Transient -WordPress temporary cache. SureForms uses transients for AI rate limiting and API responses. - -**Example:** -```php -// Store for 1 hour -set_transient('srfm_ai_rate_limit_' . $user_id, true, HOUR_IN_SECONDS); - -// Check -if (get_transient('srfm_ai_rate_limit_' . $user_id)) { - // Rate limited -} -``` - ---- - -## U - -### User Agent -String identifying browser/device. SureForms logs user agent for spam detection. - -**Example:** -``` -Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 -``` - ---- - -## V - -### Validation (Form Validation) -Checking if user input meets requirements. SureForms validates both client-side (JavaScript) and server-side (PHP). - -**Types:** -- **Required:** Field must not be empty -- **Format:** Email/URL must be valid -- **Range:** Number within min/max -- **Length:** String length constraints - -**Example:** -```php -if (empty($email) || !is_email($email)) { - $errors[] = 'Please enter a valid email'; -} -``` - ---- - -## W - -### Webhook -HTTP callback sent when event occurs. SureForms can send webhooks on form submission (Pro). - -**Flow:** -``` -User submits form - ↓ -SureForms processes submission - ↓ -Sends POST to webhook URL - ↓ -External service receives data -``` - -**Example payload:** -```json -{ - "event": "form_submit", - "form_id": 123, - "entry_id": 456, - "fields": { ... } -} -``` - -### WordPress Coding Standards (WPCS) -PHP coding style guide for WordPress. SureForms follows WPCS. - -**Key rules:** -- Tabs for indentation (not spaces) -- Yoda conditions: `if ( 'value' === $variable )` -- Braces required for all control structures -- Space after control keywords: `if (` not `if(` - -**Check compliance:** -```bash -composer lint -``` - ---- - -## X - -### XSS (Cross-Site Scripting) -Attack injecting malicious JavaScript into pages. SureForms prevents with output escaping. - -**Vulnerable code (DON'T DO THIS):** -```php -echo '
' . $_POST['name'] . '
'; -// Attack: -``` - -**Safe code:** -```php -echo '
' . esc_html($_POST['name']) . '
'; -// Output: <script>steal(document.cookie)</script> -``` - ---- - -## Z - -### Zapier -Third-party automation service. SureForms doesn't have native Zapier integration but supports webhooks (which Zapier can consume). - -**Alternative:** Use SureForms webhooks to trigger Zapier zaps. - ---- - -## Acronyms Quick Reference - -| Acronym | Full Term | Meaning | -|---------|-----------|---------| -| AJAX | Asynchronous JavaScript and XML | Update page without reload | -| API | Application Programming Interface | Methods to interact with software | -| CSRF | Cross-Site Request Forgery | Attack tricking users into unwanted actions | -| CSV | Comma-Separated Values | Spreadsheet file format | -| GDPR | General Data Protection Regulation | EU privacy law | -| JSON | JavaScript Object Notation | Data format | -| OAuth | Open Authorization | Secure authorization protocol | -| PCI DSS | Payment Card Industry Data Security Standard | Credit card security | -| REST | Representational State Transfer | Web API architecture | -| RTL | Right-to-Left | Text direction (Arabic, Hebrew) | -| SQL | Structured Query Language | Database query language | -| URL | Uniform Resource Locator | Web address | -| WCAG | Web Content Accessibility Guidelines | Accessibility standards | -| WPCS | WordPress Coding Standards | PHP coding style | -| XSS | Cross-Site Scripting | JavaScript injection attack | - ---- - -## Common Abbreviations - -| Abbr | Full Term | -|------|-----------| -| Pro | SureForms Pro (premium plugin) | -| CRM | Customer Relationship Management | -| UI | User Interface | -| UX | User Experience | -| CPT | Custom Post Type | -| DB | Database | -| WP | WordPress | -| PHP | PHP: Hypertext Preprocessor | -| JS | JavaScript | -| CSS | Cascading Style Sheets | - ---- - -**Next:** [Maintenance](maintenance.md) diff --git a/internal-docs/maintenance.md b/internal-docs/maintenance.md deleted file mode 100644 index 71c2f2604..000000000 --- a/internal-docs/maintenance.md +++ /dev/null @@ -1,842 +0,0 @@ -# Documentation Maintenance Guide - -**Version:** 2.5.0 - ---- - -## Purpose - -This guide explains how to keep SureForms internal documentation accurate and useful. - -**Goal:** Documentation should always reflect current reality. - -**Principle:** Update docs when code changes, not as afterthought. - ---- - -## When to Update Documentation - -### Always Update - -**1. New Feature Added** -- Update: `architecture.md`, `apis.md`, `product-vision.md` -- Add: Code examples to `ai-agent-guide.md` -- Update: Onboarding guide if workflow changes - -**2. API Changes** -- Update: `apis.md` (new endpoints, hooks, parameters) -- Update: Code examples in all docs referencing changed API -- Mark deprecated APIs in `apis.md` - -**3. Database Schema Changes** -- Update: `architecture.md` (database section) -- Update: `codebase-map.md` (new files) -- Update: Migration guide if schema change requires migration - -**4. Security Fix** -- Update: `ai-agent-guide.md` (add to common pitfalls) -- Update: `troubleshooting.md` if fix addresses known issue -- Add example of vulnerable pattern to avoid - -**5. Breaking Changes** -- Update: `README.md` (migration guide) -- Update: `onboarding.md` (new workflows) -- Update: `faq.md` (address upgrade questions) - ---- - -### Update if Needed - -**6. Bug Fixes** -- Update: `troubleshooting.md` if common issue -- Add: To FAQ if frequently asked - -**7. Performance Improvements** -- Update: `architecture.md` if architecture changed -- Update: Benchmarks in `README.md` - -**8. UI/UX Changes** -- Update: `ui-and-copy.md` (new patterns, copy) -- Update: `onboarding.md` (user journeys) - ---- - -### Don't Update - -**9. Code Refactoring (No Behavior Change)** -- No doc update unless internal architecture significantly changed - -**10. Minor Copy Changes** -- No doc update unless it changes UX patterns - -**11. Version Bumps** -- Update version number at top of each doc -- That's it (unless other changes) - ---- - -## How to Update Documentation - -### Step 1: Identify Affected Docs - -**Use this decision tree:** - -``` -Did you change... - -┌─ Database schema? -│ └─> Update: architecture.md, codebase-map.md -│ -┌─ REST API? -│ └─> Update: apis.md, ai-agent-guide.md (examples) -│ -┌─ AJAX handlers? -│ └─> Update: apis.md -│ -┌─ Hooks/filters? -│ └─> Update: apis.md, ai-agent-guide.md (patterns) -│ -┌─ User-facing UI? -│ └─> Update: ui-and-copy.md, onboarding.md -│ -┌─ Security patterns? -│ └─> Update: ai-agent-guide.md, coding-standards.md -│ -┌─ Build process? -│ └─> Update: README.md, onboarding.md -│ -└─ New file/folder? - └─> Update: codebase-map.md -``` - ---- - -### Step 2: Read Existing Doc - -**Before editing:** -1. Read entire document -2. Identify outdated sections -3. Check for consistency with your changes - -**Don't:** -- Blindly add new section without reading context -- Create duplicate information -- Use different terminology than existing docs - ---- - -### Step 3: Make Minimal Changes - -**Best practices:** - -**Do:** -- Update only what changed -- Keep existing structure -- Match existing tone and style -- Add code examples if helpful - -**Don't:** -- Rewrite entire document (unless necessary) -- Change unrelated sections -- Reorganize without discussion -- Remove information (mark deprecated instead) - ---- - -### Step 4: Verify Examples Still Work - -**All code examples must be tested:** - -**PHP examples:** -```bash -# Create test file -cat > /tmp/test-example.php << 'EOF' - [ - ['key' => 'form_id', 'value' => 123, 'compare' => '='] - ], - 'limit' => 20 -]); -``` - -**❌ Bad:** -```php -// Vague, generic -$data = SomeClass::get_stuff($args); -``` - ---- - -### Cross-Referencing - -**Internal links:** -```markdown -See [Architecture Guide](architecture.md) for details. -See [Database Schema](architecture.md#database-schema) for table structure. -``` - -**External links:** -```markdown -Read [WordPress Coding Standards](https://developer.wordpress.org/coding-standards/). -``` - -**Code references:** -```markdown -See `inc/form-submit.php:88-119` for nonce verification. -``` - ---- - -### Code Block Guidelines - -**Always specify language:** - -````markdown -```php -// PHP code here -``` - -```javascript -// JavaScript here -``` - -```bash -# Shell commands here -``` - -```sql --- SQL queries here -``` -```` - -**Include comments:** -```php -// Good: Explain what code does -$entries = Entries::get_all([ - 'where' => [ - ['key' => 'status', 'value' => 'published', 'compare' => '='] - ] -]); -``` - -**Show output if helpful:** -```bash -wp plugin list --status=active -# Output: -# sureforms active -# sureforms-pro active -``` - ---- - -## Deprecation Process - -**When removing features:** - -### Step 1: Mark as Deprecated - -**In code:** -```php -/** - * Old function. - * - * @deprecated 2.5.0 Use new_function() instead. - */ -function old_function() { - _deprecated_function(__FUNCTION__, '2.5.0', 'new_function'); - return new_function(); -} -``` - -**In docs:** -```markdown -## ~~Old Feature~~ (Deprecated) - -**Deprecated in:** 2.5.0 -**Removed in:** 3.0.0 -**Replacement:** [New Feature](#new-feature) - -This feature is deprecated and will be removed in version 3.0.0. -Use [New Feature](#new-feature) instead. - -~~Old documentation here...~~ -``` - ---- - -### Step 2: Update Migration Guide - -**In README.md:** - -```markdown -## Upgrading from 2.4.x to 2.5.0 - -### Breaking Changes - -**Old Feature Deprecated:** -- **What changed:** `old_function()` is now deprecated -- **Action required:** Replace with `new_function()` -- **Code example:** - ```php - // Old (deprecated) - old_function($data); - - // New (recommended) - new_function($data); - ``` -``` - ---- - -### Step 3: Remove After Major Version - -**On next major version (3.0.0):** -1. Remove deprecated code -2. Remove ~~strikethrough~~ docs -3. Update changelog - ---- - -## Changelog Management - -**Keep CHANGELOG.md updated:** - -### Format - -```markdown -# Changelog - -## [2.5.1] - 2026-02-15 - -### Added -- New REST endpoint: `/sureforms/v1/forms/{id}/duplicate` -- Support for custom date formats in email notifications - -### Changed -- Improved performance of entry queries (20% faster) -- Updated Stripe API to v2024-01-01 - -### Deprecated -- `old_function()` - Use `new_function()` instead - -### Fixed -- Bug where conditional logic didn't work with checkboxes -- Memory leak in AI form generation - -### Security -- Fixed XSS vulnerability in admin settings (CVE-2026-0001) - -## [2.5.0] - 2026-02-01 - -... -``` - -**Categories:** -- **Added:** New features -- **Changed:** Changes to existing features -- **Deprecated:** Features marked for removal -- **Removed:** Features removed -- **Fixed:** Bug fixes -- **Security:** Security fixes - ---- - -## Documentation Review Checklist - -**Before committing doc changes:** - -### Content -- [ ] Information is accurate (tested code examples) -- [ ] No outdated information (double-checked) -- [ ] Cross-references updated (links work) -- [ ] Version number updated -- [ ] Terminology consistent with other docs - -### Style -- [ ] Clear and concise (no fluff) -- [ ] Code examples formatted correctly -- [ ] Spelling and grammar correct -- [ ] Tone matches existing docs - -### Technical -- [ ] All code examples tested -- [ ] All commands verified (on dev environment) -- [ ] All links work (no 404s) -- [ ] File paths correct (checked in codebase) - -### Accessibility -- [ ] Headings in logical order (H1 → H2 → H3) -- [ ] Code blocks have language specified -- [ ] Alt text for images (if any) -- [ ] Tables have headers - ---- - -## Automation & Tools - -### Linting Documentation - -**Check Markdown syntax:** - -```bash -# Install markdownlint -npm install -g markdownlint-cli - -# Lint all docs -cd internal-docs/ -markdownlint *.md -``` - -**Common issues caught:** -- Inconsistent heading levels -- Trailing whitespace -- Missing blank lines around code blocks - ---- - -### Link Checking - -**Verify all links work:** - -```bash -# Install markdown-link-check -npm install -g markdown-link-check - -# Check links -markdown-link-check internal-docs/*.md -``` - -**Fix broken links:** -- Update to correct URL -- Remove if resource no longer exists -- Use Internet Archive if critical resource - ---- - -### Spell Checking - -**Use spell checker:** - -```bash -# Install aspell -brew install aspell # macOS -apt install aspell # Linux - -# Check spelling -aspell check internal-docs/README.md -``` - -**Custom dictionary:** - -Create `.aspell.en.pws`: -``` -personal_ws-1.1 en 50 -SureForms -WordPress -Gutenberg -Mailchimp -PayPal -``` - ---- - -## Documentation Templates - -### New Feature Documentation Template - -**When adding new feature:** - -```markdown -## [Feature Name] - -**Since:** [version] -**Type:** [Free/Pro] - -### Overview - -[2-3 sentence description of what feature does and why it exists] - -### Use Cases - -- [Use case 1] -- [Use case 2] -- [Use case 3] - -### How to Use - -**Step 1: [Action]** - -[Description] - -```php -// Code example -``` - -**Step 2: [Action]** - -[Description] - -### Configuration - -| Option | Type | Default | Description | -|--------|------|---------|-------------| -| `option_name` | string | 'default' | What this does | - -### API Reference - -**REST Endpoint:** -``` -POST /sureforms/v1/feature -``` - -**Parameters:** -- `param1` (string, required) - Description -- `param2` (integer, optional) - Description - -**Response:** -```json -{ - "success": true, - "data": { ... } -} -``` - -### Examples - -**Example 1: [Use case]** -```php -// Code here -``` - -**Example 2: [Use case]** -```php -// Code here -``` - -### Troubleshooting - -**Issue:** [Common problem] -**Solution:** [How to fix] - -### Related - -- [Related feature 1](link) -- [Related feature 2](link) -``` - ---- - -### Bug Fix Documentation Template - -**When fixing bug:** - -**In troubleshooting.md:** - -```markdown -### [Issue Description] - -**Symptom:** [What user sees] - -**Diagnosis:** - -[How to identify the issue] - -```bash -# Commands to diagnose -``` - -**Fixes:** - -**Option 1: [Fix description]** -```php -// Code or command -``` - -**Option 2: [Alternative fix]** -```php -// Alternative code -``` - -**Prevents:** [What this prevents] - -**See also:** [Related issues] -``` - ---- - -## Review & Approval Process - -### Before Merging Docs - -**Self-review:** -1. Read your changes out loud -2. Test all code examples -3. Run linters -4. Check cross-references - -**Peer review:** -1. Request review from team member -2. Address feedback -3. Update based on comments - -**Final checks:** -1. Rebase on main branch -2. Verify no conflicts -3. One last proofread - ---- - -### Documentation Pull Request Template - -**PR description:** - -```markdown -## Documentation Update - -**Plugin Version:** 2.5.1 -**Docs Changed:** [List files] - -### Changes Made - -- [ ] Added documentation for [feature] -- [ ] Updated [section] in [file] -- [ ] Fixed typos in [file] - -### Verification - -- [x] All code examples tested -- [x] All links checked -- [x] Spelling checked -- [x] Cross-references updated -- [x] Version numbers updated - -### Related - -- Related PR: #123 -- Related Issue: #456 -``` - ---- - -## Documentation Metrics - -**Track documentation quality:** - -### Metrics to Monitor - -**Coverage:** -- % of features documented -- % of APIs documented -- % of code examples tested - -**Freshness:** -- Days since last update -- Number of outdated sections -- Deprecated content count - -**Quality:** -- Broken link count -- Spelling error count -- User-reported doc issues - -**Engagement:** -- Doc views (if analytics enabled) -- Time spent reading -- Bounce rate (if high, docs unclear) - ---- - -## Long-Term Maintenance - -### Quarterly Review - -**Every 3 months:** - -1. **Audit all docs:** - - Read each document start to finish - - Test all code examples - - Verify all links - - Update outdated info - -2. **User feedback:** - - Review GitHub issues tagged "documentation" - - Survey users about doc clarity - - Identify gaps in coverage - -3. **Reorganize if needed:** - - Move sections to better fit structure - - Split large docs if too long - - Merge duplicate information - ---- - -### Annual Review - -**Every year:** - -1. **Major cleanup:** - - Remove deprecated content - - Archive old versions - - Rewrite outdated sections - -2. **Structure evaluation:** - - Does structure still make sense? - - Should we add/remove files? - - Are cross-references clear? - -3. **Voice & tone:** - - Is tone consistent? - - Is it still beginner-friendly? - - Does it match product evolution? - ---- - -## Questions? - -**For documentation questions:** -- Create GitHub issue: `[Docs] Your question` -- Tag: `documentation` -- Assign: Documentation maintainer - -**For urgent doc bugs:** -- Ping in Slack: `#sureforms-docs` -- Include: File name, line number, issue description - ---- - -## Conclusion - -**Documentation is code.** - -Treat it with same care: -- Test before committing -- Review changes -- Keep it DRY (Don't Repeat Yourself) -- Refactor when needed - -**Good documentation:** -- Saves support time -- Accelerates onboarding -- Prevents bugs -- Shows we care - -**Thank you for maintaining SureForms docs!** 📚 - ---- - -**Version:** 2.5.0 -**Last Updated:** 2026-02-12 -**Maintainer:** SureForms Team diff --git a/internal-docs/onboarding.md b/internal-docs/onboarding.md deleted file mode 100644 index ab5b83ad3..000000000 --- a/internal-docs/onboarding.md +++ /dev/null @@ -1,1086 +0,0 @@ -# Developer Onboarding - -**Version:** 2.5.0 - ---- - -## Welcome to SureForms - -This guide helps you become productive quickly, whether you have 1 hour, 1 day, or 1 week. - -**What you're working on:** -- **SureForms Free:** AI-powered WordPress form builder (219 PHP files, 50+ blocks) -- **SureForms Pro:** Premium extension (206 PHP files, payments, integrations, advanced features) - -**Architecture:** WordPress + Gutenberg blocks + React 18 + Custom database - ---- - -## Prerequisites - -Before starting: -- [ ] WordPress 6.4+ installed locally -- [ ] Node.js 18+ and npm 8+ -- [ ] PHP 7.4+ with Composer -- [ ] Git configured -- [ ] IDE with PHP/JavaScript support -- [ ] Both plugins cloned from GitHub - -**Test environment:** -```bash -# If using Local by Flywheel or similar -http://localhost:10003/wp-admin/ -Username: admin -Password: admin -``` - ---- - -## 1-Hour Quick Start - -**Goal:** Make your first successful change - -### Step 1: Get Code Running (15 min) - -```bash -# Clone repositories (if not already) -cd /path/to/wp-content/plugins/ -git clone https://github.com/brainstormforce/sureforms.git -git clone https://github.com/brainstormforce/sureforms-pro.git - -# Install dependencies - SureForms Free -cd sureforms/ -npm install -composer install - -# Build assets -npm run build - -# Install dependencies - SureForms Pro -cd ../sureforms-pro/ -npm install -composer install -npm run build -``` - -**Verify installation:** -```bash -# In WordPress admin -wp plugin activate sureforms sureforms-pro -wp plugin list | grep sureforms -``` - -### Step 2: Create Your First Form (15 min) - -**Via WordPress admin:** -1. Go to **SureForms → Add New** -2. Click **Create with AI** or **Start from Blank** -3. Add fields: Email, Name, Message -4. Click **Publish** -5. Add to a page with the SureForms block - -**Via WP-CLI:** -```bash -# Create form programmatically -wp post create \ - --post_type=sureforms_form \ - --post_title="Test Contact Form" \ - --post_status=publish \ - --post_content='' -``` - -### Step 3: Make a Simple Change (20 min) - -**Task:** Change the submit button text - -**Files to modify:** -``` -src/blocks/form/edit.js ← React component -inc/blocks/form/block.php ← Server-side rendering -``` - -**Change 1: Edit the React component** - -Open `src/blocks/form/edit.js`: - -```javascript -// Find around line 45-50 -const { submitButtonText } = attributes; - -// Change default value -const defaultSubmitText = __('Send Message', 'sureforms'); // ← Change this -``` - -**Change 2: Rebuild** - -```bash -npm run build -``` - -**Verify:** Create new form, check if default button text changed. - -### Step 4: Debug Your Change (10 min) - -**Enable debugging:** - -Edit `wp-config.php`: -```php -define('WP_DEBUG', true); -define('WP_DEBUG_LOG', true); -define('WP_DEBUG_DISPLAY', false); -define('SCRIPT_DEBUG', true); // Loads unminified JS -``` - -**Check debug log:** -```bash -tail -f wp-content/debug.log -``` - -**Browser console:** -- Open DevTools → Console -- Look for JavaScript errors -- Check Network tab for AJAX failures - ---- - -## 1-Day Deep Dive - -**Goal:** Understand architecture and make meaningful contributions - -### Morning: Core Concepts (4 hours) - -#### Hour 1: Architecture Overview - -**Read these docs first:** -1. [README.md](README.md) - Project overview -2. [architecture.md](architecture.md) - System design -3. [codebase-map.md](codebase-map.md) - File structure - -**Key concepts to understand:** -- **Gutenberg blocks:** React components that render forms -- **Custom post type:** `sureforms_form` stores form configurations -- **Custom database tables:** `wp_sureforms_entries`, `wp_sureforms_payments` -- **REST API:** Handles form submissions, AI generation -- **AJAX handlers:** Payment processing, file uploads - -**Test your understanding:** -- Where is form submission data saved? (Answer: `wp_sureforms_entries` table) -- How does AI form generation work? (Answer: REST endpoint → external middleware → GPT API) -- What's the difference between Free and Pro? (Answer: Pro adds payments, integrations, conditional logic) - -#### Hour 2: Data Flow - -**Trace a form submission from start to finish:** - -``` -User fills form → Frontend validation → AJAX request - ↓ -inc/form-submit.php (Line 88-119: Nonce verification) - ↓ -Field validation (inc/field-validation.php) - ↓ -Sanitization (inc/helper.php::sanitize_by_field_type()) - ↓ -Database insert (inc/database/tables/entries.php::insert()) - ↓ -Email notification (inc/email/email-handler.php) - ↓ -Confirmation message (or redirect) -``` - -**Hands-on exercise:** -1. Enable MySQL query logging -2. Submit a test form -3. Check `wp_sureforms_entries` table -4. Verify entry data matches submission - -```bash -# View recent entries -wp db query "SELECT * FROM wp_sureforms_entries ORDER BY id DESC LIMIT 5;" -``` - -#### Hour 3: Payment Processing - -**Understand Stripe payment flow:** - -``` -User clicks "Pay" → Frontend creates payment intent - ↓ -AJAX: wp_ajax_nopriv_srfm_create_payment_intent - ↓ -inc/payments/front-end.php (Line 77-83: Create Stripe PaymentIntent) - ↓ -Stripe API processes payment - ↓ -Webhook received: sureforms/webhook_test - ↓ -inc/payments/stripe/stripe-webhook.php (Line 220-637: Handle events) - ↓ -Update wp_sureforms_payments table - ↓ -Send confirmation email -``` - -**Hands-on exercise:** -1. Set up Stripe test keys -2. Create a payment form -3. Use Stripe test card: `4242 4242 4242 4242` -4. Check `wp_sureforms_payments` table for payment record - -#### Hour 4: Pro Features - -**Explore key Pro additions:** - -**1. User Registration:** -- File: `inc/business/user-registration/processor.php` -- Creates WordPress user accounts from form submissions -- Handles login/password reset - -**2. Native Integrations:** -- Folder: `inc/pro/native-integrations/integrations/` -- 24+ services: Mailchimp, Brevo, HubSpot, Salesforce, etc. -- OAuth authentication with encrypted token storage - -**3. Conditional Logic:** -- Frontend: `src/pro/conditional-logic/` -- Show/hide fields based on user selections -- Real-time UI updates - -**Hands-on exercise:** -1. Create form with registration block -2. Submit form, verify user created: `wp user list` -3. Enable Mailchimp integration (test mode) -4. Submit form, check integration logs - -### Afternoon: Build Your First Feature (4 hours) - -**Challenge:** Add a new field type - -**Example: "Star Rating" field** - -#### Step 1: Plan (30 min) - -**Requirements:** -- Display 5 stars (clickable) -- Save selected rating (1-5) -- Validate: Required if configured -- Display in entries table - -**Files to create/modify:** -``` -src/blocks/star-rating/ ← New React component -inc/blocks/star-rating/block.php ← Server-side rendering -inc/helper.php ← Add sanitization -inc/field-validation.php ← Add validation -``` - -#### Step 2: Create Block Structure (1 hour) - -**Create block files:** - -```bash -# Create directories -mkdir -p src/blocks/star-rating -mkdir -p inc/blocks/star-rating - -# Copy from existing field (Phone is a good template) -cp -r src/blocks/phone/* src/blocks/star-rating/ -cp inc/blocks/phone/block.php inc/blocks/star-rating/ -``` - -**Edit `src/blocks/star-rating/block.json`:** - -```json -{ - "$schema": "https://schemas.wp.org/trunk/block.json", - "apiVersion": 3, - "name": "sureforms/star-rating", - "title": "Star Rating", - "category": "sureforms", - "icon": "star-filled", - "description": "Display a star rating input", - "attributes": { - "label": { - "type": "string", - "default": "Rate your experience" - }, - "required": { - "type": "boolean", - "default": false - }, - "maxRating": { - "type": "number", - "default": 5 - } - }, - "supports": { - "html": false - } -} -``` - -**Edit `src/blocks/star-rating/edit.js`:** - -```javascript -import { __ } from '@wordpress/i18n'; -import { useBlockProps } from '@wordpress/block-editor'; -import { TextControl, ToggleControl, RangeControl } from '@wordpress/components'; - -export default function Edit({ attributes, setAttributes }) { - const { label, required, maxRating } = attributes; - - return ( -
- setAttributes({ label: value })} - /> - setAttributes({ required: value })} - /> - setAttributes({ maxRating: value })} - min={1} - max={10} - /> -
- {[...Array(maxRating)].map((_, i) => ( - - ))} -
-
- ); -} -``` - -#### Step 3: Server-Side Rendering (45 min) - -**Edit `inc/blocks/star-rating/block.php`:** - -```php - [__CLASS__, 'render'], - ] - ); - } - - public static function render($attributes) { - $label = esc_html($attributes['label'] ?? 'Rate your experience'); - $required = !empty($attributes['required']); - $max_rating = absint($attributes['maxRating'] ?? 5); - $field_name = 'srfm-star-rating-' . uniqid(); - - ob_start(); - ?> -
- -
- - - ★ - - -
- > -
- { - const stars = container.querySelectorAll('.srfm-star'); - const input = container.nextElementSibling; - const maxRating = parseInt(container.dataset.max); - - stars.forEach(star => { - star.addEventListener('click', function() { - const value = parseInt(this.dataset.value); - input.value = value; - - // Visual update - stars.forEach((s, index) => { - if (index < value) { - s.classList.add('selected'); - } else { - s.classList.remove('selected'); - } - }); - }); - - // Hover effect - star.addEventListener('mouseenter', function() { - const value = parseInt(this.dataset.value); - stars.forEach((s, index) => { - if (index < value) { - s.classList.add('hover'); - } else { - s.classList.remove('hover'); - } - }); - }); - }); - - container.addEventListener('mouseleave', function() { - stars.forEach(s => s.classList.remove('hover')); - }); - }); -}); -``` - -#### Step 5: Register Block (15 min) - -**Edit `inc/blocks/register.php`:** - -```php -// Add to existing blocks registration -Star_Rating\Block::register(); -``` - -**Edit `src/blocks/star-rating/index.js`:** - -```javascript -import { registerBlockType } from '@wordpress/blocks'; -import edit from './edit'; -import metadata from './block.json'; - -registerBlockType(metadata.name, { - edit, - save: () => null, // Server-side rendering -}); -``` - -#### Step 6: Add Sanitization & Validation (30 min) - -**Edit `inc/helper.php`:** - -Find `sanitize_by_field_type()` method and add: - -```php -case 'star-rating': - $value = absint($value); - // Ensure value is between 1 and max rating - return ($value >= 1 && $value <= 10) ? $value : 0; -``` - -**Edit `inc/field-validation.php`:** - -Find validation logic and add: - -```php -if ($field_type === 'star-rating' && $is_required && empty($value)) { - $errors[] = __('Please select a rating', 'sureforms'); -} -``` - -#### Step 7: Build & Test (30 min) - -```bash -# Build assets -npm run build - -# Test in browser -# 1. Create new form -# 2. Add "Star Rating" block -# 3. Configure settings (label, required, max stars) -# 4. Publish form -# 5. Submit test entry -# 6. Verify data saved correctly - -# Check database -wp db query "SELECT * FROM wp_sureforms_entries ORDER BY id DESC LIMIT 1;" -``` - ---- - -## 1-Week Mastery - -**Goal:** Expert-level understanding and complex feature development - -### Day 1: Architecture Deep Dive - -**Morning:** -- Complete 1-day onboarding -- Read all internal docs thoroughly -- Map data flow for all major features - -**Afternoon:** -- Trace payment processing end-to-end -- Understand webhook verification -- Study integration architecture - -### Day 2: Security & Best Practices - -**Focus areas:** -1. **Input sanitization:** Understand all 15+ sanitization methods -2. **Output escaping:** When to use `esc_html()`, `esc_attr()`, `esc_url()` -3. **SQL injection prevention:** Always use `$wpdb->prepare()` -4. **CSRF protection:** Nonce verification patterns -5. **Authorization:** `current_user_can()` checks - -**Hands-on exercises:** -- Review `inc/form-submit.php` (Lines 88-119: Security checks) -- Study `inc/helper.php` sanitization methods -- Find and fix intentional security bugs in test code - -**Read:** -- [coding-standards.md](coding-standards.md) -- [ai-agent-guide.md](ai-agent-guide.md) - Security section - -### Day 3: React & Gutenberg Blocks - -**Topics:** -1. **Block architecture:** How Gutenberg blocks work -2. **Attributes:** Data storage and retrieval -3. **Inspector controls:** Settings sidebar -4. **Block variations:** Different field configurations -5. **Dynamic blocks:** Server-side rendering - -**Build complex block:** -- **Multi-step form block** (if not using Pro feature) -- Add step navigation -- Save progress between steps -- Implement validation per step - -**Resources:** -- Official Gutenberg docs: https://developer.wordpress.org/block-editor/ -- Example: Study `src/blocks/phone/` for complex field - -### Day 4: Database & REST API - -**Morning: Database operations** - -**Study these classes:** -- `inc/database/base.php` - Base table class -- `inc/database/tables/entries.php` - Entries CRUD -- `inc/database/tables/payments.php` - Payment records - -**Practice:** -```php -// Create custom query -use SRFM\Inc\Database\Tables\Entries; - -$entries = Entries::get_all([ - 'where' => [ - ['key' => 'form_id', 'value' => 123, 'compare' => '='], - ['key' => 'status', 'value' => 'published', 'compare' => '='] - ], - 'orderby' => 'created_at', - 'order' => 'DESC', - 'limit' => 20 -]); -``` - -**Afternoon: REST API development** - -**Create custom endpoint:** - -```php -// In new file: inc/rest-api-custom.php -namespace SRFM\Inc; - -class Rest_API_Custom { - public function register_routes() { - register_rest_route('sureforms/v1', '/custom-stats', [ - 'methods' => 'GET', - 'callback' => [$this, 'get_stats'], - 'permission_callback' => [$this, 'check_permissions'] - ]); - } - - public function check_permissions() { - return current_user_can('manage_options'); - } - - public function get_stats($request) { - // Your logic here - return ['success' => true, 'data' => []]; - } -} -``` - -### Day 5: Pro Features & Integrations - -**Morning: Payment processing** - -**Study both gateways:** -- Stripe: `inc/payments/stripe/` -- PayPal (Pro): `inc/business/payments/pay-pal/` - -**Understand webhook handling:** -- Signature verification -- Event processing -- Database updates -- Error handling - -**Afternoon: Build custom integration** - -**Example: Slack integration** - -1. Create integration folder: -``` -inc/pro/native-integrations/integrations/slack/ -├── config.json -└── actions/ - └── send-message.php -``` - -2. Define config: -```json -{ - "name": "Slack", - "slug": "slack", - "auth_method": "webhook_url", - "actions": [ - { - "name": "Send Message", - "slug": "send-message", - "endpoint": "chat.postMessage" - } - ] -} -``` - -3. Implement action: -```php -format_message($form_data); - - $response = wp_remote_post($webhook_url, [ - 'body' => json_encode(['text' => $message]), - 'headers' => ['Content-Type' => 'application/json'] - ]); - - if (is_wp_error($response)) { - return ['success' => false, 'error' => $response->get_error_message()]; - } - - return ['success' => true]; - } - - private function format_message($form_data) { - // Format form data as Slack message - return "New form submission:\n" . print_r($form_data, true); - } -} -``` - ---- - -## Testing Your Changes - -### Local Testing - -**PHP Unit Tests:** -```bash -# Run all tests -composer test - -# Run specific test file -vendor/bin/phpunit tests/unit/test-helper.php - -# Run with coverage -composer test-coverage -``` - -**JavaScript Tests:** -```bash -# Run all JS tests -npm run test:unit - -# Watch mode -npm run test:unit:watch - -# Coverage -npm run test:unit:coverage -``` - -### E2E Testing (Playwright) - -```bash -# Start test environment -npm run play:up - -# Run E2E tests -npm run play:run - -# Interactive mode (see browser) -npm run play:run:interactive - -# Stop environment -npm run play:down -``` - -### Manual Testing Checklist - -Before submitting PR: -- [ ] Form creation works -- [ ] Form submission saves entry -- [ ] Email notifications sent -- [ ] Payment processing works (if touched) -- [ ] No JavaScript console errors -- [ ] No PHP errors in debug.log -- [ ] Works in latest WordPress version -- [ ] Works in Firefox, Chrome, Safari -- [ ] Mobile responsive -- [ ] Accessibility: keyboard navigation works - ---- - -## Code Review Process - -### Before Creating PR - -**Self-review:** -1. Run linters: -```bash -composer lint # PHP_CodeSniffer -npm run lint-js # ESLint -``` - -2. Auto-fix minor issues: -```bash -composer format # phpcbf -npm run lint-js:fix # ESLint --fix -``` - -3. Check for common issues: -- [ ] All inputs sanitized -- [ ] All outputs escaped -- [ ] SQL queries use `prepare()` -- [ ] Nonces verified for AJAX/forms -- [ ] Capabilities checked for admin actions -- [ ] No hardcoded strings (use `__()` for i18n) - -### Creating PR - -**Branch naming:** -```bash -git checkout -b feat/star-rating-field -git checkout -b fix/payment-webhook-error -git checkout -b refactor/database-queries -``` - -**Commit message format:** -``` -type(scope): brief description - -Longer explanation if needed. - -Co-Authored-By: Your Name -``` - -**Types:** feat, fix, docs, style, refactor, test, chore - -**Example:** -``` -feat(blocks): add star rating field - -- Add new star-rating block -- Implement frontend JavaScript -- Add sanitization and validation -- Update docs with new field type - -Co-Authored-By: Claude Sonnet 4.5 -``` - -### PR Checklist - -- [ ] Tests pass: `composer test && npm run test:unit` -- [ ] Linting passes: `composer lint && npm run lint-js` -- [ ] No console errors -- [ ] Database migrations documented (if any) -- [ ] Breaking changes documented -- [ ] Changelog updated -- [ ] Screenshots attached (for UI changes) - ---- - -## Common Tasks & Patterns - -### Add New AJAX Handler - -**Pattern:** -```php -// In controller file -public function register_ajax_actions() { - add_action('wp_ajax_srfm_my_action', [$this, 'handle_my_action']); - add_action('wp_ajax_nopriv_srfm_my_action', [$this, 'handle_my_action']); -} - -public function handle_my_action() { - // CRITICAL: Always verify nonce - check_ajax_referer('srfm_my_action_nonce', 'security'); - - // Check permissions if needed - if (!current_user_can('manage_options')) { - wp_send_json_error(['message' => 'Insufficient permissions']); - } - - // Sanitize inputs - $data = Helper::sanitize_array_recursively($_POST['data'] ?? []); - - // Process... - - wp_send_json_success(['result' => $result]); -} -``` - -### Add New REST Endpoint - -**Pattern:** -```php -// In inc/rest-api.php -public function register_routes() { - register_rest_route('sureforms/v1', '/my-endpoint', [ - 'methods' => 'POST', - 'callback' => [$this, 'handle_request'], - 'permission_callback' => [$this, 'check_permissions'] - ]); -} - -public function check_permissions() { - return current_user_can('manage_options'); -} - -public function handle_request($request) { - // Always verify nonce - $nonce = $request->get_header('X-WP-Nonce'); - if (!wp_verify_nonce($nonce, 'wp_rest')) { - return new \WP_Error('invalid_nonce', 'Invalid nonce', ['status' => 403]); - } - - // Get and sanitize parameters - $params = $request->get_params(); - $clean_params = Helper::sanitize_array_recursively($params); - - // Process... - - return ['success' => true, 'data' => $result]; -} -``` - -### Add WordPress Hook - -**Action hook (notify about event):** -```php -// Trigger action after entry save -do_action('sureforms_after_entry_save', $entry_id, $form_id, $entry_data); - -// Other plugins/themes can listen: -add_action('sureforms_after_entry_save', function($entry_id, $form_id, $data) { - // Custom logic -}, 10, 3); -``` - -**Filter hook (modify data):** -```php -// Allow filtering of email subject -$subject = apply_filters('sureforms_email_subject', $subject, $form_id, $entry_data); - -// Other plugins/themes can modify: -add_filter('sureforms_email_subject', function($subject, $form_id, $data) { - return "[Form $form_id] $subject"; -}, 10, 3); -``` - -### Database Operations - -**Insert entry:** -```php -use SRFM\Inc\Database\Tables\Entries; - -$entry_id = Entries::insert([ - 'form_id' => 123, - 'user_id' => get_current_user_id(), - 'status' => 'published', - 'entry_data' => wp_json_encode($form_data) -]); -``` - -**Update entry:** -```php -Entries::update($entry_id, [ - 'status' => 'spam' -]); -``` - -**Delete entry:** -```php -Entries::delete($entry_id); -``` - -**Query entries:** -```php -$entries = Entries::get_all([ - 'where' => [ - ['key' => 'form_id', 'value' => 123, 'compare' => '='] - ], - 'limit' => 20, - 'offset' => 0 -]); -``` - ---- - -## Debugging Tips - -### Enable Debug Mode - -**wp-config.php:** -```php -define('WP_DEBUG', true); -define('WP_DEBUG_LOG', true); -define('WP_DEBUG_DISPLAY', false); -define('SCRIPT_DEBUG', true); -define('SAVEQUERIES', true); -``` - -### Check Debug Log - -```bash -# Real-time log monitoring -tail -f wp-content/debug.log - -# Search for errors -grep "SureForms" wp-content/debug.log -``` - -### JavaScript Debugging - -**Browser console:** -```javascript -// Check global object -console.log(window.sureforms); - -// Check block attributes -wp.data.select('core/block-editor').getBlocks(); - -// Check form data -document.querySelector('form').addEventListener('submit', (e) => { - console.log('Form data:', new FormData(e.target)); -}); -``` - -### Database Queries - -**Install Query Monitor plugin:** -```bash -wp plugin install query-monitor --activate -``` - -**Check slow queries:** -- Visit any admin page -- Click "Query Monitor" in admin bar -- View "Queries" tab -- Sort by time -- Optimize slow queries - -**Manual query inspection:** -```php -// Add to code temporarily -global $wpdb; -$wpdb->show_errors(); -$wpdb->print_error(); -``` - -### AJAX Debugging - -**Check network tab:** -1. Open DevTools → Network -2. Filter: XHR -3. Submit form -4. Click request -5. Check Response tab for errors - -**Add debug output:** -```php -public function handle_ajax() { - error_log('AJAX data: ' . print_r($_POST, true)); - // ... rest of code -} -``` - ---- - -## Resources - -### Internal Documentation -- [README.md](README.md) - Quick start -- [architecture.md](architecture.md) - System design -- [codebase-map.md](codebase-map.md) - File structure -- [apis.md](apis.md) - API reference -- [coding-standards.md](coding-standards.md) - Code standards -- [ai-agent-guide.md](ai-agent-guide.md) - AI agent guidance -- [troubleshooting.md](troubleshooting.md) - Common problems - -### External Resources -- **WordPress Codex:** https://codex.wordpress.org/ -- **Block Editor Handbook:** https://developer.wordpress.org/block-editor/ -- **REST API Handbook:** https://developer.wordpress.org/rest-api/ -- **React Docs:** https://react.dev/ -- **WP-CLI:** https://wp-cli.org/ - -### Community -- **GitHub Issues:** Report bugs, request features -- **Facebook Group:** https://www.facebook.com/groups/surecart -- **Support:** https://support.brainstormforce.com/ - ---- - -## Next Steps - -After completing onboarding: - -1. **Pick a starter issue:** - - Look for "good first issue" label on GitHub - - Start with documentation or small bug fixes - - Work up to features - -2. **Read code:** - - Pick a feature you use - - Trace it from UI to database - - Understand every line - -3. **Write tests:** - - For code you touch - - Increases confidence - - Helps others understand your changes - -4. **Ask questions:** - - Don't hesitate to ask - - Better to ask than assume - - Document answers for others - -**Welcome to the team!** 🚀 diff --git a/internal-docs/product-vision.md b/internal-docs/product-vision.md deleted file mode 100644 index f41f1951c..000000000 --- a/internal-docs/product-vision.md +++ /dev/null @@ -1,688 +0,0 @@ -# Product Vision - -**Version:** 2.5.0 - ---- - -## Mission - -**Empower anyone to build beautiful, high-converting forms without code.** - -SureForms exists to solve a fundamental problem: creating forms on WordPress is unnecessarily complex, resulting in ugly forms that hurt conversion rates. - ---- - -## The Problem We Solve - -### Pain Points (Before SureForms) - -**1. Complexity** -- Learning curve: New interfaces, proprietary builders -- Time waste: Hours configuring simple contact forms -- Technical barriers: Requires developer for custom fields - -**2. Design Limitations** -- Generic templates that don't match site design -- Limited styling options without CSS knowledge -- Mobile responsiveness as afterthought - -**3. Low Engagement** -- Long, intimidating single-page forms -- No personalization or conditional logic -- High abandonment rates (avg 67% for long forms) - -**4. Spam & Security** -- Constant bot submissions -- Security vulnerabilities in popular plugins -- GDPR compliance challenges - -**5. Integration Friction** -- Payment processing requires multiple plugins -- Manual data export/import to CRMs -- Webhook setup requires developer knowledge - ---- - -## Our Solution - -### Core Differentiators - -**1. Native WordPress (Gutenberg)** -- **Why:** Users already know the interface -- **Benefit:** Zero learning curve, instant productivity -- **Technical:** React blocks, no proprietary builder - -**2. AI-Powered Form Building** -- **Innovation:** First AI form builder for WordPress -- **How:** Natural language → complete functional form in seconds -- **Examples:** - - "Create a job application form" → 12-field form with file upload - - "Simple contact form" → 3 fields, perfectly styled - - "Event RSVP with dietary restrictions" → Conditional logic auto-configured - -**3. Built-in Payments** -- **Why:** No WooCommerce, no add-ons required -- **Gateways:** Stripe (Free), PayPal (Pro) -- **Features:** One-time, subscriptions, custom amounts -- **Security:** PCI-compliant, encrypted credentials - -**4. Mobile-First Design** -- **Approach:** Responsive by default, not opt-in -- **Testing:** Every block tested on iOS/Android -- **Performance:** Fast load times on 3G networks - -**5. Engagement Features (Pro)** -- **Conversational Forms:** Chat-like, one question at a time -- **Multi-Step Forms:** Break long forms into digestible steps -- **Conditional Logic:** Show/hide based on answers -- **Result:** 3x higher completion rates vs single-page forms - ---- - -## Target Users - -### Primary Personas - -#### 1. Website Owner (40% of users) -**Profile:** -- Small business owner or solopreneur -- Limited technical skills -- DIY mentality -- Budget-conscious - -**Needs:** -- Contact forms, quote requests, bookings -- Easy setup (< 10 minutes) -- Professional appearance -- Spam protection - -**Pain Points:** -- Frustrated with complex form builders -- Can't afford developer -- Generic templates don't match brand - -**How SureForms Helps:** -- AI creates form in 30 seconds -- Instant Form feature (no embedding needed) -- Built-in anti-spam (reCAPTCHA, Honeypot) -- Modern, customizable design - ---- - -#### 2. WordPress Designer (30% of users) -**Profile:** -- Freelancer or agency designer -- Strong design skills, basic code knowledge -- Builds sites for clients -- Values aesthetics and UX - -**Needs:** -- Forms that match site design -- Custom styling without CSS -- Fast deployment -- Client-friendly interface - -**Pain Points:** -- Form plugins look "generic" -- CSS overrides are tedious -- Clients can't update forms themselves -- Other plugins don't use Gutenberg - -**How SureForms Helps:** -- Gutenberg-native (feels like page building) -- Extensive styling options in UI -- Client can edit without breaking design -- Block patterns for reusability - ---- - -#### 3. WordPress Developer (20% of users) -**Profile:** -- Full-stack developer -- Builds custom WordPress solutions -- Values clean code and extensibility -- Performance-conscious - -**Needs:** -- Developer-friendly APIs -- Hooks and filters -- Custom field types -- Database access -- Integration capabilities - -**Pain Points:** -- Other plugins have messy codebases -- Limited extensibility -- Poor documentation -- Performance issues (N+1 queries, bloat) - -**How SureForms Helps:** -- Clean, modern codebase (PSR-12-inspired) -- Extensive hooks: 50+ actions/filters -- Well-documented APIs -- Optimized queries (custom tables, not post meta) -- GitHub access for contributions - ---- - -#### 4. E-commerce Store Owner (10% of users) -**Profile:** -- Runs WooCommerce or custom store -- Needs payment forms (not full checkout) -- Sells services, memberships, donations -- Wants simplicity - -**Needs:** -- Accept payments without WooCommerce -- Subscription billing -- Custom pricing fields -- Receipt emails - -**Pain Points:** -- WooCommerce is overkill for simple payments -- Other payment forms require add-ons -- Can't customize payment flow -- Poor mobile checkout experience - -**How SureForms Helps:** -- Built-in Stripe/PayPal (no plugins) -- Subscription support included -- Custom amount fields (donations, tips) -- Mobile-optimized payment UI - ---- - -## Feature Philosophy - -### Design Principles - -**1. Simplicity Over Features** -- Don't add features just because competitors have them -- Every feature must solve real user problem -- Hide complexity behind smart defaults - -**Example:** -- ❌ Bad: 50 font options overwhelming users -- ✅ Good: 5 curated fonts + custom font option - -**2. Progressive Disclosure** -- Show basic options first -- Advanced settings collapsed by default -- Help text on hover, not always visible - -**Example:** -- Default form settings: 4 essential options -- Advanced panel: 15+ options (collapsed) - -**3. Convention Over Configuration** -- Smart defaults based on common use cases -- Zero config for 80% of users -- Power users can customize - -**Example:** -- Email notification auto-configured with sensible template -- User can override if needed - -**4. Performance First** -- Lazy load non-critical assets -- Minimize HTTP requests -- Database queries optimized (no N+1) -- CSS/JS minified and cached - -**Metrics:** -- Page load impact: < 50KB additional assets -- Time to Interactive: < 2 seconds on 3G -- Database queries: Max 5 per form render - -**5. Accessibility Built-In** -- WCAG 2.1 Level AA compliance -- Keyboard navigation -- Screen reader support -- Focus indicators - -**Testing:** -- Every block tested with NVDA/JAWS -- Keyboard-only testing required -- Color contrast checked - ---- - -## Free vs Pro Strategy - -### Free Plugin (Core Experience) - -**Philosophy:** Full-featured, not crippled trial - -**Included:** -- Unlimited forms -- Unlimited submissions -- All 15+ field types -- Email notifications -- Spam protection (reCAPTCHA, Honeypot) -- Stripe payments (one-time, subscriptions) -- Form analytics -- Export entries (CSV) -- GDPR compliance -- Instant Forms - -**Limitations:** -- No PayPal -- No native integrations (Mailchimp, etc.) -- No conditional logic -- No multi-step/conversational forms -- No user registration -- No PDF generation - -**Goal:** Provide genuine value, build trust, convert 5-10% to Pro - ---- - -### Pro Plugin (Power Features) - -**Philosophy:** Advanced features for serious users - -**Added Value:** -- **Payments:** PayPal (one-time, subscriptions) -- **Integrations:** 24+ native (Mailchimp, Brevo, HubSpot, Salesforce, etc.) -- **Logic:** Conditional show/hide, calculations -- **Forms:** Multi-step, conversational, save & resume -- **Users:** Registration, login, password reset -- **Output:** PDF generation from submissions -- **Advanced Fields:** Upload (images, files), signature, calculator -- **Priority Support:** < 24hr response time - -**Pricing Tiers:** -- **Essential:** $99/year (3 sites) -- **Plus:** $199/year (20 sites) -- **Agency:** $299/year (unlimited sites) - -**Conversion Strategy:** -- Free users see "Pro" badge on locked features -- No nag screens or popups -- Upgrade CTA in logical places (when user needs feature) -- 14-day money-back guarantee - ---- - -## Competitive Landscape - -### Direct Competitors - -**1. Gravity Forms** -- **Strengths:** Mature, extensive add-ons, trusted -- **Weaknesses:** Old UI, not Gutenberg-native, expensive -- **Our Advantage:** Modern interface, AI builder, lower cost - -**2. WPForms** -- **Strengths:** Beginner-friendly, drag-and-drop -- **Weaknesses:** Generic designs, limited styling -- **Our Advantage:** Better design flexibility, Gutenberg-native - -**3. Formidable Forms** -- **Strengths:** Advanced features, views/reporting -- **Weaknesses:** Steep learning curve, performance issues -- **Our Advantage:** Simpler, faster, AI-assisted - -**4. Fluent Forms** -- **Strengths:** Conversational forms, modern UI -- **Weaknesses:** Not Gutenberg-native, separate builder -- **Our Advantage:** Native Gutenberg, simpler UX - -**5. Contact Form 7** -- **Strengths:** Free, lightweight, popular -- **Weaknesses:** No UI, requires shortcodes, ugly default styles -- **Our Advantage:** Visual builder, beautiful defaults, AI - ---- - -### Market Positioning - -**SureForms:** The AI-powered Gutenberg form builder - -**Tagline:** "Beautiful forms without code" - -**Positioning Statement:** -> For WordPress users who want high-converting forms without complexity, SureForms is the AI-powered form builder that creates beautiful, mobile-first forms in seconds—unlike outdated plugins that require hours of configuration and result in generic-looking forms. - -**Why Users Choose SureForms:** -1. **Speed:** AI creates forms in 30 seconds vs 30 minutes -2. **Design:** Modern, mobile-first vs generic templates -3. **Ease:** Gutenberg-native vs proprietary builder -4. **Value:** Built-in payments vs add-ons required - ---- - -## Product Roadmap - -### Current Focus (2026 Q1) - -**Theme:** Stability & Performance - -**Priorities:** -1. Bug fixes from user reports -2. Performance optimization (lazy loading, query optimization) -3. Security hardening (code audit, penetration testing) -4. Documentation improvements -5. Accessibility compliance (WCAG 2.2 Level AA) - ---- - -### Near-Term (2026 Q2-Q3) - -**Theme:** Advanced Features & Integrations - -**Planned:** -1. **More Integrations:** - - Google Sheets (native, no Zapier) - - Airtable - - Notion - - Slack (native) - -2. **Field Types:** - - Star rating - - Matrix/grid (Pro) - - File upload enhancements (drag & drop, preview) - -3. **Conditional Logic Enhancements (Pro):** - - Show/hide blocks (not just fields) - - Calculation fields (price quotes, BMI calculators) - - Conditional email notifications - -4. **Analytics:** - - Conversion funnel visualization - - A/B testing (form variations) - - Heatmaps (where users drop off) - -5. **Templates:** - - 100+ pre-built form templates - - Industry-specific (real estate, healthcare, education) - - Import/export custom templates - ---- - -### Long-Term Vision (2027+) - -**Theme:** AI-Driven Personalization - -**Research Areas:** -1. **AI Form Optimization:** - - Auto-suggest field improvements based on completion rates - - Predictive text for common fields - - Smart field ordering (ML-driven) - -2. **Advanced Conversational Forms:** - - Voice input support - - Natural language processing for responses - - Branching logic based on sentiment - -3. **Global Expansion:** - - Multi-language support (WPML, Polylang) - - Currency localization - - Regional compliance (CCPA, PIPEDA, etc.) - -4. **Enterprise Features:** - - Team collaboration (roles, permissions) - - Advanced approval workflows - - Audit logs - - White-label options - -5. **Mobile App:** - - iOS/Android app for managing entries - - Push notifications for new submissions - - Offline form viewing - ---- - -## Success Metrics - -### North Star Metric -**Active Forms:** Number of forms receiving at least 1 submission per month - -**Why:** Indicates genuine usage, not just installs - -**Target:** 100,000 active forms by end of 2026 - ---- - -### Secondary Metrics - -**Growth:** -- New installations per month: 50,000+ -- Activation rate: 60% (user creates first form within 7 days) -- Retention: 80% still active after 30 days - -**Engagement:** -- Forms created per user: 3.5 average -- Submissions per form: 25/month average -- Feature adoption (Pro): 40% use conditional logic - -**Conversion:** -- Free → Pro conversion: 5-7% -- Trial → Paid: 25% -- Annual renewal rate: 85% - -**Quality:** -- Support ticket volume: < 2% of active users -- Bug reports: < 0.5% of installations -- 4.5+ star rating on WordPress.org - -**Performance:** -- Average page load impact: < 40KB -- Time to first form submission: < 5 minutes (from install) -- Support response time: < 12 hours - ---- - -## User Feedback Integration - -### How We Listen - -**1. Support Tickets** -- Every ticket tagged by topic -- Monthly review of common issues -- Feature requests tracked in GitHub - -**2. User Surveys** -- Annual user satisfaction survey -- Post-purchase survey (Pro users) -- Exit survey (churned Pro users) - -**3. Analytics** -- Feature usage tracking (opt-in) -- Error logging (anonymized) -- Performance metrics - -**4. Community** -- Facebook group discussions -- GitHub issues and discussions -- WordPress.org support forum - -**5. Direct Outreach** -- User interviews (quarterly) -- Beta tester program -- Power user advisory board - ---- - -### Decision Framework - -**Feature Requests Evaluation:** - -**Criteria:** -1. **Impact:** How many users need this? (1-10) -2. **Effort:** Development complexity? (1-10) -3. **Strategic Fit:** Aligns with vision? (Yes/No) -4. **Competitive:** Do competitors have it? (Yes/No) -5. **Revenue:** Drives conversions? (Yes/No) - -**Scoring:** -- Impact / Effort = Priority score -- Strategic Fit = multiplier (2x if yes) -- Build if score > 5 - -**Example:** -- Feature: "Drag & drop file upload" -- Impact: 8 (many requests) -- Effort: 4 (moderate complexity) -- Strategic Fit: Yes (better UX) -- Score: (8/4) × 2 = 4 → **Build later** - ---- - -## Brand & Voice - -### Brand Personality - -**Adjectives:** -- Approachable (not intimidating) -- Modern (not trendy) -- Reliable (not boring) -- Empowering (not condescending) - -**Tone:** -- Friendly but professional -- Clear over clever -- Helpful without being pushy -- Honest about limitations - ---- - -### Writing Guidelines - -**Do:** -- Use "you" (conversational) -- Short sentences -- Active voice -- Explain "why" not just "how" - -**Don't:** -- Jargon without explanation -- Marketing fluff ("revolutionary", "game-changing") -- Passive voice ("the form was created") -- Unnecessary exclamation marks!!!! - -**Examples:** - -❌ Bad: "SureForms revolutionizes form building with cutting-edge AI technology!" - -✅ Good: "SureForms uses AI to create forms in seconds. Describe what you need, and we'll build it." - ---- - -❌ Bad: "The form submission process has been optimized for maximum conversion potential." - -✅ Good: "We designed our forms to load fast and look great on mobile, so more people complete them." - ---- - -## Technical Vision - -### Architecture Goals - -**1. Performance** -- Custom database tables (not post meta) -- Lazy loading for non-critical assets -- Query optimization (no N+1) -- CDN-friendly (static assets versioned) - -**2. Scalability** -- Handle 100,000+ submissions per form -- Efficient database queries (indexed columns) -- Background processing for heavy tasks (webhooks, PDFs) -- Caching strategy (transients, object cache) - -**3. Security** -- Input sanitization (all user data) -- Output escaping (all rendered content) -- Nonce verification (all AJAX/REST) -- SQL injection prevention (prepared statements) -- Regular security audits - -**4. Extensibility** -- 50+ hooks (actions and filters) -- Clean, documented APIs -- Developer-friendly codebase -- Backward compatibility promise - -**5. Maintainability** -- WordPress coding standards (PHP_CodeSniffer) -- ESLint for JavaScript -- Automated testing (PHPUnit, Playwright) -- Clear documentation (inline and external) - ---- - -## Values & Principles - -**1. User Privacy** -- No tracking without consent -- GDPR compliance built-in -- Data portability (easy export) -- Clear privacy policy - -**2. Open Source (Free Plugin)** -- Public GitHub repository -- Accept community contributions -- Transparent roadmap -- Active maintenance - -**3. Quality Over Speed** -- Test thoroughly before release -- Fix bugs before adding features -- Code review required for all changes -- No "move fast and break things" - -**4. Accessibility** -- WCAG 2.1 Level AA minimum -- Keyboard navigation always -- Screen reader testing required -- Color contrast compliance - -**5. Sustainability** -- Reasonable pricing (not subscription trap) -- Long-term support commitment -- No vendor lock-in (data always exportable) -- Transparent upgrade policies - ---- - -## What We Won't Do - -**Out of Scope:** - -**1. Full CRM System** -- Why: Bloat, complexity, competing with specialists -- Alternative: Integrate with existing CRMs (HubSpot, Salesforce) - -**2. Email Marketing Platform** -- Why: Already solved by Mailchimp, Brevo, etc. -- Alternative: Native integrations with 24+ email platforms - -**3. Complete E-commerce Solution** -- Why: WooCommerce exists, does it well -- Alternative: Simple payment forms (our niche) - -**4. Website Builder** -- Why: Outside core competency (forms) -- Alternative: Work seamlessly with any page builder - -**5. Survey & Quiz Builder** -- Why: Different use case, different UX requirements -- Alternative: Forms work for simple surveys - ---- - -## Conclusion - -**Core Belief:** -Forms are critical touchpoints between businesses and customers. They should be beautiful, fast, and easy to create. - -**Our Promise:** -We'll keep building tools that make form creation accessible to everyone, without sacrificing power or flexibility. - -**For Developers:** -Your feedback shapes this product. Keep the issues and PRs coming. We're listening. - ---- - -**Next:** [UI & Copy Guidelines](ui-and-copy.md) diff --git a/internal-docs/troubleshooting.md b/internal-docs/troubleshooting.md deleted file mode 100644 index b7f256af5..000000000 --- a/internal-docs/troubleshooting.md +++ /dev/null @@ -1,1031 +0,0 @@ -# Troubleshooting Guide - -**Version:** 2.5.0 - ---- - -## Quick Diagnostic - -**Before diving deep, check these common issues:** - -```bash -# 1. WordPress & PHP versions -wp core version -php -v - -# 2. Plugin status -wp plugin list | grep sureforms - -# 3. Theme compatibility -wp theme list --status=active - -# 4. Recent errors -tail -50 wp-content/debug.log | grep -i "sureforms\|fatal\|error" - -# 5. Database tables exist -wp db query "SHOW TABLES LIKE '%sureforms%';" -``` - ---- - -## Installation & Activation Issues - -### Plugin Won't Activate - -**Symptom:** "Plugin activation failed" or white screen - -**Common Causes:** - -**1. PHP Version Too Old** -```bash -php -v -# Required: PHP 7.4+ -``` - -**Fix:** -```bash -# Update PHP (contact host if shared hosting) -# Or add to wp-config.php temporarily to see error: -define('WP_DEBUG', true); -define('WP_DEBUG_DISPLAY', true); -``` - -**2. WordPress Version Too Old** -```bash -wp core version -# Required: WordPress 6.4+ -``` - -**Fix:** -```bash -wp core update -``` - -**3. Conflicting Plugin** - -**Check for conflicts:** -```bash -# Deactivate all other plugins -wp plugin deactivate --all --exclude=sureforms,sureforms-pro - -# Try activating SureForms -wp plugin activate sureforms - -# Reactivate plugins one by one -wp plugin activate plugin-name -``` - -**Common conflicts:** -- Old caching plugins (W3 Total Cache < 2.0) -- Security plugins with aggressive rules -- Other form builders (namespace collisions) - -**4. Memory Limit Too Low** - -**Check current limit:** -```bash -wp eval 'echo WP_MEMORY_LIMIT;' -``` - -**Fix (wp-config.php):** -```php -define('WP_MEMORY_LIMIT', '256M'); -``` - ---- - -### Pro Plugin Shows "Base Plugin Required" - -**Symptom:** SureForms Pro won't activate - -**Diagnosis:** -```bash -wp plugin list | grep sureforms -# Ensure both sureforms AND sureforms-pro are installed -``` - -**Fix:** -1. Install SureForms Free first -2. Activate SureForms Free -3. Then activate SureForms Pro - -**Check version compatibility:** -```bash -# Free and Pro versions should match -# Both should be 2.5.0 (or same major.minor) -``` - ---- - -### Database Tables Not Created - -**Symptom:** Form submissions fail, entries not showing - -**Check tables exist:** -```bash -wp db query "SHOW TABLES LIKE '%sureforms%';" -``` - -**Expected output:** -``` -wp_sureforms_entries -wp_sureforms_payments -wp_sureforms_integrations -wp_sureforms_save_resume -``` - -**Fix: Force database creation** -```bash -# Deactivate plugin -wp plugin deactivate sureforms sureforms-pro - -# Delete plugin (backup first!) -wp plugin delete sureforms - -# Reinstall -wp plugin install sureforms --activate - -# Tables should be created on activation -``` - -**Manual creation (last resort):** - -Read schema from: -- `inc/database/tables/entries.php` -- `inc/database/tables/payments.php` - -Run CREATE TABLE statements manually. - ---- - -## Form Builder (Editor) Issues - -### Forms Won't Load in Editor - -**Symptom:** Blank screen or infinite loading spinner - -**Diagnosis:** - -**1. Check browser console:** -``` -Open DevTools → Console -Look for JavaScript errors -``` - -**Common errors:** - -**a) "wp.blockEditor is undefined"** -- **Cause:** Outdated WordPress version -- **Fix:** `wp core update` - -**b) "React version mismatch"** -- **Cause:** Another plugin using old React version -- **Fix:** Deactivate other plugins one by one to find conflict - -**c) "Uncaught SyntaxError"** -- **Cause:** JavaScript file corrupted or not minified correctly -- **Fix:** Rebuild assets: `npm run build` in plugin directory - -**2. Check network tab:** -``` -DevTools → Network -Filter: JS -Look for failed requests (red, 404, 500) -``` - -**Common failures:** -- `form-editor.js` (404) → Rebuild assets -- `chunk-vendors.js` (500) → Server misconfiguration - -**3. Enable SCRIPT_DEBUG:** - -In `wp-config.php`: -```php -define('SCRIPT_DEBUG', true); -``` - -This loads unminified JS, easier to debug. - ---- - -### Blocks Not Appearing in Inserter - -**Symptom:** SureForms blocks missing from block library - -**Diagnosis:** -```bash -# Check if blocks are registered -wp eval "print_r(get_option('srfm_blocks_registration'));" -``` - -**Fixes:** - -**1. Re-register blocks:** -```bash -wp plugin deactivate sureforms -wp plugin activate sureforms -``` - -**2. Clear block cache:** -```bash -wp cache flush -wp transient delete --all -``` - -**3. Check block.json files exist:** -```bash -find wp-content/plugins/sureforms/inc/blocks -name "block.json" -# Should return multiple files -``` - ---- - -### Form Preview Shows "Invalid Block" - -**Symptom:** Form renders as "This block contains unexpected or invalid content" - -**Cause:** Block HTML structure changed, saved form has old structure - -**Fix:** - -**Option 1: Update block (preserves data):** -1. Click "Attempt Block Recovery" -2. Verify content looks correct -3. Update form - -**Option 2: Clear and rebuild:** -1. Delete the invalid block -2. Add fresh block -3. Reconfigure settings - -**Prevention:** -- Always test after plugin updates -- Keep staging environment for testing - ---- - -## Form Submission Issues - -### Form Submissions Not Saving - -**Symptom:** User submits form, success message shows, but no entry in database - -**Diagnosis:** - -**1. Check debug log:** -```bash -tail -f wp-content/debug.log -# Submit form while watching log -``` - -**Common errors:** -- "Database insert failed" → Check table permissions -- "Nonce verification failed" → Caching issue (see below) -- "Call to undefined method" → PHP version or missing dependency - -**2. Check database directly:** -```bash -# Get latest entry -wp db query "SELECT * FROM wp_sureforms_entries ORDER BY id DESC LIMIT 1;" -``` - -**3. Test with minimal form:** -Create form with ONLY: -- Email field -- Submit button - -If this works, issue is with specific field type. - -**Fixes:** - -**Database Permissions:** -```bash -# Check MySQL user has INSERT privilege -wp db query "SHOW GRANTS;" -``` - -**Fix permissions (MySQL):** -```sql -GRANT INSERT, UPDATE, DELETE ON database_name.* TO 'wp_user'@'localhost'; -FLUSH PRIVILEGES; -``` - -**Caching Interference:** - -Caching plugins cache nonce values, causing verification failures. - -**Fix:** -1. Exclude `/wp-admin/admin-ajax.php` from cache -2. Exclude REST API `/wp-json/` from cache -3. Or disable caching temporarily to test - ---- - -### Email Notifications Not Sending - -**Symptom:** Form submitted successfully, but no email received - -**Diagnosis:** - -**1. Check if emails are being sent at all:** -```bash -# Install WP Mail SMTP or similar -wp plugin install wp-mail-smtp --activate - -# Or test with simple command: -wp eval "wp_mail('your@email.com', 'Test', 'Testing SureForms');" -``` - -**2. Check SureForms email settings:** -```bash -# View form meta -wp post meta list | grep email -``` - -**3. Check spam folder** -- WordPress default `from` address: `wordpress@yourdomain.com` -- Often flagged as spam - -**Fixes:** - -**Configure SMTP:** - -Install WP Mail SMTP plugin: -```bash -wp plugin install wp-mail-smtp --activate -``` - -Configure with: -- Gmail -- SendGrid -- Mailgun -- Amazon SES - -**Check email template:** - -In form settings → Email Notification: -- Verify "To" address is correct -- Check "From" address is valid domain -- Test with simple subject/message - -**Server mail() function:** - -Some hosts disable PHP `mail()` function. - -Test: -```bash -php -r "mail('test@example.com', 'Test', 'Test message');" -``` - -If no email received, `mail()` is disabled. Use SMTP. - ---- - -### Form Validation Not Working - -**Symptom:** Form submits even with empty required fields - -**Causes:** - -**1. JavaScript disabled** (frontend validation skipped) -**2. Theme CSS hiding error messages** -**3. Custom JavaScript conflict** - -**Diagnosis:** - -**Check browser console:** -``` -Look for JavaScript errors -Check if srfm-validation.js loaded -``` - -**Test with default theme:** -```bash -wp theme activate twentytwentythree -# Submit form again -``` - -If works with default theme → Theme conflict. - -**Fixes:** - -**Theme conflict:** - -Add to theme's `functions.php`: -```php -add_action('wp_enqueue_scripts', function() { - // Ensure SureForms scripts load - wp_enqueue_script('srfm-frontend'); -}, 20); -``` - -**CSS hiding errors:** - -Check if theme has: -```css -.srfm-error { display: none !important; } -``` - -Remove or override. - ---- - -## Payment Processing Issues - -### Stripe Payments Failing - -**Symptom:** "Payment failed" error after entering card details - -**Diagnosis:** - -**1. Check Stripe API keys:** -```bash -# In WordPress admin: SureForms → Settings → Payments → Stripe -# Verify: -# - Using correct keys (test vs live) -# - Keys match Stripe dashboard -``` - -**2. Check Stripe webhook:** -```bash -# In Stripe Dashboard → Developers → Webhooks -# Verify webhook URL is: -https://yoursite.com/wp-json/sureforms/webhook_test - -# Check recent webhook deliveries for errors -``` - -**3. Check browser console:** -``` -DevTools → Console -Look for Stripe.js errors -``` - -**Common Errors:** - -**"Invalid API Key"** -- Using test key in live mode (or vice versa) -- API key revoked in Stripe dashboard -- Fix: Copy fresh keys from Stripe - -**"Payment Intent creation failed"** -- Amount is $0 or negative -- Currency mismatch -- Fix: Check form configuration, amount field - -**"Webhook signature verification failed"** -- Webhook secret incorrect -- Middleware issue -- Fix: Copy webhook signing secret from Stripe, update settings - -**Fixes:** - -**Test mode checklist:** -```bash -# 1. Use test API keys (starts with pk_test_ / sk_test_) -# 2. Test card: 4242 4242 4242 4242 -# 3. Any future expiry date -# 4. Any 3-digit CVC -``` - -**Live mode checklist:** -```bash -# 1. Use live API keys (starts with pk_live_ / sk_live_) -# 2. SSL certificate valid (https://) -# 3. Webhook verified in Stripe dashboard -# 4. Test with real card (refund immediately) -``` - ---- - -### PayPal Payments Failing (Pro) - -**Symptom:** Redirected to PayPal but payment doesn't process - -**Diagnosis:** - -**Check PayPal credentials:** -```bash -# SureForms → Settings → Payments → PayPal -# Verify: -# - Client ID matches PayPal dashboard -# - Secret matches -# - Using sandbox for testing, live for production -``` - -**Check webhook endpoint:** -```bash -# PayPal Dashboard → Apps & Credentials → Webhooks -# Webhook URL should be: -https://yoursite.com/wp-json/sureforms-pro/paypal-live-webhook -``` - -**Fixes:** - -**Test in sandbox mode first:** -1. Create PayPal sandbox account: https://developer.paypal.com/ -2. Use sandbox credentials in SureForms -3. Test with sandbox buyer account - -**Common issues:** -- **Wrong environment:** Using sandbox credentials in live mode -- **Webhook not subscribed:** Must subscribe to payment events in PayPal dashboard -- **SSL certificate:** PayPal requires valid HTTPS - ---- - -## Integration Issues (Pro) - -### Native Integration Not Connecting - -**Symptom:** "Connection failed" when adding integration (Mailchimp, HubSpot, etc.) - -**Diagnosis:** - -**1. Check OAuth redirect URL:** - -For OAuth integrations (Mailchimp, HubSpot, Salesforce): -``` -Redirect URL must be: -https://yoursite.com/wp-json/sureforms-pro/v1/oauth/callback -``` - -**2. Test API credentials:** - -For API key integrations (Brevo, etc.): -```bash -# Test API key directly -curl -X GET "https://api.brevo.com/v3/account" \ - -H "api-key: YOUR_API_KEY" -``` - -Should return account info, not error. - -**3. Check error logs:** -```bash -tail -f wp-content/debug.log | grep -i "integration\|oauth" -``` - -**Fixes:** - -**OAuth issues:** -- Ensure site uses HTTPS (required for OAuth) -- Whitelist redirect URL in service's developer console -- Check OAuth app has correct permissions/scopes - -**API key issues:** -- Regenerate key in service dashboard -- Copy entire key (no spaces, no quotes) -- Check key has required permissions (read/write) - ---- - -### Webhook Not Firing - -**Symptom:** Form submitted, but data not sent to integrated service - -**Diagnosis:** - -**Check webhook logs:** - -Install Query Monitor plugin: -```bash -wp plugin install query-monitor --activate -``` - -Submit form, check "HTTP API Calls" panel for webhook requests. - -**Manually trigger webhook:** -```bash -# Find integration ID -wp db query "SELECT * FROM wp_sureforms_integrations;" - -# Trigger webhook manually (developer test) -wp eval "do_action('sureforms_after_entry_save', 123, 456, []);" -``` - -**Fixes:** - -**Webhook URL validation:** - -In `inc/pro/integrations/webhooks.php`, ensure URL is valid: -- HTTPS only (no HTTP) -- No localhost (unless testing) -- Responds with 200 OK - -**Timeout issues:** - -Increase timeout in `wp-config.php`: -```php -define('WP_HTTP_BLOCK_EXTERNAL', false); -define('WP_ACCESSIBLE_HOSTS', 'api.mailchimp.com,api.hubspot.com'); -``` - ---- - -## Performance Issues - -### Form Editor Slow to Load - -**Symptom:** Takes 10+ seconds to load form in editor - -**Diagnosis:** - -**1. Check database size:** -```bash -wp db query "SELECT COUNT(*) FROM wp_sureforms_entries;" -# If > 100,000 entries, database may be slow -``` - -**2. Check server resources:** -```bash -# Memory usage -free -h - -# CPU usage -top - -# Disk I/O -iostat -``` - -**3. Profile with Query Monitor:** -```bash -wp plugin install query-monitor --activate -# Open form editor, check QM panel for slow queries -``` - -**Fixes:** - -**Optimize database:** -```bash -# Clean old entries (backup first!) -wp db query "DELETE FROM wp_sureforms_entries WHERE created_at < DATE_SUB(NOW(), INTERVAL 1 YEAR);" - -# Optimize tables -wp db optimize -``` - -**Increase PHP limits:** - -In `php.ini` or `.htaccess`: -``` -max_execution_time = 300 -memory_limit = 256M -``` - -**Enable object caching:** - -Install Redis or Memcached: -```bash -wp plugin install redis-cache --activate -wp redis enable -``` - ---- - -### Frontend Form Loads Slowly - -**Symptom:** Form takes 5+ seconds to appear on page - -**Diagnosis:** - -**Check asset loading:** -``` -DevTools → Network → Slow 3G simulation -Watch which assets are slow -``` - -**Common bottlenecks:** -- Google Fonts loading slowly -- Large CSS/JS files -- Unoptimized images in form - -**Fixes:** - -**Lazy load non-critical assets:** - -In `functions.php`: -```php -add_filter('script_loader_tag', function($tag, $handle) { - if ($handle === 'srfm-frontend') { - return str_replace(' src', ' defer src', $tag); - } - return $tag; -}, 10, 2); -``` - -**Use CDN for Google Fonts:** - -In form settings → Design → Typography: -- Limit to 1-2 font families -- Use system fonts for faster load (e.g., -apple-system) - -**Minify and combine assets:** -```bash -npm run build # Ensures assets are minified -``` - -**Enable caching:** - -Install caching plugin: -```bash -wp plugin install wp-super-cache --activate -``` - -Configure to cache pages with forms. - ---- - -## Block Compatibility Issues - -### Form Breaks After Theme Update - -**Symptom:** Form displays incorrectly or not at all after theme update - -**Diagnosis:** - -**Compare theme CSS:** - -Check if new theme has conflicting styles: -```css -/* Common conflicts */ -.srfm-form input { /* Theme override */ } -.srfm-field { /* Theme override */ } -``` - -**Test with default theme:** -```bash -wp theme activate twentytwentythree -``` - -If works → Theme issue. - -**Fixes:** - -**Add theme compatibility CSS:** - -In child theme `style.css`: -```css -/* Reset SureForms blocks */ -.srfm-form, -.srfm-field, -.srfm-form input, -.srfm-form textarea { - all: revert; -} - -/* Then apply minimal SureForms styles */ -``` - -**Use !important (last resort):** - -In SureForms settings → Custom CSS: -```css -.srfm-form input { - border: 1px solid #ccc !important; - padding: 10px !important; -} -``` - ---- - -### Conflicts with Page Builders - -**Symptom:** Forms don't work inside Elementor/Divi/Beaver Builder - -**Common Issues:** - -**1. JavaScript conflicts:** -- Page builder loads own jQuery version -- Conflicts with SureForms scripts - -**Fix:** -```php -// In functions.php -add_action('wp_enqueue_scripts', function() { - if (class_exists('Elementor\Plugin')) { - wp_dequeue_script('jquery'); - wp_enqueue_script('jquery'); - } -}, 100); -``` - -**2. CSS specificity:** -- Page builder CSS overrides SureForms - -**Fix:** - -Use SureForms settings → Custom CSS with higher specificity: -```css -.elementor-widget-container .srfm-form input { - /* Your styles */ -} -``` - ---- - -## Database & Query Issues - -### "Too many connections" Error - -**Symptom:** Site crashes during high form submission volume - -**Diagnosis:** -```bash -wp db query "SHOW STATUS LIKE 'max_used_connections';" -wp db query "SHOW VARIABLES LIKE 'max_connections';" -``` - -**Fixes:** - -**Increase max connections (MySQL):** - -In `my.cnf`: -``` -[mysqld] -max_connections = 500 -``` - -**Use persistent connections:** - -In `wp-config.php`: -```php -define('DB_CHARSET', 'utf8mb4'); -define('DB_COLLATE', ''); -define('MYSQL_CLIENT_FLAGS', MYSQLI_CLIENT_PERSISTENT); -``` - -**Add connection pooling:** - -Use ProxySQL or PgBouncer for connection pooling. - ---- - -### Slow Query: "SELECT * FROM wp_sureforms_entries" - -**Symptom:** Admin page very slow when viewing entries - -**Diagnosis:** -```bash -wp plugin install query-monitor --activate -# View entries page, check QM for slow queries -``` - -**Fixes:** - -**Add database indexes:** -```sql -ALTER TABLE wp_sureforms_entries -ADD INDEX idx_form_id (form_id), -ADD INDEX idx_created_at (created_at), -ADD INDEX idx_status (status); -``` - -**Limit entries displayed:** - -In admin, reduce entries per page from 100 to 20. - -**Paginate large result sets:** - -Ensure code uses `LIMIT` and `OFFSET`: -```php -$entries = Entries::get_all([ - 'limit' => 20, - 'offset' => ($page - 1) * 20 -]); -``` - ---- - -## WordPress.org Review Issues - -### Plugin Rejected for Security - -**Common reasons:** - -**1. Direct database calls without prepare():** -```php -// ❌ Bad -$wpdb->query("DELETE FROM table WHERE id = $id"); - -// ✅ Good -$wpdb->query($wpdb->prepare("DELETE FROM table WHERE id = %d", $id)); -``` - -**2. Unsanitized user input:** -```php -// ❌ Bad -echo $_POST['name']; - -// ✅ Good -echo esc_html(sanitize_text_field($_POST['name'] ?? '')); -``` - -**3. Missing nonce verification:** -```php -// ❌ Bad -if (isset($_POST['action'])) { do_action(); } - -// ✅ Good -if (isset($_POST['action']) && check_ajax_referer('my_action_nonce')) { - do_action(); -} -``` - -**Fix:** - -Run WordPress Coding Standards checker: -```bash -composer require --dev wp-coding-standards/wpcs -vendor/bin/phpcs --standard=WordPress inc/ -``` - -Fix all errors before resubmitting. - ---- - -## Getting Help - -### Before Asking for Help - -**Gather this information:** - -```bash -# 1. WordPress & PHP versions -wp core version -php -v - -# 2. Plugin version -wp plugin list | grep sureforms - -# 3. Active theme -wp theme list --status=active - -# 4. Other active plugins -wp plugin list --status=active - -# 5. Recent errors -tail -50 wp-content/debug.log - -# 6. Browser/OS (if frontend issue) -# Example: Chrome 120 on macOS 14 -``` - -### Where to Get Help - -**1. Documentation** (check first) -- This troubleshooting guide -- [FAQ](faq.md) -- [Architecture](architecture.md) - -**2. GitHub Issues** (bugs & feature requests) -- Search existing issues first -- Provide minimal reproduction steps -- Include system info from above - -**3. Support Portal** (Pro users) -- https://support.brainstormforce.com/ -- < 24hr response time for Pro users - -**4. Community** -- Facebook group: https://www.facebook.com/groups/surecart -- WordPress.org forum (Free only) - ---- - -## Still Stuck? - -If none of the above solutions work: - -**Create detailed bug report:** - -```markdown -**Environment:** -- WordPress: 6.4.2 -- PHP: 8.1 -- SureForms: 2.5.0 (Free/Pro) -- Theme: Astra 4.5.0 -- Browser: Chrome 120 - -**Steps to Reproduce:** -1. Create form with email field -2. Mark field as required -3. Submit form with empty email -4. [Describe unexpected behavior] - -**Expected:** Validation error shows -**Actual:** Form submits anyway - -**Debug Log:** -[Paste relevant errors from debug.log] - -**Screenshots:** -[Attach if visual issue] -``` - -Submit to: https://github.com/brainstormforce/sureforms/issues - ---- - -**Next:** [FAQ](faq.md) diff --git a/internal-docs/ui-and-copy.md b/internal-docs/ui-and-copy.md deleted file mode 100644 index e12a9a45a..000000000 --- a/internal-docs/ui-and-copy.md +++ /dev/null @@ -1,1077 +0,0 @@ -# UI & Copy Guidelines - -**Version:** 2.5.0 - ---- - -## User Experience Philosophy - -**Principle:** Every word and interaction should make the user feel capable, not confused. - -**User Mindset:** -- "I just want to create a form quickly" -- "I don't have time to read documentation" -- "I'm not a developer" - -**Our Responsibility:** -- Make obvious what to do next -- Explain why, not just how -- Never blame the user - ---- - -## User Journeys - -### Journey 1: First-Time User Creates Contact Form - -**Goal:** Create and publish first form in < 5 minutes - -**Steps:** - -**1. Plugin Activation (30 seconds)** - -``` -User activates plugin - ↓ -Redirect to welcome screen - ↓ -Show 2 options: - [Create with AI] [Start from Blank] -``` - -**Copy:** -``` -Welcome to SureForms! - -Let's create your first form. - -[Create with AI] ← Recommended for beginners - Let AI build your form from a simple description - -[Start from Blank] - Build your form block-by-block -``` - -**Design notes:** -- Large, friendly buttons -- "Recommended" badge on AI option -- No walls of text - ---- - -**2. AI Form Creation (2 minutes)** - -``` -User clicks "Create with AI" - ↓ -Modal appears with text input - ↓ -User types: "simple contact form" - ↓ -AI generates form (3-5 seconds) - ↓ -Form opens in editor, ready to publish -``` - -**Copy:** - -``` -Create Form with AI - -Describe the form you need: -┌─────────────────────────────────────┐ -│ Example: "job application with │ -│ file upload" or "event RSVP" │ -└─────────────────────────────────────┘ - -[Cancel] [Generate Form →] -``` - -**Loading state:** -``` -✨ Creating your form... - -AI is adding fields based on your description. -This usually takes 3-5 seconds. -``` - -**Success state:** -``` -✅ Your form is ready! - -We added: -• Name field -• Email field -• Message field -• Submit button - -You can add, remove, or rearrange fields below. - -[Publish Form] -``` - -**Design notes:** -- Loading spinner + encouraging message -- Success message lists what was created -- Clear next action (Publish) - ---- - -**3. Form Publishing (1 minute)** - -``` -User clicks "Publish" - ↓ -Gutenberg publish panel opens - ↓ -SureForms shows additional options -``` - -**Copy in publish panel:** - -``` -📋 Form Settings - -Where should submissions be sent? - -Email: [admin@yoursite.com ▼] - -After submission, show: -○ Confirmation message -○ Redirect to page -● Confirmation message (selected by default) - -Message: -┌─────────────────────────────────────┐ -│ Thank you! We'll respond within │ -│ 24 hours. │ -└─────────────────────────────────────┘ - -[Publish Form] -``` - -**Design notes:** -- Sensible defaults (confirmation message, admin email) -- Inline editing (no separate settings page) -- Jargon-free labels - ---- - -**4. Embedding Form (30 seconds)** - -``` -User wants to add form to page - ↓ -Edit page in Gutenberg - ↓ -Add SureForms block - ↓ -Select form from dropdown -``` - -**Copy in block inserter:** - -``` -SureForms - -Display a form on your page. - -📝 No form yet? Create one in SureForms > Add New -``` - -**Copy in block settings:** - -``` -Form - -Select a form: -[Contact Form ▼] [Create New] - -Display settings: -☑ Show form title -☑ Show form description -☐ Hide labels (show placeholders only) -``` - -**Design notes:** -- Help text guides to form creation if needed -- Checkbox labels explain what they do -- Preview updates in real-time - ---- - -### Journey 2: Pro User Sets Up Payment Form - -**Goal:** Create payment form and collect first payment - -**Complexity:** Higher (involves Stripe setup) - -**Steps:** - -**1. Payment Gateway Setup (5 minutes)** - -``` -User navigates to: -SureForms → Settings → Payments → Stripe -``` - -**Copy:** - -``` -Stripe Payments - -Accept credit card payments with Stripe. - -🔒 Secure: We never store card details. Payments are processed directly by Stripe. - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Test Mode (for testing) - -☑ Enable test mode - -Use these while testing: - Test card: 4242 4242 4242 4242 - Any future expiry, any CVC - -Publishable Key (starts with pk_test_) -┌─────────────────────────────────────┐ -│ │ -└─────────────────────────────────────┘ - -Secret Key (starts with sk_test_) -┌─────────────────────────────────────┐ -│ •••••••••••••••••••••••••••••••• │ -└─────────────────────────────────────┘ - -Where to get keys: -→ Stripe Dashboard > Developers > API Keys - https://dashboard.stripe.com/apikeys - -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - -Live Mode (for real payments) - -⚠️ Only use after testing - -Publishable Key (starts with pk_live_) -┌─────────────────────────────────────┐ -│ │ -└─────────────────────────────────────┘ - -Secret Key (starts with sk_live_) -┌─────────────────────────────────────┐ -│ │ -└─────────────────────────────────────┘ - -[Save Settings] -``` - -**Design notes:** -- Test mode emphasized first -- Clear instructions where to get keys -- Security reassurance ("We never store") -- Direct link to Stripe dashboard - ---- - -**2. Creating Payment Form (3 minutes)** - -``` -User creates new form - ↓ -Adds "Payment" block - ↓ -Configures amount and currency -``` - -**Copy in Payment block settings:** - -``` -Payment Details - -Amount -○ Fixed amount - ┌──────┐ - │ 50 │ USD ▼ - └──────┘ - -● Let user choose amount - Min: [10] Max: [1000] USD ▼ - Default: [50] - -Payment Type -● One-time payment -○ Subscription - Interval: [Monthly ▼] - -Button Text -┌─────────────────────────────────────┐ -│ Pay Now │ -└─────────────────────────────────────┘ -``` - -**Design notes:** -- Radio buttons for mutually exclusive options -- Currency dropdown next to amount -- Clear labels (no "recurring" jargon, use "subscription") - ---- - -**3. Testing Payment (2 minutes)** - -**Copy on frontend form:** - -``` -Payment Information - -Amount: $50.00 - -Card Number -┌─────────────────────────────────────┐ -│ 1234 5678 9012 3456 │ [Card icon] -└─────────────────────────────────────┘ - -Expiry CVC -┌──────────┐ ┌─────┐ -│ MM / YY │ │ 123 │ -└──────────┘ └─────┘ - -🔒 Secure payment powered by Stripe - Your card details are encrypted and never stored. - -[Pay $50.00] -``` - -**Success message after payment:** - -``` -✅ Payment Successful! - -Receipt sent to: john@example.com - -Transaction ID: ch_1A2B3C4D5E6F - -[View Receipt] [Back to Home] -``` - -**Error message if payment fails:** - -``` -❌ Payment Failed - -Your card was declined. - -Common reasons: -• Insufficient funds -• Incorrect card number or expiry date -• Card requires 3D Secure verification - -Please try again or use a different card. - -[Try Again] -``` - -**Design notes:** -- Security reassurance prominent -- Success message includes receipt email and transaction ID -- Error message explains why and how to fix - ---- - -### Journey 3: Power User Builds Conditional Logic Form (Pro) - -**Goal:** Show/hide fields based on user selection - -**Example:** Event RSVP with dietary restrictions (only show if attending) - -**Steps:** - -**1. Creating Base Form (2 minutes)** - -``` -User adds fields: - - "Will you attend?" (Multiple Choice: Yes/No) - - "Dietary restrictions" (Dropdown) -``` - -**2. Adding Conditional Logic (3 minutes)** - -``` -User clicks "Dietary restrictions" block - ↓ -Opens block settings panel - ↓ -Enables conditional logic -``` - -**Copy in block settings:** - -``` -Conditional Logic - -Show this field only when certain conditions are met. - -☑ Enable conditional logic - -Show this field when: - -[Will you attend? ▼] [is ▼] [Yes ▼] - -[+ Add Condition] - -Logic: -● Show if ALL conditions match (AND) -○ Show if ANY condition matches (OR) -``` - -**Design notes:** -- Toggle to enable -- Dropdown-based condition builder (no code) -- Visual feedback: field grays out in editor preview when hidden - ---- - -**3. Testing Logic (1 minute)** - -**Copy in editor preview mode:** - -``` -💡 Preview Mode - -This is how your form will appear to users. - -Try selecting different options to see conditional logic in action. - -[Exit Preview] -``` - -**Behavior:** -- User selects "Yes" → Dietary field appears -- User selects "No" → Dietary field disappears - -**Design notes:** -- Clear indication of preview mode -- Real-time updates (no reload) - ---- - -## Microcopy Guidelines - -### Field Labels - -**Be concise and conversational** - -❌ Bad: "Please enter your electronic mail address" -✅ Good: "Email" - -❌ Bad: "Input telephone number (optional)" -✅ Good: "Phone (optional)" - -**Use sentence case, not title case** - -❌ Bad: "First Name" -✅ Good: "First name" - -❌ Bad: "Company Name (If Applicable)" -✅ Good: "Company name (if applicable)" - ---- - -### Help Text - -**Explain why or provide examples** - -**Email field:** -❌ Bad: "Enter email" -✅ Good: "We'll send a confirmation to this email" - -**Phone field:** -❌ Bad: "Phone number" -✅ Good: "We'll only call if there's an issue with your order" - -**File upload:** -❌ Bad: "Upload file" -✅ Good: "Upload your resume (PDF or DOCX, max 10MB)" - ---- - -### Error Messages - -**Be specific and actionable** - -**Email validation:** -❌ Bad: "Invalid email" -✅ Good: "Please enter a valid email (e.g., name@example.com)" - -**Required field:** -❌ Bad: "This field is required" -✅ Good: "Please enter your name" - -**File size:** -❌ Bad: "File too large" -✅ Good: "File must be under 10MB. Yours is 15MB. Try compressing it." - -**Payment failed:** -❌ Bad: "Transaction error" -✅ Good: "Your card was declined. Please check your card details or try a different card." - ---- - -### Success Messages - -**Be enthusiastic but not over-the-top** - -**Form submission:** -❌ Bad: "Form submitted" -✅ Good: "Thanks! We'll get back to you within 24 hours." - -**Payment successful:** -❌ Bad: "Payment processed successfully. Transaction ID: 1234." -✅ Good: "✅ Payment received! Receipt sent to your email." - -**Registration:** -❌ Bad: "Account created. Please log in." -✅ Good: "Welcome! Check your email to verify your account." - ---- - -### Button Labels - -**Use verbs that describe the action** - -❌ Bad: "Submit" -✅ Good: "Send Message" - -❌ Bad: "Click Here" -✅ Good: "Download Receipt" - -❌ Bad: "Proceed" -✅ Good: "Continue to Payment" - -**For payment buttons, include amount** - -❌ Bad: "Pay" -✅ Good: "Pay $50.00" - -❌ Bad: "Subscribe" -✅ Good: "Subscribe for $9.99/month" - ---- - -### Settings & Options - -**Explain consequences, not just features** - -**Email notification:** -❌ Bad: "Send email notification" -✅ Good: "Email me when someone submits this form" - -**Required field:** -❌ Bad: "Required" -✅ Good: "Make this field required" (checkbox label) - -**Conditional logic:** -❌ Bad: "Enable conditional logic" -✅ Good: "Show or hide this field based on other answers" - ---- - -## Visual Design Patterns - -### Empty States - -**When user has no forms yet:** - -``` -┌─────────────────────────────────────────┐ -│ │ -│ 📝 │ -│ │ -│ No forms yet │ -│ │ -│ Forms help you collect information │ -│ from your website visitors. │ -│ │ -│ [Create Your First Form] │ -│ │ -└─────────────────────────────────────────┘ -``` - -**Copy principles:** -- Icon relevant to context -- 1-sentence explanation -- Clear call-to-action button - ---- - -**When form has no submissions:** - -``` -┌─────────────────────────────────────────┐ -│ │ -│ 📭 │ -│ │ -│ No submissions yet │ -│ │ -│ Share this form to start collecting │ -│ responses. │ -│ │ -│ [Copy Form Link] [Embed on Page] │ -│ │ -└─────────────────────────────────────────┘ -``` - -**Design notes:** -- Actionable next steps -- Multiple options (link vs embed) - ---- - -### Loading States - -**Form submission in progress:** - -``` -┌─────────────────────────────────────┐ -│ ⏳ Sending... │ -│ │ -│ Please don't close this page. │ -└─────────────────────────────────────┘ -``` - -**AI form generation:** - -``` -┌─────────────────────────────────────┐ -│ ✨ Creating your form... │ -│ │ -│ [████████░░] 80% │ -│ │ -│ Adding email validation... │ -└─────────────────────────────────────┘ -``` - -**Design notes:** -- Spinner or progress indicator -- Explain what's happening -- Show progress if possible - ---- - -### Confirmation Dialogs - -**Deleting a form:** - -``` -┌─────────────────────────────────────┐ -│ Delete "Contact Form"? │ -│ │ -│ This will permanently delete: │ -│ • The form │ -│ • 47 submissions │ -│ • All settings │ -│ │ -│ This cannot be undone. │ -│ │ -│ [Cancel] [Delete Form] │ -└─────────────────────────────────────┘ -``` - -**Design notes:** -- Specific about what will be deleted -- Use red/destructive style for delete button -- Cancel button should be default (easier to accidentally click) - ---- - -### Tooltips & Hints - -**When to use:** -- Explaining technical terms -- Providing examples -- Showing keyboard shortcuts - -**Format:** - -``` -Field Name [?] - ↓ (on hover) -┌─────────────────────────────────────┐ -│ This is the internal name used in │ -│ the database. │ -│ │ -│ Example: "first_name" │ -└─────────────────────────────────────┘ -``` - -**Guidelines:** -- Keep under 2 sentences -- Provide example if helpful -- Don't repeat the label - ---- - -## Accessibility - -### Screen Reader Text - -**Form structure:** - -```html -
-
-

Personal Information

- -
-
-``` - -**Error announcements:** - -```html -
- Please fix 2 errors before submitting. -
- - - - Please enter a valid email address - -``` - ---- - -### Keyboard Navigation - -**Required interactions:** -- Tab through all fields -- Space to toggle checkboxes/radio buttons -- Enter to submit form -- Escape to close modals - -**Visual focus indicators:** - -```css -.srfm-field input:focus { - outline: 2px solid #0073aa; - outline-offset: 2px; -} -``` - -**Never:** -```css -:focus { - outline: none; /* ❌ Never remove focus outline */ -} -``` - ---- - -### Color Contrast - -**WCAG 2.1 Level AA Requirements:** -- Normal text: 4.5:1 minimum -- Large text (18pt+): 3:1 minimum -- UI components: 3:1 minimum - -**Test tools:** -- WebAIM Contrast Checker -- Chrome DevTools (Lighthouse) - -**Safe color combinations:** -- White text on dark backgrounds (#333 or darker) -- Dark text on light backgrounds (#F0F0F0 or lighter) -- Avoid gray text on gray backgrounds - ---- - -## Tone & Voice - -### Voice Characteristics - -**Friendly but professional** -- Use "we" and "you" -- Conversational, not formal -- Helpful, not condescending - -**Example:** -❌ Formal: "The system has detected an error in your input." -✅ Friendly: "Oops! We couldn't save that. Check for any errors above." - ---- - -**Clear over clever** -- Avoid puns and wordplay -- Be direct -- Technical accuracy over marketing fluff - -**Example:** -❌ Clever: "Houston, we have a problem!" -✅ Clear: "Something went wrong. Please try again." - ---- - -**Empowering, not blaming** -- Focus on solutions, not problems -- Use "we" for errors, "you" for successes - -**Example:** -❌ Blaming: "You entered an invalid email." -✅ Empowering: "Hmm, that email doesn't look quite right. Mind double-checking it?" - ---- - -### Writing for Different Contexts - -**First-time users:** -- More explanation -- Examples provided -- Encouraging tone - -**Example:** -``` -Welcome to SureForms! - -Creating your first form is easy. We'll walk you through each step. - -Let's start by choosing what kind of form you need. -``` - ---- - -**Power users:** -- Less explanation -- Assume knowledge -- Efficiency-focused - -**Example:** -``` -Advanced Settings - -Show field if: [condition builder] -Custom CSS class: [input] -``` - ---- - -**Error states:** -- Apologetic but not dramatic -- Specific about what went wrong -- Clear next steps - -**Example:** -``` -We couldn't save your changes. - -The connection to the server timed out. - -Please try again. If this keeps happening, check your internet connection. - -[Try Again] -``` - ---- - -**Success states:** -- Positive reinforcement -- What happens next -- Optional next action - -**Example:** -``` -✅ Form published! - -Your form is now live at: -https://yoursite.com/contact - -[View Form] [Create Another] -``` - ---- - -## Form Field Best Practices - -### Required vs Optional - -**Default:** Make fields optional - -**Require only when absolutely necessary:** -- Name (if sending personalized response) -- Email (if you need to contact them) -- Payment details (if collecting payment) - -**Label optional fields:** -``` -Phone (optional) -Company name (optional) -``` - -**Don't label required fields:** -❌ Bad: "Email (required)" -✅ Good: "Email" (with * indicator) - ---- - -### Field Order - -**Logical flow:** -1. Personal info (Name, Email) -2. Specific questions -3. Payment details (if applicable) -4. Submit button - -**Example contact form:** -``` -1. Name -2. Email -3. Subject -4. Message -5. [Submit] -``` - -**Example order form:** -``` -1. Name -2. Email -3. Product selection -4. Quantity -5. Payment details -6. [Complete Purchase] -``` - ---- - -### Placeholder Text - -**Use sparingly** - -Only for examples, not as labels: - -❌ Bad: -``` -Label: [empty] -Placeholder: "Enter your email" -``` - -✅ Good: -``` -Label: Email -Placeholder: "name@example.com" -``` - -**Never use placeholders as only label** (accessibility issue) - ---- - -### Multi-Step Forms (Pro) - -**Step indicators:** - -``` -Step 1 of 3: Your Information -━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -●━━━━━━━━━━━━○━━━━━━━━━━━━━○ - -[Fields here] - -[Continue to Step 2 →] -``` - -**Navigation:** -- Show progress (Step 1 of 3) -- Visual progress bar -- Allow back navigation (not just forward) - -**Button labels:** -- Step 1: "Continue" (not "Next") -- Step 2: "Continue" -- Step 3: "Submit Form" (or "Complete Order") - ---- - -## Internationalization (i18n) - -### Text Translation - -**All user-facing strings must be translatable:** - -```php -// ✅ Good -__('Email', 'sureforms'); -_e('Submit Form', 'sureforms'); - -// ❌ Bad -echo 'Email'; // Hardcoded English -``` - -**Placeholders for dynamic content:** - -```php -// ✅ Good -sprintf(__('You have %d new submissions', 'sureforms'), $count); - -// ❌ Bad -echo "You have $count new submissions"; -``` - ---- - -### Date & Number Formatting - -**Use WordPress functions:** - -```php -// Dates -echo date_i18n(get_option('date_format'), $timestamp); - -// Numbers -echo number_format_i18n($number); - -// Currency -echo '$' . number_format_i18n($amount, 2); -``` - ---- - -### RTL Support - -**CSS for right-to-left languages:** - -```css -/* Use logical properties */ -.srfm-field { - margin-inline-start: 10px; /* Not margin-left */ - padding-inline-end: 20px; /* Not padding-right */ -} -``` - -**Test with RTL languages:** -- Arabic -- Hebrew -- Persian - ---- - -## Quality Checklist - -Before shipping UI copy: - -- [ ] Spell check passed -- [ ] Grammar correct -- [ ] Tone matches guidelines -- [ ] Actionable error messages -- [ ] Examples provided where helpful -- [ ] Accessibility: screen reader friendly -- [ ] Accessibility: color contrast ≥ 4.5:1 -- [ ] Keyboard navigation works -- [ ] i18n: All strings translatable -- [ ] RTL languages supported -- [ ] Tested with real users (if major UI) - ---- - -**Next:** [FAQ](faq.md) diff --git a/languages/sureforms-de_DE-120a6dad015d3891c70f578c2251576b.json b/languages/sureforms-de_DE-120a6dad015d3891c70f578c2251576b.json index 2adf62a77..b48c11488 100644 --- a/languages/sureforms-de_DE-120a6dad015d3891c70f578c2251576b.json +++ b/languages/sureforms-de_DE-120a6dad015d3891c70f578c2251576b.json @@ -1 +1 @@ -{"translation-revision-date":"2024-12-13T16:14:52+00:00","generator":"WP-CLI\/2.12.0","source":"assets\/build\/templatePicker.js","domain":"messages","locale_data":{"messages":{"":{"domain":"messages","lang":"en","plural-forms":"nplurals=2; plural=(n != 1);"},"Dashboard":["Armaturenbrett"],"Connect Now":["Jetzt verbinden"],"Authentication Failed":["Authentifizierung fehlgeschlagen"],"Contact Support":["Support kontaktieren"],"Click Here to Retry":["Klicken Sie hier, um es erneut zu versuchen"],"Exit to Dashboard":["Zum Dashboard zur\u00fcckkehren"],"AI Form Builder":["AI-Formular-Generator"],"Speech recognition is not supported in your current browser. Please use Google Chrome \/ Safari.":["Die Spracherkennung wird in Ihrem aktuellen Browser nicht unterst\u00fctzt. Bitte verwenden Sie Google Chrome \/ Safari."],"Please allow microphone access to use voice input.":["Bitte erlauben Sie den Mikrofonzugriff, um die Spracheingabe zu verwenden."],"Voice Input":["Spracheingabe"],"Try Again":["Versuchen Sie es erneut"],"Please try again after %s.":["Bitte versuchen Sie es nach %s erneut."],"You have reached the maximum number of form generations in your Free Plan.":["Sie haben die maximale Anzahl von Formularerstellungen in Ihrem kostenlosen Plan erreicht."],"Unlock Conversational Forms":["Konversationelle Formulare freischalten"],"Simple":["Einfach"],"Upgrade Now":["Jetzt upgraden"],"Generate with AI":["Mit KI generieren"],"Please check your username and password for the account, and try to reconnect again. Need help?":["Bitte \u00fcberpr\u00fcfen Sie Ihren Benutzernamen und Ihr Passwort f\u00fcr das Konto und versuchen Sie erneut, eine Verbindung herzustellen. Brauchen Sie Hilfe?"],"Describe the form you want to create":["Beschreiben Sie das Formular, das Sie erstellen m\u00f6chten"],"We are building your form\u2026":["Wir erstellen Ihr Formular\u2026"],"Payment":["Zahlung"],"and ":["und"],"more\u2026":["mehr\u2026"],"Calculations":["Berechnungen"],"Unlock Calculator Forms":["Rechnerformulare entsperren"],"Build Smart Forms That Calculate Instantly":["Erstellen Sie intelligente Formulare, die sofort berechnen"],"Empower your forms with advanced calculations. From loan calculators to BMI checkers - create interactive forms that give real-time results.":["Statten Sie Ihre Formulare mit fortschrittlichen Berechnungen aus. Von Kreditrechnern bis hin zu BMI-Checkern \u2013 erstellen Sie interaktive Formulare, die Echtzeitergebnisse liefern."],"Add complex formulas with ease":["F\u00fcgen Sie komplexe Formeln m\u00fchelos hinzu"],"Provide instant answers to users":["Bieten Sie den Nutzern sofortige Antworten."],"Perfect for finance, health, and pricing forms":["Perfekt f\u00fcr Finanz-, Gesundheits- und Preisformulare"],"Conversational":["Gespr\u00e4chig"],"Turn Simple Forms Into Conversations":["Verwandeln Sie einfache Formulare in Gespr\u00e4che"],"Transform boring forms into friendly, chat-like experiences. Ask one question at a time, just like a real conversation, and see higher engagement.":["Verwandeln Sie langweilige Formulare in freundliche, chat\u00e4hnliche Erlebnisse. Stellen Sie eine Frage nach der anderen, genau wie in einem echten Gespr\u00e4ch, und erleben Sie eine h\u00f6here Beteiligung."],"One question at a time, in chat flow":["Eine Frage nach der anderen, im Chat-Verlauf"],"More engaging than traditional forms":["Fesselnder als traditionelle Formen"],"Boosts completion rates with a friendly interface":["Steigert die Abschlussraten mit einer benutzerfreundlichen Oberfl\u00e4che"],"Select this if you need calculations in your form. For example: Loan interest calculator.":["W\u00e4hlen Sie dies, wenn Sie Berechnungen in Ihrem Formular ben\u00f6tigen. Zum Beispiel: Kreditrechner f\u00fcr Zinsen."],"Select this if you want your form to display one question at a time, like a chat.":["W\u00e4hlen Sie dies aus, wenn Ihr Formular eine Frage nach der anderen anzeigen soll, wie in einem Chat."],"Select this if you want to collect payments through your form.":["W\u00e4hlen Sie dies aus, wenn Sie Zahlungen \u00fcber Ihr Formular einziehen m\u00f6chten."],"%d AI Generations Left. SureForms Premium allows:":["%d KI-Generationen \u00fcbrig. SureForms Premium erm\u00f6glicht:"],"%d AI Generations Left, Connect to SureForms AI to Get 10 More":["%d KI-Generationen \u00fcbrig, verbinden Sie sich mit SureForms AI, um 10 weitere zu erhalten"],"%d AI Generations Left. Upgrade to SureForms Premium":["%d KI-Generationen \u00fcbrig. Upgrade auf SureForms Premium"],"Contact form to collect name, email, and message from visitors":["Kontaktformular zur Erfassung von Name, E-Mail und Nachricht von Besuchern"],"Job application form for \"Marketing Manager\" with resume upload":["Bewerbungsformular f\u00fcr \"Marketing Manager\" mit Lebenslauf-Upload"],"Feedback form to ask customers: \"How would you rate our product and what should we improve?\"":["Feedback-Formular, um Kunden zu fragen: \"Wie w\u00fcrden Sie unser Produkt bewerten und was sollten wir verbessern?\""],"Event registration form for \"Photography Workshop\" with date and seat selection":["Anmeldeformular f\u00fcr die Veranstaltung \"Fotografie-Workshop\" mit Datums- und Sitzplatzauswahl"],"Newsletter signup form with name and email to join mailing list":["Anmeldeformular f\u00fcr den Newsletter mit Name und E-Mail, um der Mailingliste beizutreten"],"Order form for \"Custom T-Shirt\" with size, color, and quantity options":["Bestellformular f\u00fcr \"Individuelles T-Shirt\" mit Optionen f\u00fcr Gr\u00f6\u00dfe, Farbe und Menge"],"Survey form: \"How satisfied are you with our service? (1\u20135 stars)\"":["Umfrageformular: \"Wie zufrieden sind Sie mit unserem Service? (1\u20135 Sterne)\""],"Appointment booking form for \"Consultation Call\" with preferred time":["Formular zur Terminbuchung f\u00fcr \"Beratungsgespr\u00e4ch\" mit bevorzugter Zeit"],"Describe the form that you want":["Beschreiben Sie das Formular, das Sie m\u00f6chten"],"Generate":["Erzeugen"],"Create Unlimited Forms with AI":["Erstellen Sie unbegrenzt Formulare mit KI"],"Add Advanced Field Types":["Erweiterte Feldtypen hinzuf\u00fcgen"],"Create Calculators, Surveys, etc.":["Erstellen Sie Rechner, Umfragen usw."],"Form Generation Limit Reached":["Formularerstellungslimit erreicht"],"You have reached the maximum number of form generations in your Free Plan. SureForms Premium allows:":["Sie haben die maximale Anzahl von Formularerstellungen in Ihrem kostenlosen Plan erreicht. SureForms Premium erm\u00f6glicht:"],"%s AI Generations Left.":["%s KI-Generationen \u00fcbrig."],"Unlock Unlimited Generations":["Schalte unbegrenzte Generationen frei"],"Connect to SureForms AI":["Mit SureForms AI verbinden"],"You Have Hit Your Free Limit.":["Sie haben Ihr kostenloses Limit erreicht."],"Connect to SureForms AI to Get 10 More.":["Verbinden Sie sich mit SureForms AI, um 10 weitere zu erhalten."],"Or create it yourself":["Oder erstellen Sie es selbst"],"Unable to create form":["Formular kann nicht erstellt werden"],"Something went wrong. Please try again.":["Etwas ist schiefgelaufen. Bitte versuchen Sie es erneut."],"Describe what kind of form you want":["Beschreiben Sie, welche Art von Formular Sie m\u00f6chten"],"Click to generate the form":["Klicken Sie, um das Formular zu erstellen"],"Connecting to AI service":["Verbindung zum KI-Dienst wird hergestellt"],"Generating fields":["Felder werden generiert"],"Finalizing your form":["Ihr Formular wird abgeschlossen"],"Opening form editor":["Formular-Editor wird ge\u00f6ffnet"],"Design Multistep Forms":["Mehrstufige Formulare entwerfen"],"Send Form Entries to Your CRM or Any App":["Senden Sie Formulareintr\u00e4ge an Ihr CRM oder eine beliebige App"],"You've reached your daily generation limit.":["Sie haben Ihr t\u00e4gliches Generierungslimit erreicht."],"You've reached your daily limit for AI form generations.":["Sie haben Ihr t\u00e4gliches Limit f\u00fcr die Erstellung von KI-Formularen erreicht."],"Quiz":["Quiz"],"Unlock Quiz Forms":["Quizformulare entsperren"],"Create Engaging Quizzes That Score Automatically":["Erstellen Sie ansprechende Quizze, die automatisch bewertet werden"],"Build interactive quizzes with scored questions and graded results. Perfect for assessments, trivia, and educational content.":["Erstellen Sie interaktive Quizze mit bewerteten Fragen und benoteten Ergebnissen. Perfekt f\u00fcr Bewertungen, Quizspiele und Bildungsinhalte."],"Auto-score responses instantly":["Antworten sofort automatisch bewerten"],"Display graded results to users":["Bewertete Ergebnisse f\u00fcr Benutzer anzeigen"],"Perfect for education, training, and fun trivia":["Perfekt f\u00fcr Bildung, Schulungen und unterhaltsame Quizfragen"],"Select this to create a quiz with scored questions and graded results.":["W\u00e4hlen Sie dies, um ein Quiz mit bewerteten Fragen und benoteten Ergebnissen zu erstellen."],"Select this to create a survey to collect responses and opinions.":["W\u00e4hlen Sie dies, um eine Umfrage zu erstellen, um Antworten und Meinungen zu sammeln."],"Survey":["Umfrage"],"Unlock Survey Forms":["Umfrageformulare entsperren"],"Collect Insights with Powerful Surveys":["Sammeln Sie Erkenntnisse mit leistungsstarken Umfragen"],"Create surveys to collect responses and opinions. Visualize results with charts and share aggregated insights with your audience.":["Erstellen Sie Umfragen, um Antworten und Meinungen zu sammeln. Visualisieren Sie die Ergebnisse mit Diagrammen und teilen Sie aggregierte Erkenntnisse mit Ihrem Publikum."],"Aggregate and visualize responses":["Antworten aggregieren und visualisieren"],"Show live results to respondents":["Live-Ergebnisse den Befragten anzeigen"],"Perfect for feedback, polls, and research":["Perfekt f\u00fcr Feedback, Umfragen und Forschung"]}}} \ No newline at end of file +{"translation-revision-date":"2024-12-13T16:14:52+00:00","generator":"WP-CLI\/2.12.0","source":"assets\/build\/templatePicker.js","domain":"messages","locale_data":{"messages":{"":{"domain":"messages","lang":"en","plural-forms":"nplurals=2; plural=(n != 1);"},"Dashboard":["Armaturenbrett"],"Connect Now":["Jetzt verbinden"],"Authentication Failed":["Authentifizierung fehlgeschlagen"],"Contact Support":["Support kontaktieren"],"Click Here to Retry":["Klicken Sie hier, um es erneut zu versuchen"],"Exit to Dashboard":["Zum Dashboard zur\u00fcckkehren"],"AI Form Builder":["AI-Formular-Generator"],"Speech recognition is not supported in your current browser. Please use Google Chrome \/ Safari.":["Die Spracherkennung wird in Ihrem aktuellen Browser nicht unterst\u00fctzt. Bitte verwenden Sie Google Chrome \/ Safari."],"Please allow microphone access to use voice input.":["Bitte erlauben Sie den Mikrofonzugriff, um die Spracheingabe zu verwenden."],"Voice Input":["Spracheingabe"],"Try Again":["Versuchen Sie es erneut"],"Please try again after %s.":["Bitte versuchen Sie es nach %s erneut."],"You have reached the maximum number of form generations in your Free Plan.":["Sie haben die maximale Anzahl von Formularerstellungen in Ihrem kostenlosen Plan erreicht."],"Unlock Conversational Forms":["Konversationelle Formulare freischalten"],"Simple":["Einfach"],"Upgrade Now":["Jetzt upgraden"],"Generate with AI":["Mit KI generieren"],"Please check your username and password for the account, and try to reconnect again. Need help?":["Bitte \u00fcberpr\u00fcfen Sie Ihren Benutzernamen und Ihr Passwort f\u00fcr das Konto und versuchen Sie erneut, eine Verbindung herzustellen. Brauchen Sie Hilfe?"],"Describe the form you want to create":["Beschreiben Sie das Formular, das Sie erstellen m\u00f6chten"],"We are building your form\u2026":["Wir erstellen Ihr Formular\u2026"],"Payment":["Zahlung"],"and ":["und"],"more\u2026":["mehr\u2026"],"Calculations":["Berechnungen"],"Unlock Calculator Forms":["Rechnerformulare entsperren"],"Build Smart Forms That Calculate Instantly":["Erstellen Sie intelligente Formulare, die sofort berechnen"],"Empower your forms with advanced calculations. From loan calculators to BMI checkers - create interactive forms that give real-time results.":["Statten Sie Ihre Formulare mit fortschrittlichen Berechnungen aus. Von Kreditrechnern bis hin zu BMI-Checkern \u2013 erstellen Sie interaktive Formulare, die Echtzeitergebnisse liefern."],"Add complex formulas with ease":["F\u00fcgen Sie komplexe Formeln m\u00fchelos hinzu"],"Provide instant answers to users":["Bieten Sie den Nutzern sofortige Antworten."],"Perfect for finance, health, and pricing forms":["Perfekt f\u00fcr Finanz-, Gesundheits- und Preisformulare"],"Conversational":["Gespr\u00e4chig"],"Turn Simple Forms Into Conversations":["Verwandeln Sie einfache Formulare in Gespr\u00e4che"],"Transform boring forms into friendly, chat-like experiences. Ask one question at a time, just like a real conversation, and see higher engagement.":["Verwandeln Sie langweilige Formulare in freundliche, chat\u00e4hnliche Erlebnisse. Stellen Sie eine Frage nach der anderen, genau wie in einem echten Gespr\u00e4ch, und erleben Sie eine h\u00f6here Beteiligung."],"One question at a time, in chat flow":["Eine Frage nach der anderen, im Chat-Verlauf"],"More engaging than traditional forms":["Fesselnder als traditionelle Formen"],"Boosts completion rates with a friendly interface":["Steigert die Abschlussraten mit einer benutzerfreundlichen Oberfl\u00e4che"],"Select this if you need calculations in your form. For example: Loan interest calculator.":["W\u00e4hlen Sie dies, wenn Sie Berechnungen in Ihrem Formular ben\u00f6tigen. Zum Beispiel: Kreditrechner f\u00fcr Zinsen."],"Select this if you want your form to display one question at a time, like a chat.":["W\u00e4hlen Sie dies aus, wenn Ihr Formular eine Frage nach der anderen anzeigen soll, wie in einem Chat."],"Select this if you want to collect payments through your form.":["W\u00e4hlen Sie dies aus, wenn Sie Zahlungen \u00fcber Ihr Formular einziehen m\u00f6chten."],"%d AI Generations Left. SureForms Premium allows:":["%d KI-Generationen \u00fcbrig. SureForms Premium erm\u00f6glicht:"],"%d AI Generations Left, Connect to SureForms AI to Get 10 More":["%d KI-Generationen \u00fcbrig, verbinden Sie sich mit SureForms AI, um 10 weitere zu erhalten"],"%d AI Generations Left. Upgrade to SureForms Premium":["%d KI-Generationen \u00fcbrig. Upgrade auf SureForms Premium"],"Contact form to collect name, email, and message from visitors":["Kontaktformular zur Erfassung von Name, E-Mail und Nachricht von Besuchern"],"Job application form for \"Marketing Manager\" with resume upload":["Bewerbungsformular f\u00fcr \"Marketing Manager\" mit Lebenslauf-Upload"],"Feedback form to ask customers: \"How would you rate our product and what should we improve?\"":["Feedback-Formular, um Kunden zu fragen: \"Wie w\u00fcrden Sie unser Produkt bewerten und was sollten wir verbessern?\""],"Event registration form for \"Photography Workshop\" with date and seat selection":["Anmeldeformular f\u00fcr die Veranstaltung \"Fotografie-Workshop\" mit Datums- und Sitzplatzauswahl"],"Newsletter signup form with name and email to join mailing list":["Anmeldeformular f\u00fcr den Newsletter mit Name und E-Mail, um der Mailingliste beizutreten"],"Order form for \"Custom T-Shirt\" with size, color, and quantity options":["Bestellformular f\u00fcr \"Individuelles T-Shirt\" mit Optionen f\u00fcr Gr\u00f6\u00dfe, Farbe und Menge"],"Survey form: \"How satisfied are you with our service? (1\u20135 stars)\"":["Umfrageformular: \"Wie zufrieden sind Sie mit unserem Service? (1\u20135 Sterne)\""],"Appointment booking form for \"Consultation Call\" with preferred time":["Formular zur Terminbuchung f\u00fcr \"Beratungsgespr\u00e4ch\" mit bevorzugter Zeit"],"Describe the form that you want":["Beschreiben Sie das Formular, das Sie m\u00f6chten"],"Generate":["Erzeugen"],"Create Unlimited Forms with AI":["Erstellen Sie unbegrenzt Formulare mit KI"],"Add Advanced Field Types":["Erweiterte Feldtypen hinzuf\u00fcgen"],"Create Calculators, Surveys, etc.":["Erstellen Sie Rechner, Umfragen usw."],"Form Generation Limit Reached":["Formularerstellungslimit erreicht"],"You have reached the maximum number of form generations in your Free Plan. SureForms Premium allows:":["Sie haben die maximale Anzahl von Formularerstellungen in Ihrem kostenlosen Plan erreicht. SureForms Premium erm\u00f6glicht:"],"%s AI Generations Left.":["%s KI-Generationen \u00fcbrig."],"Unlock Unlimited Generations":["Schalte unbegrenzte Generationen frei"],"Connect to SureForms AI":["Mit SureForms AI verbinden"],"You Have Hit Your Free Limit.":["Sie haben Ihr kostenloses Limit erreicht."],"Connect to SureForms AI to Get 10 More.":["Verbinden Sie sich mit SureForms AI, um 10 weitere zu erhalten."],"Or create it yourself":["Oder erstellen Sie es selbst"],"Unable to create form":["Formular kann nicht erstellt werden"],"Something went wrong. Please try again.":["Etwas ist schiefgelaufen. Bitte versuchen Sie es erneut."],"Describe what kind of form you want":["Beschreiben Sie, welche Art von Formular Sie m\u00f6chten"],"Click to generate the form":["Klicken Sie, um das Formular zu erstellen"],"Connecting to AI service":["Verbindung zum KI-Dienst wird hergestellt"],"Generating fields":["Felder werden generiert"],"Finalizing your form":["Ihr Formular wird abgeschlossen"],"Opening form editor":["Formular-Editor wird ge\u00f6ffnet"],"Design Multistep Forms":["Mehrstufige Formulare entwerfen"],"Send Form Entries to Your CRM or Any App":["Senden Sie Formulareintr\u00e4ge an Ihr CRM oder eine beliebige App"],"You've reached your daily generation limit.":["Sie haben Ihr t\u00e4gliches Generierungslimit erreicht."],"You've reached your daily limit for AI form generations.":["Sie haben Ihr t\u00e4gliches Limit f\u00fcr die Erstellung von KI-Formularen erreicht."],"Quiz":["Quiz"],"Unlock Quiz Forms":["Quizformulare entsperren"],"Create Engaging Quizzes That Score Automatically":["Erstellen Sie ansprechende Quizze, die automatisch bewertet werden"],"Build interactive quizzes with scored questions and graded results. Perfect for assessments, trivia, and educational content.":["Erstellen Sie interaktive Quizze mit bewerteten Fragen und benoteten Ergebnissen. Perfekt f\u00fcr Bewertungen, Quizspiele und Bildungsinhalte."],"Auto-score responses instantly":["Antworten sofort automatisch bewerten"],"Display graded results to users":["Bewertete Ergebnisse f\u00fcr Benutzer anzeigen"],"Perfect for education, training, and fun trivia":["Perfekt f\u00fcr Bildung, Schulungen und unterhaltsame Quizfragen"],"Select this to create a quiz with scored questions and graded results.":["W\u00e4hlen Sie dies, um ein Quiz mit bewerteten Fragen und benoteten Ergebnissen zu erstellen."],"Select this to create a survey to collect responses and opinions.":["W\u00e4hlen Sie dies, um eine Umfrage zu erstellen, um Antworten und Meinungen zu sammeln."],"Survey":["Umfrage"],"Unlock Survey Forms":["Umfrageformulare entsperren"],"Collect Insights with Powerful Surveys":["Sammeln Sie Erkenntnisse mit leistungsstarken Umfragen"],"Create surveys to collect responses and opinions. Visualize results with charts and share aggregated insights with your audience.":["Erstellen Sie Umfragen, um Antworten und Meinungen zu sammeln. Visualisieren Sie die Ergebnisse mit Diagrammen und teilen Sie aggregierte Erkenntnisse mit Ihrem Publikum."],"Aggregate and visualize responses":["Antworten aggregieren und visualisieren"],"Show live results to respondents":["Live-Ergebnisse den Befragten anzeigen"],"Perfect for feedback, polls, and research":["Perfekt f\u00fcr Feedback, Umfragen und Forschung"],"You do not have permission to create forms.":["Sie haben keine Berechtigung, Formulare zu erstellen."],"The form could not be saved. Please try again.":["Das Formular konnte nicht gespeichert werden. Bitte versuchen Sie es erneut."],"Unable to reach the SureForms AI service. Please check your connection and try again.":["Der SureForms AI-Dienst ist nicht erreichbar. Bitte \u00fcberpr\u00fcfen Sie Ihre Verbindung und versuchen Sie es erneut."],"The AI service did not return a response. Please try again.":["Der KI-Dienst hat keine Antwort zur\u00fcckgegeben. Bitte versuchen Sie es erneut."],"Form generation failed. Please try again.":["Die Formularerstellung ist fehlgeschlagen. Bitte versuchen Sie es erneut."],"The AI response was empty. Please refine your prompt and try again.":["Die KI-Antwort war leer. Bitte verfeinern Sie Ihre Eingabeaufforderung und versuchen Sie es erneut."],"Unable to build form fields from the AI response.":["Formularfelder k\u00f6nnen nicht aus der KI-Antwort erstellt werden."]}}} \ No newline at end of file diff --git a/languages/sureforms-de_DE-4b62e3f004dea2c587b5a3069263d994.json b/languages/sureforms-de_DE-4b62e3f004dea2c587b5a3069263d994.json index 23d4e69fb..7984eb64c 100644 --- a/languages/sureforms-de_DE-4b62e3f004dea2c587b5a3069263d994.json +++ b/languages/sureforms-de_DE-4b62e3f004dea2c587b5a3069263d994.json @@ -1 +1 @@ -{"translation-revision-date":"2024-12-13T16:14:52+00:00","generator":"WP-CLI\/2.12.0","source":"assets\/build\/blocks.js","domain":"messages","locale_data":{"messages":{"":{"domain":"messages","lang":"en","plural-forms":"nplurals=2; plural=(n != 1);"},"Settings":["Einstellungen"],"Search":["Suche"],"Fields":["Felder"],"Image":["Bild"],"Submit":["Einreichen"],"Required":["Erforderlich"],"Form Title":["Formulartitel"],"Show":["Zeigen"],"Hide":["Verbergen"],"Edit Form":["Formular bearbeiten"],"Icon":["Symbol"],"Desktop":["Desktop"],"Medium":["Mittel"],"Mobile":["Mobil"],"Repeat":["Wiederholen"],"Scroll":["Scrollen"],"Tablet":["Tablet"],"Basic":["Grundlegend"],"(no title)":["(kein Titel)"],"Select a Form":["W\u00e4hlen Sie ein Formular aus"],"No forms found\u2026":["Keine Formulare gefunden\u2026"],"Choose":["W\u00e4hlen"],"Create New":["Neu erstellen"],"Change Form":["Formular \u00e4ndern"],"This form has been deleted or is unavailable.":["Dieses Formular wurde gel\u00f6scht oder ist nicht verf\u00fcgbar."],"Form Settings":["Formulareinstellungen"],"Show Form Title on this Page":["Formulartitel auf dieser Seite anzeigen"],"Note: For editing SureForms, please refer to the SureForms Editor - ":["Hinweis: F\u00fcr die Bearbeitung von SureForms, bitte den SureForms-Editor verwenden -"],"Field preview":["Feldvorschau"],"General":["Allgemein"],"Style":["Stil"],"Advanced":["Fortgeschritten"],"No tags available":["Keine Tags verf\u00fcgbar"],"Device":["Ger\u00e4t"],"Select Shortcodes":["Shortcodes ausw\u00e4hlen"],"Page Break Label":["Seitenumbruch-Label"],"Next":["Weiter"],"Back":["Zur\u00fcck"],"Reset":["Zur\u00fccksetzen"],"Generic tags":["Allgemeine Tags"],"Pixel":["Pixel"],"Em":["Em"],"Select Units":["Einheiten ausw\u00e4hlen"],"%s units":["%s Einheiten"],"Margin":["Marge"],"Attributes":["Attribute"],"Input Pattern":["Eingabemuster"],"None":["Keine"],"(###) ###-####":["(###) ###-####"],"(##) ####-####":["(##) ####-####"],"27\/08\/2024":["27.08.2024"],"23:59:59":["23:59:59"],"27\/08\/2024 23:59:59":["27.08.2024 23:59:59"],"Custom":["Benutzerdefiniert"],"Custom Mask":["Benutzerdefinierte Maske"],"Please check the documentation to manage custom input pattern ":["Bitte \u00fcberpr\u00fcfen Sie die Dokumentation, um das benutzerdefinierte Eingabemuster zu verwalten"],"here":["hier"],"Default Value":["Standardwert"],"Error Message":["Fehlermeldung"],"Help Text":["Hilfetext"],"Number Format":["Zahlenformat"],"US Style (Eg: 9,999.99)":["US-Stil (z. B.: 9.999,99)"],"EU Style (Eg: 9.999,99)":["EU-Stil (z. B.: 9.999,99)"],"Minimum Value":["Mindestwert"],"Maximum Value":["Maximalwert"],"Please check the Minimum and Maximum value":["Bitte \u00fcberpr\u00fcfen Sie den Mindest- und H\u00f6chstwert"],"Enable Email Confirmation":["E-Mail-Best\u00e4tigung aktivieren"],"Checked by Default":["Standardm\u00e4\u00dfig aktiviert"],"Error message":["Fehlermeldung"],"Checked by default":["Standardm\u00e4\u00dfig ausgew\u00e4hlt"],"Please add a option props to MultiButtonsControl":["Bitte f\u00fcgen Sie eine Option props zu MultiButtonsControl hinzu"],"Icon Library":["Icon-Bibliothek"],"Close":["Schlie\u00dfen"],"All Icons":["Alle Symbole"],"Other":["Andere"],"No Icons Found":["Keine Symbole gefunden"],"Insert Icon":["Symbol einf\u00fcgen"],"Change Icon":["Symbol \u00e4ndern"],"Choose Icon":["Symbol ausw\u00e4hlen"],"Confirm":["Best\u00e4tigen"],"Cancel":["Abbrechen"],"Processing\u2026":["Verarbeitung\u2026"],"Select Video":["Video ausw\u00e4hlen"],"Change Video":["Video \u00e4ndern"],"Select Lottie Animation":["Lottie-Animation ausw\u00e4hlen"],"Change Lottie Animation":["Lottie-Animation \u00e4ndern"],"Upload SVG":["SVG hochladen"],"Change SVG":["SVG \u00e4ndern"],"Select Image":["Bild ausw\u00e4hlen"],"Change Image":["Bild \u00e4ndern"],"Upload SVG?":["SVG hochladen?"],"Upload SVG can be potentially risky. Are you sure?":["Das Hochladen von SVG kann potenziell riskant sein. Bist du sicher?"],"Upload Anyway":["Trotzdem hochladen"],"Bulk Add":["Massenhinzuf\u00fcgen"],"Bulk Add Options":["Optionen in gro\u00dfen Mengen hinzuf\u00fcgen"],"Enter each option on a new line.":["Geben Sie jede Option in einer neuen Zeile ein."],"Insert Options":["Optionen einf\u00fcgen"],"Full Width":["Volle Breite"],"Option Type":["Optionstyp"],"Edit Options":["Optionen bearbeiten"],"Add New Option":["Neue Option hinzuf\u00fcgen"],"ADD":["HINZUF\u00dcGEN"],"Enable Auto Country Detection":["Automatische L\u00e4nderdetektion aktivieren"],"%s Width":["%s Breite"],"Upgrade":["Aktualisieren"],"Clear":["Klar"],"Select Color":["Farbe ausw\u00e4hlen"],"Primary Color":["Prim\u00e4rfarbe"],"Text Color":["Textfarbe"],"Field Spacing":["Feldabstand"],"Small":["Klein"],"Large":["Gro\u00df"],"Left":["Links"],"Center":["Zentrum"],"Right":["Richtig"],"Color":["Farbe"],"Background Color":["Hintergrundfarbe"],"Auto":["Auto"],"Default":["Standard"],"Normal":["Normal"],"%":["%"],"Top":["Oben"],"Bottom":["Unten"],"Width":["Breite"],"Size":["Gr\u00f6\u00dfe"],"EM":["EM"],"Padding":["Polsterung"],"Color 1":["Farbe 1"],"Color 2":["Farbe 2"],"Type":["Typ"],"Linear":["Linear"],"Radial":["Radial"],"Location 1":["Standort 1"],"Location 2":["Standort 2"],"Angle":["Winkel"],"Classic":["Klassisch"],"Gradient":["Gradient"],"Horizontal":["Horizontal"],"Vertical":["Vertikal"],"Background":["Hintergrund"],"Cover":["Abdeckung"],"Contain":["Enthalten"],"Layout":["Layout"],"Overlay":["\u00dcberlagerung"],"No Repeat":["Keine Wiederholung"],"Overlay Opacity":["\u00dcberlagerungsdeckkraft"],"Conditional Logic":["Bedingte Logik"],"Upgrade to the SureForms Starter Plan to create dynamic forms that adapt based on user input, offering a personalised and efficient form experience.":["Wechseln Sie zum SureForms Starter-Plan, um dynamische Formulare zu erstellen, die sich basierend auf Benutzereingaben anpassen und ein personalisiertes und effizientes Formularerlebnis bieten."],"Enable Conditional Logic":["Bedingte Logik aktivieren"],"this field if":["dieses Feld, wenn"],"Configure Conditions":["Bedingungen konfigurieren"],"Premium":["Premium"],"Overlay Type":["Overlay-Typ"],"Image Overlay Color":["Bild\u00fcberlagerungsfarbe"],"Image Position":["Bildposition"],"Attachment":["Anhang"],"Fixed":["Fest"],"Blend Mode":["Mischmodus"],"Multiply":["Multiplizieren"],"Screen":["Bildschirm"],"Darken":["Verdunkeln"],"Lighten":["Erleichtern"],"Color Dodge":["Farb-Abwedeln"],"Saturation":["S\u00e4ttigung"],"Repeat-x":["Wiederholen-x"],"Repeat-y":["Wiederhole-y"],"PX":["PX"],"Button":["Schaltfl\u00e4che"],"Prefix Label":["Pr\u00e4fix-Label"],"Suffix Label":["Suffix-Label"],"Border Radius":["Randradius"],"Form Theme":["Formular-Thema"],"Select Gradient":["Gradient ausw\u00e4hlen"],"Unlock Conditional Logic Editor":["Conditional Logic Editor entsperren"],"Rich Text Editor":["Rich-Text-Editor"],"Read Only":["Nur Lesen"],"Select Country":["Land ausw\u00e4hlen"],"Default Country":["Standardland"],"Subscription":["Abonnement"],"One Time":["Einmal"],"Unique Entry":["Einzigartiger Eintrag"],"Maximum Characters":["Maximale Zeichen"],"Textarea Height":["Textbereichsh\u00f6he"],"Minimum Selections":["Mindestanzahl an Auswahlen"],"Maximum Selections":["Maximale Auswahlen"],"Add Numeric Values to Options":["F\u00fcgen Sie numerische Werte zu Optionen hinzu"],"Single Choice Only":["Nur eine Auswahl m\u00f6glich"],"Enable Dropdown Search":["Dropdown-Suche aktivieren"],"Allow Multiple":["Mehrfach erlauben"],"%1$s fields are required. Please configure these fields in the block settings.":["%1$s Felder sind erforderlich. Bitte konfigurieren Sie diese Felder in den Blockeinstellungen."],"%1$s field is required. Please configure this field in the block settings.":["%1$s Feld ist erforderlich. Bitte konfigurieren Sie dieses Feld in den Blockeinstellungen."],"You need to configure a payment account to collect payments from this form. Please configure your payment provider to proceed.":["Sie m\u00fcssen ein Zahlungskonto einrichten, um Zahlungen \u00fcber dieses Formular zu sammeln. Bitte konfigurieren Sie Ihren Zahlungsanbieter, um fortzufahren."],"Configure Payment Account":["Zahlungskonto konfigurieren"],"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.":["Dies ist ein Platzhalter f\u00fcr den Zahlungsblock. Die tats\u00e4chlichen Zahlungsfelder f\u00fcr Ihre konfigurierten Zahlungsanbieter werden nur angezeigt, wenn Sie das Formular in der Vorschau anzeigen oder ver\u00f6ffentlichen."],"2 Payments":["2 Zahlungen"],"3 Payments":["3 Zahlungen"],"4 Payments":["4 Zahlungen"],"5 Payments":["5 Zahlungen"],"Never":["Niemals"],"Stop Subscription After":["Abonnement beenden nach"],"Choose when to automatically stop the subscription":["W\u00e4hlen Sie, wann das Abonnement automatisch beendet werden soll"],"Number of Payments":["Anzahl der Zahlungen"],"Enter a number between 1 to 100":["Geben Sie eine Zahl zwischen 1 und 100 ein"],"Form Field":["Formularfeld"],"Payment Type":["Zahlungsart"],"Subscription Plan Name":["Abonnementplanname"],"Billing Interval":["Abrechnungsintervall"],"Daily":["T\u00e4glich"],"Weekly":["W\u00f6chentlich"],"Monthly":["Monatlich"],"Quarterly":["Viertelj\u00e4hrlich"],"Yearly":["J\u00e4hrlich"],"Amount Type":["Betragstyp"],"Fixed Amount":["Fester Betrag"],"Dynamic Amount":["Dynamischer Betrag"],"Choose whether to charge a fixed amount or charge the amount based on user input in other form fields.":["W\u00e4hlen Sie, ob ein fester Betrag berechnet werden soll oder ob der Betrag basierend auf Benutzereingaben in anderen Formularfeldern berechnet werden soll."],"Set the exact amount you want to charge. Users won\u2019t be able to change it":["Legen Sie den genauen Betrag fest, den Sie berechnen m\u00f6chten. Benutzer k\u00f6nnen ihn nicht \u00e4ndern"],"Choose Amount Field":["Betragsfeld ausw\u00e4hlen"],"Select a field\u2026":["W\u00e4hlen Sie ein Feld aus\u2026"],"Pick a field from your form like a number, dropdown, or multichoice whose value should decide the payment amount.":["W\u00e4hlen Sie ein Feld aus Ihrem Formular, wie eine Zahl, ein Dropdown-Men\u00fc oder eine Mehrfachauswahl, dessen Wert den Zahlungsbetrag bestimmen soll."],"Minimum Amount":["Mindestbetrag"],"Set the minimum amount users can enter (0 for no minimum)":["Legen Sie den Mindestbetrag fest, den Benutzer eingeben k\u00f6nnen (0 f\u00fcr kein Minimum)"],"Customer Name Field (Required)":["Kundenname-Feld (erforderlich)"],"Customer Name Field (Optional)":["Kundenname-Feld (Optional)"],"Select the input field that contains the customer name (Required for subscriptions)":["W\u00e4hlen Sie das Eingabefeld aus, das den Kundennamen enth\u00e4lt (Erforderlich f\u00fcr Abonnements)"],"Select the input field that contains the customer name":["W\u00e4hlen Sie das Eingabefeld aus, das den Kundennamen enth\u00e4lt"],"Customer Email Field (Required)":["Kunden-E-Mail-Feld (erforderlich)"],"Select the email field that contains the customer email":["W\u00e4hlen Sie das E-Mail-Feld aus, das die Kunden-E-Mail enth\u00e4lt"],"Payment":["Zahlung"],"%s - Order ID":["%s - Bestell-ID"],"%s - Amount":["%s - Betrag"],"%s - Customer Email":["%s - Kunden-E-Mail"],"%s - Customer Name":["%s - Kundenname"],"%s - Status":["%s - Status"],"Button Alignment":["Schaltfl\u00e4chenanordnung"],"Placeholder":["Platzhalter"],"Preselect this option":["Diese Option vorausw\u00e4hlen"],"Restrict Country Codes":["L\u00e4ndercodes einschr\u00e4nken"],"Restriction Type":["Einschr\u00e4nkungstyp"],"Allow":["Erlauben"],"Block":["Blockieren"],"Select Allowed Countries":["Zul\u00e4ssige L\u00e4nder ausw\u00e4hlen"],"Choose countries\u2026":["L\u00e4nder ausw\u00e4hlen\u2026"],"Choose which country codes users can select in the phone number field. Leave empty to allow all country codes.":["W\u00e4hlen Sie aus, welche L\u00e4ndercodes Benutzer im Telefonnummernfeld ausw\u00e4hlen k\u00f6nnen. Lassen Sie das Feld leer, um alle L\u00e4ndercodes zuzulassen."],"Select Blocked Countries":["Gesperrte L\u00e4nder ausw\u00e4hlen"],"These countries will be hidden from the dropdown.":["Diese L\u00e4nder werden im Dropdown-Men\u00fc ausgeblendet."],"Bulk Edit":["Massenbearbeitung"],"Select Layout":["Layout ausw\u00e4hlen"],"Number of Columns":["Anzahl der Spalten"],"Validation Message for Duplicate":["Validierungsnachricht f\u00fcr Duplikat"],"Click here to insert a form":["Klicken Sie hier, um ein Formular einzuf\u00fcgen"],"Inherit Form's Original Style":["Urspr\u00fcnglichen Stil des Formulars \u00fcbernehmen"],"Text on Primary":["Text auf Prim\u00e4r"],"%s - Description":["%s - Beschreibung"],"Upgrade to Unlock":["Upgrade zum Freischalten"],"Custom (Premium)":["Benutzerdefiniert (Premium)"],"Select a theme style for this form embed.":["W\u00e4hlen Sie einen Themenstil f\u00fcr dieses Formulareinbettung aus."],"Colors":["Farben"],"Advanced Styling":["Erweitertes Styling"],"Unlock Custom Styling":["Benutzerdefinierte Gestaltung freischalten"],"Switch to Custom Mode to take full control of your form's design and spacing.":["Wechseln Sie in den benutzerdefinierten Modus, um die volle Kontrolle \u00fcber das Design und den Abstand Ihres Formulars zu \u00fcbernehmen."],"Full color control (buttons, fields, text)":["Volle Farbkontrolle (Schaltfl\u00e4chen, Felder, Text)"],"Row and column gap control":["Steuerung von Zeilen- und Spaltenabst\u00e4nden"],"Field spacing and layout precision":["Feldabst\u00e4nde und Layoutpr\u00e4zision"],"Complete button styling":["Komplette Schaltfl\u00e4chen-Stilgestaltung"],"Payment Description":["Zahlungsbeschreibung"],"Shown on payment receipts and in your payment dashboard (Stripe and PayPal). Leave blank to use the default.":["Auf Zahlungsbelegen und in Ihrem Zahlungs-Dashboard (Stripe und PayPal) angezeigt. Leer lassen, um den Standard zu verwenden."],"Slug":["Schnecke"],"Auto-generated on save":["Automatisch beim Speichern generiert"],"This slug is already used by another field. It will revert to the previous value.":["Dieser Slug wird bereits von einem anderen Feld verwendet. Er wird auf den vorherigen Wert zur\u00fcckgesetzt."],"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.":["Das \u00c4ndern des Slugs kann Formular\u00fcbermittlungen, bedingte Logik, Integrationen oder andere Funktionen, die derzeit auf diesen Slug verweisen, beeintr\u00e4chtigen. Sie m\u00fcssen alle derartigen Verweise manuell aktualisieren."],"Field Slug":["Feld-Slug"],"Location Services":["Standortdienste"],"Unlock Address Autocomplete":["Adresse-Autovervollst\u00e4ndigung freischalten"],"Upgrade to enable Google Address Autocomplete with interactive map preview, making address entry faster and more accurate for your users.":["Upgrade, um die Google Address Autocomplete-Funktion mit interaktiver Kartenansicht zu aktivieren, wodurch die Adresseingabe f\u00fcr Ihre Nutzer schneller und genauer wird."],"Enable Google Autocomplete":["Google Autovervollst\u00e4ndigung aktivieren"],"Show Interactive Map":["Interaktive Karte anzeigen"],"Payments Per Page":["Zahlungen pro Seite"],"Show Subscriptions Section":["Abonnement-Bereich anzeigen"],"Show a dedicated subscriptions section above payment history.":["Zeige einen eigenen Abonnementbereich \u00fcber der Zahlungshistorie an."],"Payment Dashboard":["Zahlungs\u00fcbersicht"],"View your payments and manage subscriptions in a single dashboard.":["Sehen Sie Ihre Zahlungen ein und verwalten Sie Abonnements in einem einzigen Dashboard."],"Dynamic Default Value":["Dynamischer Standardwert"]}}} \ No newline at end of file +{"translation-revision-date":"2024-12-13T16:14:52+00:00","generator":"WP-CLI\/2.12.0","source":"assets\/build\/blocks.js","domain":"messages","locale_data":{"messages":{"":{"domain":"messages","lang":"en","plural-forms":"nplurals=2; plural=(n != 1);"},"Settings":["Einstellungen"],"Search":["Suche"],"Fields":["Felder"],"Image":["Bild"],"Submit":["Einreichen"],"Required":["Erforderlich"],"Form Title":["Formulartitel"],"Show":["Zeigen"],"Hide":["Verbergen"],"Edit Form":["Formular bearbeiten"],"Icon":["Symbol"],"Desktop":["Desktop"],"Medium":["Mittel"],"Mobile":["Mobil"],"Repeat":["Wiederholen"],"Scroll":["Scrollen"],"Tablet":["Tablet"],"Basic":["Grundlegend"],"(no title)":["(kein Titel)"],"Select a Form":["W\u00e4hlen Sie ein Formular aus"],"No forms found\u2026":["Keine Formulare gefunden\u2026"],"Choose":["W\u00e4hlen"],"Create New":["Neu erstellen"],"Change Form":["Formular \u00e4ndern"],"This form has been deleted or is unavailable.":["Dieses Formular wurde gel\u00f6scht oder ist nicht verf\u00fcgbar."],"Form Settings":["Formulareinstellungen"],"Show Form Title on this Page":["Formulartitel auf dieser Seite anzeigen"],"Note: For editing SureForms, please refer to the SureForms Editor - ":["Hinweis: F\u00fcr die Bearbeitung von SureForms, bitte den SureForms-Editor verwenden -"],"Field preview":["Feldvorschau"],"General":["Allgemein"],"Style":["Stil"],"Advanced":["Fortgeschritten"],"No tags available":["Keine Tags verf\u00fcgbar"],"Device":["Ger\u00e4t"],"Select Shortcodes":["Shortcodes ausw\u00e4hlen"],"Page Break Label":["Seitenumbruch-Label"],"Next":["Weiter"],"Back":["Zur\u00fcck"],"Reset":["Zur\u00fccksetzen"],"Generic tags":["Allgemeine Tags"],"Pixel":["Pixel"],"Em":["Em"],"Select Units":["Einheiten ausw\u00e4hlen"],"%s units":["%s Einheiten"],"Margin":["Marge"],"Attributes":["Attribute"],"Input Pattern":["Eingabemuster"],"None":["Keine"],"(###) ###-####":["(###) ###-####"],"(##) ####-####":["(##) ####-####"],"27\/08\/2024":["27.08.2024"],"23:59:59":["23:59:59"],"27\/08\/2024 23:59:59":["27.08.2024 23:59:59"],"Custom":["Benutzerdefiniert"],"Custom Mask":["Benutzerdefinierte Maske"],"Please check the documentation to manage custom input pattern ":["Bitte \u00fcberpr\u00fcfen Sie die Dokumentation, um das benutzerdefinierte Eingabemuster zu verwalten"],"here":["hier"],"Default Value":["Standardwert"],"Error Message":["Fehlermeldung"],"Help Text":["Hilfetext"],"Number Format":["Zahlenformat"],"US Style (Eg: 9,999.99)":["US-Stil (z. B.: 9.999,99)"],"EU Style (Eg: 9.999,99)":["EU-Stil (z. B.: 9.999,99)"],"Minimum Value":["Mindestwert"],"Maximum Value":["Maximalwert"],"Please check the Minimum and Maximum value":["Bitte \u00fcberpr\u00fcfen Sie den Mindest- und H\u00f6chstwert"],"Enable Email Confirmation":["E-Mail-Best\u00e4tigung aktivieren"],"Checked by Default":["Standardm\u00e4\u00dfig aktiviert"],"Error message":["Fehlermeldung"],"Checked by default":["Standardm\u00e4\u00dfig ausgew\u00e4hlt"],"Please add a option props to MultiButtonsControl":["Bitte f\u00fcgen Sie eine Option props zu MultiButtonsControl hinzu"],"Icon Library":["Icon-Bibliothek"],"Close":["Schlie\u00dfen"],"All Icons":["Alle Symbole"],"Other":["Andere"],"No Icons Found":["Keine Symbole gefunden"],"Insert Icon":["Symbol einf\u00fcgen"],"Change Icon":["Symbol \u00e4ndern"],"Choose Icon":["Symbol ausw\u00e4hlen"],"Confirm":["Best\u00e4tigen"],"Cancel":["Abbrechen"],"Processing\u2026":["Verarbeitung\u2026"],"Select Video":["Video ausw\u00e4hlen"],"Change Video":["Video \u00e4ndern"],"Select Lottie Animation":["Lottie-Animation ausw\u00e4hlen"],"Change Lottie Animation":["Lottie-Animation \u00e4ndern"],"Upload SVG":["SVG hochladen"],"Change SVG":["SVG \u00e4ndern"],"Select Image":["Bild ausw\u00e4hlen"],"Change Image":["Bild \u00e4ndern"],"Upload SVG?":["SVG hochladen?"],"Upload SVG can be potentially risky. Are you sure?":["Das Hochladen von SVG kann potenziell riskant sein. Bist du sicher?"],"Upload Anyway":["Trotzdem hochladen"],"Bulk Add":["Massenhinzuf\u00fcgen"],"Bulk Add Options":["Optionen in gro\u00dfen Mengen hinzuf\u00fcgen"],"Enter each option on a new line.":["Geben Sie jede Option in einer neuen Zeile ein."],"Insert Options":["Optionen einf\u00fcgen"],"Full Width":["Volle Breite"],"Option Type":["Optionstyp"],"Edit Options":["Optionen bearbeiten"],"Add New Option":["Neue Option hinzuf\u00fcgen"],"ADD":["HINZUF\u00dcGEN"],"Enable Auto Country Detection":["Automatische L\u00e4nderdetektion aktivieren"],"%s Width":["%s Breite"],"Upgrade":["Aktualisieren"],"Clear":["Klar"],"Select Color":["Farbe ausw\u00e4hlen"],"Primary Color":["Prim\u00e4rfarbe"],"Text Color":["Textfarbe"],"Field Spacing":["Feldabstand"],"Small":["Klein"],"Large":["Gro\u00df"],"Left":["Links"],"Center":["Zentrum"],"Right":["Richtig"],"Color":["Farbe"],"Background Color":["Hintergrundfarbe"],"Auto":["Auto"],"Default":["Standard"],"Normal":["Normal"],"%":["%"],"Top":["Oben"],"Bottom":["Unten"],"Width":["Breite"],"Size":["Gr\u00f6\u00dfe"],"EM":["EM"],"Padding":["Polsterung"],"Color 1":["Farbe 1"],"Color 2":["Farbe 2"],"Type":["Typ"],"Linear":["Linear"],"Radial":["Radial"],"Location 1":["Standort 1"],"Location 2":["Standort 2"],"Angle":["Winkel"],"Classic":["Klassisch"],"Gradient":["Gradient"],"Horizontal":["Horizontal"],"Vertical":["Vertikal"],"Background":["Hintergrund"],"Cover":["Abdeckung"],"Contain":["Enthalten"],"Layout":["Layout"],"Overlay":["\u00dcberlagerung"],"No Repeat":["Keine Wiederholung"],"Overlay Opacity":["\u00dcberlagerungsdeckkraft"],"Conditional Logic":["Bedingte Logik"],"Upgrade to the SureForms Starter Plan to create dynamic forms that adapt based on user input, offering a personalised and efficient form experience.":["Wechseln Sie zum SureForms Starter-Plan, um dynamische Formulare zu erstellen, die sich basierend auf Benutzereingaben anpassen und ein personalisiertes und effizientes Formularerlebnis bieten."],"Enable Conditional Logic":["Bedingte Logik aktivieren"],"this field if":["dieses Feld, wenn"],"Configure Conditions":["Bedingungen konfigurieren"],"Premium":["Premium"],"Overlay Type":["Overlay-Typ"],"Image Overlay Color":["Bild\u00fcberlagerungsfarbe"],"Image Position":["Bildposition"],"Attachment":["Anhang"],"Fixed":["Fest"],"Blend Mode":["Mischmodus"],"Multiply":["Multiplizieren"],"Screen":["Bildschirm"],"Darken":["Verdunkeln"],"Lighten":["Erleichtern"],"Color Dodge":["Farb-Abwedeln"],"Saturation":["S\u00e4ttigung"],"Repeat-x":["Wiederholen-x"],"Repeat-y":["Wiederhole-y"],"PX":["PX"],"Button":["Schaltfl\u00e4che"],"Prefix Label":["Pr\u00e4fix-Label"],"Suffix Label":["Suffix-Label"],"Border Radius":["Randradius"],"Form Theme":["Formular-Thema"],"Select Gradient":["Gradient ausw\u00e4hlen"],"Unlock Conditional Logic Editor":["Conditional Logic Editor entsperren"],"Rich Text Editor":["Rich-Text-Editor"],"Read Only":["Nur Lesen"],"Select Country":["Land ausw\u00e4hlen"],"Default Country":["Standardland"],"Subscription":["Abonnement"],"One Time":["Einmal"],"Unique Entry":["Einzigartiger Eintrag"],"Maximum Characters":["Maximale Zeichen"],"Textarea Height":["Textbereichsh\u00f6he"],"Minimum Selections":["Mindestanzahl an Auswahlen"],"Maximum Selections":["Maximale Auswahlen"],"Add Numeric Values to Options":["F\u00fcgen Sie numerische Werte zu Optionen hinzu"],"Single Choice Only":["Nur eine Auswahl m\u00f6glich"],"Enable Dropdown Search":["Dropdown-Suche aktivieren"],"Allow Multiple":["Mehrfach erlauben"],"%1$s fields are required. Please configure these fields in the block settings.":["%1$s Felder sind erforderlich. Bitte konfigurieren Sie diese Felder in den Blockeinstellungen."],"%1$s field is required. Please configure this field in the block settings.":["%1$s Feld ist erforderlich. Bitte konfigurieren Sie dieses Feld in den Blockeinstellungen."],"You need to configure a payment account to collect payments from this form. Please configure your payment provider to proceed.":["Sie m\u00fcssen ein Zahlungskonto einrichten, um Zahlungen \u00fcber dieses Formular zu sammeln. Bitte konfigurieren Sie Ihren Zahlungsanbieter, um fortzufahren."],"Configure Payment Account":["Zahlungskonto konfigurieren"],"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.":["Dies ist ein Platzhalter f\u00fcr den Zahlungsblock. Die tats\u00e4chlichen Zahlungsfelder f\u00fcr Ihre konfigurierten Zahlungsanbieter werden nur angezeigt, wenn Sie das Formular in der Vorschau anzeigen oder ver\u00f6ffentlichen."],"2 Payments":["2 Zahlungen"],"3 Payments":["3 Zahlungen"],"4 Payments":["4 Zahlungen"],"5 Payments":["5 Zahlungen"],"Never":["Niemals"],"Stop Subscription After":["Abonnement beenden nach"],"Choose when to automatically stop the subscription":["W\u00e4hlen Sie, wann das Abonnement automatisch beendet werden soll"],"Number of Payments":["Anzahl der Zahlungen"],"Enter a number between 1 to 100":["Geben Sie eine Zahl zwischen 1 und 100 ein"],"Form Field":["Formularfeld"],"Payment Type":["Zahlungsart"],"Subscription Plan Name":["Abonnementplanname"],"Billing Interval":["Abrechnungsintervall"],"Daily":["T\u00e4glich"],"Weekly":["W\u00f6chentlich"],"Monthly":["Monatlich"],"Quarterly":["Viertelj\u00e4hrlich"],"Yearly":["J\u00e4hrlich"],"Amount Type":["Betragstyp"],"Fixed Amount":["Fester Betrag"],"Dynamic Amount":["Dynamischer Betrag"],"Choose whether to charge a fixed amount or charge the amount based on user input in other form fields.":["W\u00e4hlen Sie, ob ein fester Betrag berechnet werden soll oder ob der Betrag basierend auf Benutzereingaben in anderen Formularfeldern berechnet werden soll."],"Set the exact amount you want to charge. Users won\u2019t be able to change it":["Legen Sie den genauen Betrag fest, den Sie berechnen m\u00f6chten. Benutzer k\u00f6nnen ihn nicht \u00e4ndern"],"Choose Amount Field":["Betragsfeld ausw\u00e4hlen"],"Select a field\u2026":["W\u00e4hlen Sie ein Feld aus\u2026"],"Minimum Amount":["Mindestbetrag"],"Set the minimum amount users can enter (0 for no minimum)":["Legen Sie den Mindestbetrag fest, den Benutzer eingeben k\u00f6nnen (0 f\u00fcr kein Minimum)"],"Customer Name Field (Required)":["Kundenname-Feld (erforderlich)"],"Customer Name Field (Optional)":["Kundenname-Feld (Optional)"],"Select the input field that contains the customer name (Required for subscriptions)":["W\u00e4hlen Sie das Eingabefeld aus, das den Kundennamen enth\u00e4lt (Erforderlich f\u00fcr Abonnements)"],"Select the input field that contains the customer name":["W\u00e4hlen Sie das Eingabefeld aus, das den Kundennamen enth\u00e4lt"],"Customer Email Field (Required)":["Kunden-E-Mail-Feld (erforderlich)"],"Select the email field that contains the customer email":["W\u00e4hlen Sie das E-Mail-Feld aus, das die Kunden-E-Mail enth\u00e4lt"],"Payment":["Zahlung"],"%s - Order ID":["%s - Bestell-ID"],"%s - Amount":["%s - Betrag"],"%s - Customer Email":["%s - Kunden-E-Mail"],"%s - Customer Name":["%s - Kundenname"],"%s - Status":["%s - Status"],"Button Alignment":["Schaltfl\u00e4chenanordnung"],"Placeholder":["Platzhalter"],"Preselect this option":["Diese Option vorausw\u00e4hlen"],"Restrict Country Codes":["L\u00e4ndercodes einschr\u00e4nken"],"Restriction Type":["Einschr\u00e4nkungstyp"],"Allow":["Erlauben"],"Block":["Blockieren"],"Select Allowed Countries":["Zul\u00e4ssige L\u00e4nder ausw\u00e4hlen"],"Choose countries\u2026":["L\u00e4nder ausw\u00e4hlen\u2026"],"Choose which country codes users can select in the phone number field. Leave empty to allow all country codes.":["W\u00e4hlen Sie aus, welche L\u00e4ndercodes Benutzer im Telefonnummernfeld ausw\u00e4hlen k\u00f6nnen. Lassen Sie das Feld leer, um alle L\u00e4ndercodes zuzulassen."],"Select Blocked Countries":["Gesperrte L\u00e4nder ausw\u00e4hlen"],"These countries will be hidden from the dropdown.":["Diese L\u00e4nder werden im Dropdown-Men\u00fc ausgeblendet."],"Bulk Edit":["Massenbearbeitung"],"Select Layout":["Layout ausw\u00e4hlen"],"Number of Columns":["Anzahl der Spalten"],"Validation Message for Duplicate":["Validierungsnachricht f\u00fcr Duplikat"],"Click here to insert a form":["Klicken Sie hier, um ein Formular einzuf\u00fcgen"],"Inherit Form's Original Style":["Urspr\u00fcnglichen Stil des Formulars \u00fcbernehmen"],"Text on Primary":["Text auf Prim\u00e4r"],"%s - Description":["%s - Beschreibung"],"Upgrade to Unlock":["Upgrade zum Freischalten"],"Custom (Premium)":["Benutzerdefiniert (Premium)"],"Select a theme style for this form embed.":["W\u00e4hlen Sie einen Themenstil f\u00fcr dieses Formulareinbettung aus."],"Colors":["Farben"],"Advanced Styling":["Erweitertes Styling"],"Unlock Custom Styling":["Benutzerdefinierte Gestaltung freischalten"],"Switch to Custom Mode to take full control of your form's design and spacing.":["Wechseln Sie in den benutzerdefinierten Modus, um die volle Kontrolle \u00fcber das Design und den Abstand Ihres Formulars zu \u00fcbernehmen."],"Full color control (buttons, fields, text)":["Volle Farbkontrolle (Schaltfl\u00e4chen, Felder, Text)"],"Row and column gap control":["Steuerung von Zeilen- und Spaltenabst\u00e4nden"],"Field spacing and layout precision":["Feldabst\u00e4nde und Layoutpr\u00e4zision"],"Complete button styling":["Komplette Schaltfl\u00e4chen-Stilgestaltung"],"Payment Description":["Zahlungsbeschreibung"],"Shown on payment receipts and in your payment dashboard (Stripe and PayPal). Leave blank to use the default.":["Auf Zahlungsbelegen und in Ihrem Zahlungs-Dashboard (Stripe und PayPal) angezeigt. Leer lassen, um den Standard zu verwenden."],"Slug":["Schnecke"],"Auto-generated on save":["Automatisch beim Speichern generiert"],"This slug is already used by another field. It will revert to the previous value.":["Dieser Slug wird bereits von einem anderen Feld verwendet. Er wird auf den vorherigen Wert zur\u00fcckgesetzt."],"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.":["Das \u00c4ndern des Slugs kann Formular\u00fcbermittlungen, bedingte Logik, Integrationen oder andere Funktionen, die derzeit auf diesen Slug verweisen, beeintr\u00e4chtigen. Sie m\u00fcssen alle derartigen Verweise manuell aktualisieren."],"Field Slug":["Feld-Slug"],"Location Services":["Standortdienste"],"Unlock Address Autocomplete":["Adresse-Autovervollst\u00e4ndigung freischalten"],"Upgrade to enable Google Address Autocomplete with interactive map preview, making address entry faster and more accurate for your users.":["Upgrade, um die Google Address Autocomplete-Funktion mit interaktiver Kartenansicht zu aktivieren, wodurch die Adresseingabe f\u00fcr Ihre Nutzer schneller und genauer wird."],"Enable Google Autocomplete":["Google Autovervollst\u00e4ndigung aktivieren"],"Show Interactive Map":["Interaktive Karte anzeigen"],"Payments Per Page":["Zahlungen pro Seite"],"Show Subscriptions Section":["Abonnement-Bereich anzeigen"],"Show a dedicated subscriptions section above payment history.":["Zeige einen eigenen Abonnementbereich \u00fcber der Zahlungshistorie an."],"Payment Dashboard":["Zahlungs\u00fcbersicht"],"View your payments and manage subscriptions in a single dashboard.":["Sehen Sie Ihre Zahlungen ein und verwalten Sie Abonnements in einem einzigen Dashboard."],"Dynamic Default Value":["Dynamischer Standardwert"],"Minimum Characters":["Mindestanzahl von Zeichen"],"Minimum characters cannot exceed Maximum characters.":["Mindestanzahl an Zeichen darf die H\u00f6chstanzahl an Zeichen nicht \u00fcberschreiten."],"Both":["Beide"],"One-Time Label":["Einmaliges Etikett"],"Label shown to users for the one-time payment option.":["Beschriftung, die den Benutzern f\u00fcr die Einmalzahlungsoption angezeigt wird."],"Subscription Label":["Abonnementsetikett"],"Label shown to users for the subscription option.":["Beschriftung, die den Benutzern f\u00fcr die Abonnementoption angezeigt wird."],"Default Selection":["Standardauswahl"],"Which option is pre-selected when the form loads.":["Welche Option ist vorausgew\u00e4hlt, wenn das Formular geladen wird."],"One-Time Amount Type":["Einmaliger Betragstyp"],"Set how the one-time payment amount is determined.":["Legen Sie fest, wie der Einmalzahlungsbetrag bestimmt wird."],"One-Time Fixed Amount":["Einmaliger Festbetrag"],"Amount charged for a one-time payment.":["Betrag, der f\u00fcr eine einmalige Zahlung berechnet wird."],"One-Time Amount Field":["Einmaliger Betragsfeld"],"Pick a form field whose value determines the one-time payment amount.":["W\u00e4hlen Sie ein Formularfeld aus, dessen Wert den Einmalzahlungsbetrag bestimmt."],"One-Time Minimum Amount":["Einmaliger Mindestbetrag"],"Minimum amount users can enter for one-time payment (0 for no minimum).":["Mindestbetrag, den Benutzer f\u00fcr eine einmalige Zahlung eingeben k\u00f6nnen (0 f\u00fcr kein Minimum)."],"Subscription Amount Type":["Abonnementbetragstyp"],"Set how the subscription amount is determined.":["Legen Sie fest, wie der Abonnementbetrag bestimmt wird."],"Subscription Fixed Amount":["Abonnement Festbetrag"],"Recurring amount charged per billing interval.":["Wiederkehrender Betrag, der pro Abrechnungsintervall berechnet wird."],"Subscription Amount Field":["Feld f\u00fcr den Abonnementbetrag"],"Pick a form field whose value determines the subscription amount.":["W\u00e4hlen Sie ein Formularfeld aus, dessen Wert den Abonnementbetrag bestimmt."],"Subscription Minimum Amount":["Mindestbetrag f\u00fcr das Abonnement"],"Minimum amount users can enter for subscription (0 for no minimum).":["Mindestbetrag, den Benutzer f\u00fcr das Abonnement eingeben k\u00f6nnen (0 f\u00fcr kein Minimum)."],"Pick a field from your form like a number, dropdown, multichoice, or hidden whose value should decide the payment amount.":["W\u00e4hlen Sie ein Feld aus Ihrem Formular, wie eine Zahl, ein Dropdown-Men\u00fc, eine Mehrfachauswahl oder ein verstecktes Feld, dessen Wert den Zahlungsbetrag bestimmen soll."]}}} \ No newline at end of file diff --git a/languages/sureforms-de_DE.mo b/languages/sureforms-de_DE.mo index 8361d41a6..df1a0bde7 100644 Binary files a/languages/sureforms-de_DE.mo and b/languages/sureforms-de_DE.mo differ diff --git a/languages/sureforms-de_DE.po b/languages/sureforms-de_DE.po index 3509356fb..5040e9e4e 100644 --- a/languages/sureforms-de_DE.po +++ b/languages/sureforms-de_DE.po @@ -106,13 +106,13 @@ msgstr "%1$s bearbeiten" #: inc/ai-form-builder/ai-auth.php:93 #: inc/ai-form-builder/ai-auth.php:167 #: inc/background-process.php:112 -#: inc/create-new-form.php:101 +#: inc/create-new-form.php:102 #: inc/duplicate-form.php:176 #: inc/export.php:118 #: inc/export.php:176 #: inc/forms-data.php:88 #: inc/global-settings/global-settings.php:86 -#: inc/global-settings/global-settings.php:403 +#: inc/global-settings/global-settings.php:404 #: inc/rest-api.php:177 msgid "Nonce verification failed." msgstr "Überprüfung des Nonce ist fehlgeschlagen." @@ -388,7 +388,7 @@ msgid "Selected radio option" msgstr "Ausgewählte Radiooption" #: inc/admin-ajax.php:341 -#: inc/create-new-form.php:63 +#: inc/create-new-form.php:64 #: assets/build/blocks.js:172 #: assets/build/formEditor.js:172 msgid "Submit" @@ -427,53 +427,53 @@ msgid "The message array was not supplied" msgstr "Das Nachrichtenarray wurde nicht bereitgestellt" #: inc/ai-form-builder/ai-form-builder.php:68 -#: inc/ai-form-builder/ai-form-builder.php:78 -#: inc/ai-form-builder/ai-helper.php:73 +#: inc/ai-form-builder/ai-form-builder.php:87 +#: inc/ai-form-builder/ai-helper.php:294 msgid "The SureForms AI Middleware encountered an error." msgstr "Die SureForms AI-Middleware ist auf einen Fehler gestoßen." -#: inc/ai-form-builder/ai-helper.php:95 +#: inc/ai-form-builder/ai-helper.php:91 msgid "Unable to get usage response." msgstr "Antwort zur Nutzung konnte nicht abgerufen werden." -#: inc/ai-form-builder/ai-helper.php:148 +#: inc/ai-form-builder/ai-helper.php:145 msgid "The SureForms API server encountered an error." msgstr "Der SureForms-API-Server hat einen Fehler festgestellt." -#: inc/ai-form-builder/ai-helper.php:174 -#: inc/ai-form-builder/ai-helper.php:206 +#: inc/ai-form-builder/ai-helper.php:167 +#: inc/ai-form-builder/ai-helper.php:199 msgid "An unknown error occurred." msgstr "Ein unbekannter Fehler ist aufgetreten." -#: inc/ai-form-builder/ai-helper.php:181 +#: inc/ai-form-builder/ai-helper.php:174 msgid "HTTP Request Failed" msgstr "HTTP-Anfrage fehlgeschlagen" -#: inc/ai-form-builder/ai-helper.php:185 +#: inc/ai-form-builder/ai-helper.php:178 msgid "License Verification Failed" msgstr "Lizenzüberprüfung fehlgeschlagen" -#: inc/ai-form-builder/ai-helper.php:189 +#: inc/ai-form-builder/ai-helper.php:182 msgid "User Verification Failed" msgstr "Benutzerüberprüfung fehlgeschlagen" -#: inc/ai-form-builder/ai-helper.php:193 +#: inc/ai-form-builder/ai-helper.php:186 msgid "Referer Mismatch" msgstr "Referer stimmt nicht überein" -#: inc/ai-form-builder/ai-helper.php:197 +#: inc/ai-form-builder/ai-helper.php:190 msgid "Invalid Website URL" msgstr "Ungültige Website-URL" -#: inc/ai-form-builder/ai-helper.php:198 +#: inc/ai-form-builder/ai-helper.php:191 msgid "AI Form Builder does not work on localhost. Please try on a live website." msgstr "AI Form Builder funktioniert nicht auf localhost. Bitte versuchen Sie es auf einer Live-Website." -#: inc/ai-form-builder/ai-helper.php:201 +#: inc/ai-form-builder/ai-helper.php:194 msgid "Domain Verification Failed" msgstr "Domain-Verifizierung fehlgeschlagen" -#: inc/ai-form-builder/ai-helper.php:205 +#: inc/ai-form-builder/ai-helper.php:198 msgid "Unknown Error" msgstr "Unbekannter Fehler" @@ -481,22 +481,18 @@ msgstr "Unbekannter Fehler" msgid "Submission id missing." msgstr "Übermittlungs-ID fehlt." -#: inc/create-new-form.php:113 +#: inc/create-new-form.php:114 msgid "Invalid JSON format." msgstr "Ungültiges JSON-Format." -#: inc/create-new-form.php:125 +#: inc/create-new-form.php:126 msgid "Missing required properties in form info." msgstr "Fehlende erforderliche Eigenschaften in den Formularinformationen." -#: inc/create-new-form.php:161 +#: inc/create-new-form.php:187 msgid "SureForms Form created successfully." msgstr "SureForms-Formular erfolgreich erstellt." -#: inc/create-new-form.php:168 -msgid "Error creating SureForms Form, " -msgstr "Fehler beim Erstellen des SureForms-Formulars," - #: inc/email/email-template.php:46 msgid "New form submission" msgstr "Neue Formularübermittlung" @@ -558,7 +554,7 @@ msgstr "Zahl" msgid "Phone" msgstr "Telefon" -#: inc/fields/textarea-markup.php:95 +#: inc/fields/textarea-markup.php:111 msgid "Textarea" msgstr "Textbereich" @@ -601,8 +597,8 @@ msgstr "Keine Formulare gefunden." #: inc/abilities/settings/get-global-settings.php:192 #: inc/global-settings/email-summary.php:571 -#: inc/global-settings/global-settings.php:250 -#: inc/global-settings/global-settings.php:456 +#: inc/global-settings/global-settings.php:251 +#: inc/global-settings/global-settings.php:457 #: assets/build/settings.js:172 msgid "Monday" msgstr "Montag" @@ -7005,7 +7001,7 @@ msgstr "Street View" msgid "Strikethrough" msgstr "Durchgestrichen" -#: inc/fields/payment-markup.php:412 +#: inc/fields/payment-markup.php:513 #: modules/gutenberg/icons/icons-v6-3.php:1812 #: assets/build/payments.js:172 msgid "Stripe" @@ -11593,6 +11589,7 @@ msgstr "Erstellen Sie Ihr erstes Formular" msgid "Invalid nonce action or name." msgstr "Ungültige Nonce-Aktion oder -Name." +#: inc/admin/editor-nudge.php:216 #: inc/helper.php:2029 #: inc/helper.php:2037 msgid "Invalid security token." @@ -11776,7 +11773,7 @@ msgstr "Erkunde SureDash" msgid "Something went wrong. We have logged the error for further investigation" msgstr "Etwas ist schiefgelaufen. Wir haben den Fehler zur weiteren Untersuchung protokolliert." -#: inc/field-validation.php:273 +#: inc/field-validation.php:276 msgid "Field is not valid." msgstr "Feld ist nicht gültig." @@ -11934,82 +11931,82 @@ msgstr "Keine Formulardaten für den Import bereitgestellt." msgid "Invalid form data structure provided." msgstr "Ungültige Formular-Datenstruktur bereitgestellt." -#: inc/fields/payment-markup.php:249 +#: inc/fields/payment-markup.php:346 #: inc/payments/payment-helper.php:543 msgid "Subscription Plan" msgstr "Abonnementplan" #. translators: 1: Amount with currency, 2: Interval (day/week/month/quarter/year) -#: inc/fields/payment-markup.php:288 +#: inc/fields/payment-markup.php:672 #, php-format msgid "%1$s per %2$s (until cancelled)" msgstr "%1$s pro %2$s (bis zur Kündigung)" #. translators: 1: Amount with currency, 2: Interval (day/week/month/quarter/year), 3: Number of billing cycles -#: inc/fields/payment-markup.php:297 +#: inc/fields/payment-markup.php:681 #, php-format msgid "%1$s per %2$s (%3$s payments)" msgstr "%1$s pro %2$s (%3$s Zahlungen)" #. translators: 1: Amount with currency, 2: Interval (day/week/month/quarter/year) -#: inc/fields/payment-markup.php:307 +#: inc/fields/payment-markup.php:691 #, php-format msgid "%1$s per %2$s" msgstr "%1$s pro %2$s" #. translators: 1: Amount with currency placeholder, 2: Interval (day/week/month/quarter/year) -#: inc/fields/payment-markup.php:334 +#: inc/fields/payment-markup.php:714 #, php-format msgid "{amount} per %s (until cancelled)" msgstr "{amount} pro %s (bis zur Kündigung)" #. translators: 1: Amount with currency placeholder, 2: Interval (day/week/month/quarter/year), 3: Number of billing cycles -#: inc/fields/payment-markup.php:337 +#: inc/fields/payment-markup.php:717 #, php-format msgid "{amount} per %1$s (%2$s payments)" msgstr "{amount} pro %1$s (%2$s Zahlungen)" #. translators: 1: Amount with currency placeholder, 2: Interval (day/week/month/quarter/year) -#: inc/fields/payment-markup.php:340 +#: inc/fields/payment-markup.php:720 #, php-format msgid "{amount} per %s" msgstr "{amount} pro %s" #. translators: %s: Minimum amount with currency -#: inc/fields/payment-markup.php:353 +#: inc/fields/payment-markup.php:740 #, php-format msgid "Minimum amount: %s" msgstr "Mindestbetrag: %s" -#: inc/fields/payment-markup.php:385 +#: inc/fields/payment-markup.php:486 msgid "Processing payment..." msgstr "Zahlung wird verarbeitet..." -#: inc/fields/payment-markup.php:579 +#: inc/fields/payment-markup.php:906 msgid "day" msgstr "Tag" -#: inc/fields/payment-markup.php:580 +#: inc/fields/payment-markup.php:907 msgid "week" msgstr "Woche" -#: inc/fields/payment-markup.php:581 +#: inc/fields/payment-markup.php:908 msgid "month" msgstr "Monat" -#: inc/fields/payment-markup.php:582 +#: inc/fields/payment-markup.php:909 msgid "quarter" msgstr "Viertel" -#: inc/fields/payment-markup.php:583 +#: inc/fields/payment-markup.php:910 msgid "year" msgstr "Jahr" -#: inc/fields/payment-markup.php:608 +#: inc/fields/payment-markup.php:935 msgid "Test mode is enabled:" msgstr "Der Testmodus ist aktiviert:" -#: inc/fields/payment-markup.php:610 +#: inc/fields/payment-markup.php:937 msgid "Click here to enable live mode and accept payment" msgstr "Klicken Sie hier, um den Live-Modus zu aktivieren und Zahlungen zu akzeptieren" @@ -12192,6 +12189,7 @@ msgstr "Unbekanntes Formular" msgid "N/A" msgstr "N/V" +#: inc/fields/payment-markup.php:247 #: inc/payments/admin/admin-handler.php:975 #: inc/payments/payment-history-shortcode.php:306 #: assets/build/blocks.js:172 @@ -12220,21 +12218,21 @@ msgstr "Unbekannt" #: inc/payments/admin/admin-handler.php:1468 #: inc/payments/admin/admin-handler.php:1472 #: inc/payments/admin/admin-handler.php:1476 -#: inc/payments/front-end.php:811 -#: inc/payments/front-end.php:1209 +#: inc/payments/front-end.php:854 +#: inc/payments/front-end.php:1253 msgid "Guest User" msgstr "Gastbenutzer" -#: inc/payments/front-end.php:91 +#: inc/payments/front-end.php:92 msgid "Invalid payment amount." msgstr "Ungültiger Zahlungsbetrag." -#: inc/payments/front-end.php:107 +#: inc/payments/front-end.php:109 msgid "Valid customer email is required for payments." msgstr "Eine gültige Kunden-E-Mail ist für Zahlungen erforderlich." -#: inc/payments/front-end.php:113 -#: inc/payments/front-end.php:320 +#: inc/payments/front-end.php:115 +#: inc/payments/front-end.php:340 #: inc/payments/stripe/admin-stripe-handler.php:877 #: inc/payments/stripe/payments-settings.php:349 #: inc/payments/stripe/payments-settings.php:474 @@ -12244,137 +12242,137 @@ msgstr "Eine gültige Kunden-E-Mail ist für Zahlungen erforderlich." msgid "Stripe is not connected." msgstr "Stripe ist nicht verbunden." -#: inc/payments/front-end.php:119 -#: inc/payments/front-end.php:326 -#: inc/payments/front-end.php:610 -#: inc/payments/front-end.php:1099 +#: inc/payments/front-end.php:121 +#: inc/payments/front-end.php:346 +#: inc/payments/front-end.php:634 +#: inc/payments/front-end.php:1142 msgid "Stripe secret key not found." msgstr "Stripe-Geheimschlüssel nicht gefunden." #. translators: %s: formatted payment amount -#: inc/payments/front-end.php:201 +#: inc/payments/front-end.php:203 #, php-format msgid "The payment amount (%s) is below the minimum allowed. Stripe only processes amounts above 50¢." msgstr "Der Zahlungsbetrag (%s) liegt unter dem zulässigen Minimum. Stripe verarbeitet nur Beträge über 50¢." #. translators: %s: Field name -#: inc/payments/front-end.php:268 +#: inc/payments/front-end.php:273 #, php-format msgid "Missing required field: %s" msgstr "Fehlendes erforderliches Feld: %s" -#: inc/payments/front-end.php:287 +#: inc/payments/front-end.php:292 msgid "Valid customer email is required for subscriptions." msgstr "Eine gültige Kunden-E-Mail ist für Abonnements erforderlich." -#: inc/payments/front-end.php:292 +#: inc/payments/front-end.php:297 msgid "Customer name is required for subscriptions." msgstr "Der Name des Kunden ist für Abonnements erforderlich." -#: inc/payments/front-end.php:308 +#: inc/payments/front-end.php:314 msgid "Amount must be greater than 0" msgstr "Betrag muss größer als 0 sein" -#: inc/payments/front-end.php:314 +#: inc/payments/front-end.php:322 msgid "Invalid billing interval" msgstr "Ungültiges Abrechnungsintervall" -#: inc/payments/front-end.php:337 +#: inc/payments/front-end.php:357 msgid "Failed to create customer for subscription." msgstr "Erstellung des Kunden für das Abonnement fehlgeschlagen." -#: inc/payments/front-end.php:370 -#: inc/payments/front-end.php:386 +#: inc/payments/front-end.php:390 +#: inc/payments/front-end.php:406 msgid "Failed to create subscription through middleware." msgstr "Fehler beim Erstellen des Abonnements über die Middleware." -#: inc/payments/front-end.php:391 +#: inc/payments/front-end.php:411 msgid "Empty response from subscription creation." msgstr "Leere Antwort von der Abonnementerstellung." -#: inc/payments/front-end.php:396 +#: inc/payments/front-end.php:416 msgid "Invalid JSON response from subscription creation." msgstr "Ungültige JSON-Antwort von der Abonnementerstellung." -#: inc/payments/front-end.php:400 -#: inc/payments/front-end.php:404 +#: inc/payments/front-end.php:420 +#: inc/payments/front-end.php:424 msgid "Invalid subscription data." msgstr "Ungültige Abonnementdaten." -#: inc/payments/front-end.php:411 +#: inc/payments/front-end.php:431 msgid "Failed to create subscription." msgstr "Erstellung des Abonnements fehlgeschlagen." #. translators: %s: Error message -#: inc/payments/front-end.php:441 +#: inc/payments/front-end.php:464 #, php-format msgid "Unexpected error: %s" msgstr "Unerwarteter Fehler: %s" -#: inc/payments/front-end.php:581 +#: inc/payments/front-end.php:604 #: inc/payments/stripe/admin-stripe-handler.php:103 #: inc/payments/stripe/admin-stripe-handler.php:184 #: inc/payments/stripe/admin-stripe-handler.php:489 msgid "Subscription ID not found." msgstr "Abonnement-ID nicht gefunden." -#: inc/payments/front-end.php:599 +#: inc/payments/front-end.php:623 msgid "Customer ID not found for the payment." msgstr "Kunden-ID für die Zahlung nicht gefunden." -#: inc/payments/front-end.php:627 +#: inc/payments/front-end.php:651 msgid "Failed to retrieve setup intent." msgstr "Fehler beim Abrufen der Einrichtungsvorgabe." -#: inc/payments/front-end.php:656 +#: inc/payments/front-end.php:699 msgid "Failed to update subscription." msgstr "Aktualisierung des Abonnements fehlgeschlagen." -#: inc/payments/front-end.php:664 +#: inc/payments/front-end.php:707 msgid "Latest invoice not found on subscription." msgstr "Neueste Rechnung im Abonnement nicht gefunden." -#: inc/payments/front-end.php:677 +#: inc/payments/front-end.php:720 msgid "Failed to retrieve invoice." msgstr "Rechnung konnte nicht abgerufen werden." -#: inc/payments/front-end.php:699 +#: inc/payments/front-end.php:742 msgid "Payment intent not found on invoice." msgstr "Zahlungsabsicht auf der Rechnung nicht gefunden." -#: inc/payments/front-end.php:714 +#: inc/payments/front-end.php:757 msgid "Failed to confirm payment." msgstr "Zahlung konnte nicht bestätigt werden." -#: inc/payments/front-end.php:730 +#: inc/payments/front-end.php:773 msgid "Failed to retrieve subscription." msgstr "Abonnement konnte nicht abgerufen werden." -#: inc/payments/front-end.php:745 +#: inc/payments/front-end.php:788 msgid "Subscription not found for the payment." msgstr "Abonnement für die Zahlung nicht gefunden." #. translators: %d: User ID -#: inc/payments/front-end.php:809 -#: inc/payments/front-end.php:1209 +#: inc/payments/front-end.php:852 +#: inc/payments/front-end.php:1253 #, php-format msgid "User ID: %d" msgstr "Benutzer-ID: %d" #. translators: %s: Invoice status -#: inc/payments/front-end.php:817 +#: inc/payments/front-end.php:860 #, php-format msgid "Invoice Status: %s" msgstr "Rechnungsstatus: %s" #. translators: Title for subscription verification log -#: inc/payments/front-end.php:824 +#: inc/payments/front-end.php:867 msgid "Subscription Verification" msgstr "Abonnement-Verifizierung" #. translators: %s: Subscription ID #. translators: %s: Stripe subscription ID -#: inc/payments/front-end.php:828 +#: inc/payments/front-end.php:871 #: inc/payments/stripe/admin-stripe-handler.php:119 #: inc/payments/stripe/admin-stripe-handler.php:204 #: inc/payments/stripe/admin-stripe-handler.php:505 @@ -12390,8 +12388,8 @@ msgstr "Abonnement-ID: %s" #. 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:830 -#: inc/payments/front-end.php:1220 +#: inc/payments/front-end.php:873 +#: inc/payments/front-end.php:1264 #: inc/payments/stripe/admin-stripe-handler.php:124 #: inc/payments/stripe/admin-stripe-handler.php:209 #: inc/payments/stripe/admin-stripe-handler.php:510 @@ -12406,13 +12404,13 @@ msgid "Payment Gateway: %s" msgstr "Zahlungs-Gateway: %s" #. translators: %s: Payment Intent ID -#: inc/payments/front-end.php:832 +#: inc/payments/front-end.php:875 #, php-format msgid "Payment Intent ID: %s" msgstr "Zahlungsabsichts-ID: %s" #. translators: %s: Charge ID -#: inc/payments/front-end.php:834 +#: inc/payments/front-end.php:877 #: inc/payments/stripe/stripe-webhook.php:1048 #, php-format msgid "Charge ID: %s" @@ -12420,7 +12418,7 @@ msgstr "Charge-ID: %s" #. translators: %s: Subscription Status #. translators: %s: subscription status -#: inc/payments/front-end.php:836 +#: inc/payments/front-end.php:879 #: inc/payments/stripe/admin-stripe-handler.php:129 #: inc/payments/stripe/admin-stripe-handler.php:214 #: inc/payments/stripe/admin-stripe-handler.php:515 @@ -12429,7 +12427,7 @@ msgid "Subscription Status: %s" msgstr "Abonnementstatus: %s" #. translators: %s: Customer ID -#: inc/payments/front-end.php:838 +#: inc/payments/front-end.php:881 #: inc/payments/stripe/stripe-webhook.php:1122 #, php-format msgid "Customer ID: %s" @@ -12437,8 +12435,8 @@ msgstr "Kunden-ID: %s" #. translators: 1: Amount, 2: Currency #. translators: %1$s: amount, %2$s: currency. -#: inc/payments/front-end.php:840 -#: inc/payments/front-end.php:1222 +#: inc/payments/front-end.php:883 +#: inc/payments/front-end.php:1266 #: inc/payments/stripe/stripe-webhook.php:1053 #: inc/payments/stripe/stripe-webhook.php:1114 #, php-format @@ -12447,34 +12445,34 @@ msgstr "Betrag: %1$s %2$s" #. translators: %s: Payment mode (e.g. Live or Test) #. translators: %s: payment mode -#: inc/payments/front-end.php:843 -#: inc/payments/front-end.php:1227 +#: inc/payments/front-end.php:886 +#: inc/payments/front-end.php:1271 #, php-format msgid "Mode: %s" msgstr "Modus: %s" -#: inc/payments/front-end.php:877 +#: inc/payments/front-end.php:920 msgid "Failed to verify subscription." msgstr "Überprüfung des Abonnements fehlgeschlagen." -#: inc/payments/front-end.php:1131 -#: inc/payments/front-end.php:1149 -#: inc/payments/front-end.php:1157 -#: inc/payments/front-end.php:1164 +#: inc/payments/front-end.php:1175 +#: inc/payments/front-end.php:1193 +#: inc/payments/front-end.php:1201 +#: inc/payments/front-end.php:1208 msgid "Failed to retrieve payment intent." msgstr "Fehler beim Abrufen des Zahlungsziels." -#: inc/payments/front-end.php:1172 +#: inc/payments/front-end.php:1216 msgid "Payment was not confirmed successfully." msgstr "Die Zahlung wurde nicht erfolgreich bestätigt." -#: inc/payments/front-end.php:1214 +#: inc/payments/front-end.php:1258 msgid "Payment Verification" msgstr "Zahlungsüberprüfung" #. translators: %s: Stripe transaction ID #. translators: %s: Charge ID -#: inc/payments/front-end.php:1218 +#: inc/payments/front-end.php:1262 #: inc/payments/stripe/stripe-webhook.php:1110 #, php-format msgid "Transaction ID: %s" @@ -12482,18 +12480,18 @@ msgstr "Transaktions-ID: %s" #. translators: %s: payment status #. translators: %s: Status -#: inc/payments/front-end.php:1224 +#: inc/payments/front-end.php:1268 #: inc/payments/stripe/stripe-webhook.php:576 #: inc/payments/stripe/stripe-webhook.php:1116 #, php-format msgid "Status: %s" msgstr "Status: %s" -#: inc/payments/front-end.php:1330 +#: inc/payments/front-end.php:1374 msgid "Failed to create Stripe customer." msgstr "Erstellung des Stripe-Kunden fehlgeschlagen." -#: inc/payments/front-end.php:1394 +#: inc/payments/front-end.php:1438 msgid "Failed to create Stripe guest customer." msgstr "Erstellung des Stripe-Gastkunden fehlgeschlagen." @@ -12856,6 +12854,7 @@ msgstr "Unbekannter Fehler" msgid "Missing payment ID." msgstr "Fehlende Zahlungs-ID." +#: inc/admin/editor-nudge.php:209 #: inc/payments/stripe/admin-stripe-handler.php:84 #: inc/payments/stripe/admin-stripe-handler.php:470 msgid "You are not allowed to perform this action." @@ -13535,10 +13534,6 @@ msgstr "Betragsfeld auswählen" msgid "Select a field…" msgstr "Wählen Sie ein Feld aus…" -#: assets/build/blocks.js:172 -msgid "Pick a field from your form like a number, dropdown, or multichoice whose value should decide the payment amount." -msgstr "Wählen Sie ein Feld aus Ihrem Formular, wie eine Zahl, ein Dropdown-Menü oder eine Mehrfachauswahl, dessen Wert den Zahlungsbetrag bestimmen soll." - #: assets/build/blocks.js:172 msgid "Minimum Amount" msgstr "Mindestbetrag" @@ -14118,6 +14113,7 @@ msgstr "Verwenden Sie KI, um Formulare sofort aus einem einfachen Prompt zu erst msgid "Build engaging conversational, calculation, and multi-step forms." msgstr "Erstellen Sie ansprechende Konversations-, Berechnungs- und mehrstufige Formulare." +#: inc/admin/editor-nudge.php:192 #: assets/build/forms.js:172 msgid "Create Form" msgstr "Formular erstellen" @@ -14976,76 +14972,78 @@ msgstr "Der angegebene Beitrag ist kein SureForms-Formular." msgid "Failed to create duplicate form." msgstr "Erstellung des doppelten Formulars fehlgeschlagen." -#: inc/payments/front-end.php:97 -#: inc/payments/front-end.php:298 -#: inc/payments/payment-helper.php:594 +#: inc/payments/front-end.php:98 +#: inc/payments/front-end.php:303 +#: inc/payments/payment-helper.php:595 msgid "Invalid form configuration." msgstr "Ungültige Formular-Konfiguration." -#: inc/payments/payment-helper.php:602 +#: inc/payments/payment-helper.php:603 msgid "Payment configuration not found for this form." msgstr "Zahlungskonfiguration für dieses Formular nicht gefunden." #. translators: 1: expected currency, 2: received currency -#: inc/payments/payment-helper.php:613 +#: inc/payments/payment-helper.php:614 #, php-format msgid "Currency mismatch: expected %1$s, received %2$s." msgstr "Währungsabweichung: erwartet %1$s, erhalten %2$s." #. translators: 1: expected amount with currency -#: inc/payments/payment-helper.php:630 +#: inc/payments/payment-helper.php:649 #, php-format msgid "Payment amount must be exactly %1$s." msgstr "Der Zahlungsbetrag muss genau %1$s betragen." #. translators: 1: minimum amount with currency -#: inc/payments/payment-helper.php:641 +#: inc/payments/payment-helper.php:660 #, php-format msgid "Payment amount must be at least %1$s." msgstr "Der Zahlungsbetrag muss mindestens %1$s betragen." -#: inc/payments/payment-helper.php:717 +#: inc/payments/payment-helper.php:737 msgid "Invalid payment verification parameters." msgstr "Ungültige Zahlungsüberprüfungsparameter." -#: inc/payments/payment-helper.php:728 +#: inc/payments/payment-helper.php:748 msgid "Payment verification failed. Invalid payment intent." msgstr "Zahlungsüberprüfung fehlgeschlagen. Ungültige Zahlungsabsicht." -#: inc/payments/payment-helper.php:814 -#: inc/payments/payment-helper.php:952 +#: inc/payments/payment-helper.php:903 +#: inc/payments/payment-helper.php:1043 msgid "Variable amount field configuration not found." msgstr "Konfiguration des variablen Betragsfeldes nicht gefunden." -#: inc/payments/payment-helper.php:835 +#: inc/payments/payment-helper.php:924 msgid "No payment options are configured for this field." msgstr "Für dieses Feld sind keine Zahlungsoptionen konfiguriert." #. translators: %s: currency code -#: inc/payments/payment-helper.php:861 +#: inc/payments/payment-helper.php:950 msgid "Invalid payment amount. Please select a valid amount from the available options." msgstr "Ungültiger Zahlungsbetrag. Bitte wählen Sie einen gültigen Betrag aus den verfügbaren Optionen aus." #. translators: %1$s: expected amount, %2$s: payment amount -#: inc/payments/payment-helper.php:896 +#: inc/payments/payment-helper.php:986 msgid "Payment configuration not found." msgstr "Zahlungskonfiguration nicht gefunden." #. translators: %1$s: expected amount, %2$s: payment amount -#: inc/payments/payment-helper.php:912 -#: inc/payments/payment-helper.php:964 -#: inc/payments/payment-helper.php:1000 +#: inc/payments/payment-helper.php:1003 +#: inc/payments/payment-helper.php:1055 +#: inc/payments/payment-helper.php:1091 +#: inc/payments/payment-helper.php:1111 #, php-format msgid "Payment amount mismatch. Expected %1$s, received %2$s." msgstr "Zahlungsbetrag stimmt nicht überein. Erwartet %1$s, erhalten %2$s." -#: inc/payments/payment-helper.php:941 -#: inc/payments/payment-helper.php:991 +#: 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." msgstr "Der Wert des variablen Betragsfeldes ist erforderlich." #. translators: %1$s: minimum amount, %2$s: payment amount -#: inc/payments/payment-helper.php:1012 +#: inc/payments/payment-helper.php:1125 #, php-format msgid "Payment amount below minimum. Minimum: %1$s, received %2$s." msgstr "Zahlungsbetrag unter dem Minimum. Minimum: %1$s, erhalten %2$s." @@ -15107,7 +15105,7 @@ msgstr "Beim Duplizieren des Formulars ist ein Fehler aufgetreten." msgid "This will create a copy of \"%s\" with all its settings." msgstr "Dies wird eine Kopie von \"%s\" mit allen Einstellungen erstellen." -#: inc/fields/payment-markup.php:413 +#: inc/fields/payment-markup.php:514 msgid "Pay with credit or debit card" msgstr "Zahlen Sie mit Kredit- oder Debitkarte" @@ -15115,8 +15113,8 @@ msgstr "Zahlen Sie mit Kredit- oder Debitkarte" msgid "This form is not yet available. Please check back after the scheduled start time." msgstr "Dieses Formular ist noch nicht verfügbar. Bitte schauen Sie nach der geplanten Startzeit wieder vorbei." -#: inc/form-restriction.php:165 -#: inc/form-restriction.php:166 +#: inc/form-restriction.php:187 +#: inc/form-restriction.php:188 #: assets/build/formEditor.js:172 msgid "This form is no longer accepting submissions. The submission period has ended." msgstr "Dieses Formular nimmt keine Einsendungen mehr an. Die Einreichungsfrist ist abgelaufen." @@ -15131,7 +15129,7 @@ msgstr "Zahlungsgateway nicht gefunden." msgid "Refund processing is not supported for %s gateway." msgstr "Die Rückerstattungsverarbeitung wird für das %s-Gateway nicht unterstützt." -#: inc/payments/payment-helper.php:974 +#: inc/payments/payment-helper.php:1065 msgid "Number field configuration not found." msgstr "Konfiguration des Zahlenfelds nicht gefunden." @@ -15508,11 +15506,11 @@ msgstr "Der Formular-Titel ist erforderlich." msgid "At least one form field is required." msgstr "Mindestens ein Formularfeld ist erforderlich." -#: inc/abilities/forms/create-form.php:322 +#: inc/abilities/forms/create-form.php:326 msgid "Failed to generate form fields from the provided data." msgstr "Fehler beim Generieren der Formularfelder aus den bereitgestellten Daten." -#: inc/abilities/forms/create-form.php:372 +#: inc/abilities/forms/create-form.php:376 msgid "Failed to create the form." msgstr "Erstellen des Formulars fehlgeschlagen." @@ -15688,23 +15686,23 @@ msgstr "Authentifizierungssitzung abgelaufen. Bitte versuchen Sie es erneut." msgid "Invalid access key format." msgstr "Ungültiges Zugriffsschlüsselformat." -#: inc/ai-form-builder/ai-helper.php:182 +#: inc/ai-form-builder/ai-helper.php:175 msgid "Unable to connect to SureForms API. Please check your connection." msgstr "Verbindung zur SureForms-API nicht möglich. Bitte überprüfen Sie Ihre Verbindung." -#: inc/ai-form-builder/ai-helper.php:186 +#: inc/ai-form-builder/ai-helper.php:179 msgid "Unable to verify license. Please check your license key." msgstr "Lizenz konnte nicht verifiziert werden. Bitte überprüfen Sie Ihren Lizenzschlüssel." -#: inc/ai-form-builder/ai-helper.php:190 +#: inc/ai-form-builder/ai-helper.php:183 msgid "An error occurred while trying to verify your email. Please check your email you have used to log in or sign up on billing.sureforms.com." msgstr "Ein Fehler ist aufgetreten, während versucht wurde, Ihre E-Mail zu verifizieren. Bitte überprüfen Sie die E-Mail, die Sie zum Einloggen oder Registrieren auf billing.sureforms.com verwendet haben." -#: inc/ai-form-builder/ai-helper.php:194 +#: inc/ai-form-builder/ai-helper.php:187 msgid "Unable to verify referer. Please check your referer." msgstr "Referer kann nicht überprüft werden. Bitte überprüfen Sie Ihren Referer." -#: inc/ai-form-builder/ai-helper.php:202 +#: inc/ai-form-builder/ai-helper.php:195 msgid "Domain Verification Failed on current site. Please try again on another website." msgstr "Domain-Verifizierung auf der aktuellen Seite fehlgeschlagen. Bitte versuchen Sie es auf einer anderen Website erneut." @@ -15730,8 +15728,8 @@ msgstr "Ich stimme zu, dass diese Website meine Informationen speichert, damit s msgid "Text field" msgstr "Textfeld" -#: inc/form-restriction.php:160 -#: inc/form-restriction.php:161 +#: inc/form-restriction.php:182 +#: inc/form-restriction.php:183 #: inc/post-types.php:1203 #: inc/post-types.php:1243 msgid "This form is not yet available. Check back after the scheduled start time." @@ -15741,8 +15739,8 @@ msgstr "Dieses Formular ist noch nicht verfügbar. Schauen Sie nach der geplante #: inc/form-submit.php:400 #: inc/form-submit.php:445 #: inc/form-submit.php:968 -#: inc/payments/front-end.php:77 -#: inc/payments/front-end.php:258 +#: 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 @@ -16097,32 +16095,32 @@ msgid "Enter a valid email address." msgstr "Geben Sie eine gültige E-Mail-Adresse ein." #. translators: %s represents the minimum acceptable value -#: inc/translatable.php:94 +#: inc/translatable.php:97 #, php-format msgid "Minimum value is %s." msgstr "Mindestwert ist %s." #. translators: %s represents the maximum acceptable value -#: inc/translatable.php:97 +#: inc/translatable.php:100 #, php-format msgid "Maximum value is %s." msgstr "Der Höchstwert ist %s." #. translators: %s represents the minimum number of options to select -#: inc/translatable.php:100 -#: inc/translatable.php:106 +#: inc/translatable.php:103 +#: inc/translatable.php:109 #, php-format msgid "Select at least %s options." msgstr "Wählen Sie mindestens %s Optionen aus." #. translators: %s represents the maximum number of options that can be selected -#: inc/translatable.php:103 -#: inc/translatable.php:109 +#: inc/translatable.php:106 +#: inc/translatable.php:112 #, php-format msgid "You can select up to %s options." msgstr "Sie können bis zu %s Optionen auswählen." -#: inc/translatable.php:120 +#: inc/translatable.php:123 msgid "This form is now closed as we have reached the maximum number of entries." msgstr "Dieses Formular ist jetzt geschlossen, da wir die maximale Anzahl an Einträgen erreicht haben." @@ -16649,35 +16647,35 @@ msgstr "Rufen Sie die globalen Einstellungen von SureForms ab. Optional nach Kat msgid "Setting categories to retrieve. Omit for all categories." msgstr "Kategorien zum Abrufen festlegen. Auslassen für alle Kategorien." -#: inc/abilities/settings/update-global-settings.php:105 +#: inc/abilities/settings/update-global-settings.php:106 msgid "Update Global Settings" msgstr "Globale Einstellungen aktualisieren" -#: inc/abilities/settings/update-global-settings.php:106 +#: inc/abilities/settings/update-global-settings.php:107 msgid "Update SureForms global settings for a specific category: general, validation-messages, email-summary, or security." msgstr "Aktualisieren Sie die globalen Einstellungen von SureForms für eine bestimmte Kategorie: allgemein, Validierungsnachrichten, E-Mail-Zusammenfassung oder Sicherheit." -#: inc/abilities/settings/update-global-settings.php:139 +#: inc/abilities/settings/update-global-settings.php:140 msgid "The settings category to update." msgstr "Die zu aktualisierende Einstellungskategorie." -#: inc/abilities/settings/update-global-settings.php:144 +#: inc/abilities/settings/update-global-settings.php:145 msgid "Key-value pairs of settings to update." msgstr "Schlüssel-Wert-Paare von Einstellungen zum Aktualisieren." -#: inc/abilities/settings/update-global-settings.php:180 +#: inc/abilities/settings/update-global-settings.php:181 msgid "Settings category is required." msgstr "Die Einstellungskategorie ist erforderlich." -#: inc/abilities/settings/update-global-settings.php:188 +#: inc/abilities/settings/update-global-settings.php:189 msgid "Settings data is required." msgstr "Einstellungsdaten sind erforderlich." -#: inc/abilities/settings/update-global-settings.php:199 +#: inc/abilities/settings/update-global-settings.php:200 msgid "No valid settings keys provided for this category." msgstr "Für diese Kategorie wurden keine gültigen Einstellungsschlüssel bereitgestellt." -#: inc/abilities/settings/update-global-settings.php:225 +#: inc/abilities/settings/update-global-settings.php:226 msgid "Invalid settings category." msgstr "Ungültige Einstellungskategorie." @@ -17578,6 +17576,212 @@ msgstr "Polnischer Złoty" msgid "Dynamic Default Value" msgstr "Dynamischer Standardwert" +#: inc/admin/editor-nudge.php:191 +msgid "Hey! It looks like you're creating a form. Build a ready-to-use form in under 30 seconds with SureForms AI, with no extra setup required." +msgstr "Hey! Es sieht so aus, als würdest du ein Formular erstellen. Erstelle ein einsatzbereites Formular in weniger als 30 Sekunden mit SureForms AI, ohne zusätzlichen Aufwand." + +#: inc/admin/editor-nudge.php:228 +#: inc/admin/editor-nudge.php:237 +msgid "Invalid post." +msgstr "Ungültiger Beitrag." + +#: inc/admin/editor-nudge.php:246 +msgid "You cannot edit this post." +msgstr "Sie können diesen Beitrag nicht bearbeiten." + +#: inc/ai-form-builder/ai-form-builder.php:96 +msgid "The AI did not return a form. Please refine your prompt and try again." +msgstr "Die KI hat kein Formular zurückgegeben. Bitte verfeinern Sie Ihre Eingabeaufforderung und versuchen Sie es erneut." + +#: inc/ai-form-builder/ai-form-builder.php:104 +msgid "The AI response is missing a form title. Please try again." +msgstr "Die KI-Antwort fehlt ein Formular-Titel. Bitte versuchen Sie es erneut." + +#: inc/ai-form-builder/ai-form-builder.php:115 +#: inc/ai-form-builder/field-mapping.php:69 +msgid "The AI was unable to generate form fields. Please try again." +msgstr "Die KI konnte keine Formularfelder generieren. Bitte versuchen Sie es erneut." + +#: inc/ai-form-builder/field-mapping.php:41 +msgid "The AI form data is missing. Please try again." +msgstr "Die AI-Formulardaten fehlen. Bitte versuchen Sie es erneut." + +#: inc/ai-form-builder/field-mapping.php:51 +msgid "The AI form data is not in the expected format." +msgstr "Die AI-Formulardaten sind nicht im erwarteten Format." + +#: inc/ai-form-builder/field-mapping.php:60 +msgid "The AI response did not include a form. Please try again." +msgstr "Die KI-Antwort enthielt kein Formular. Bitte versuchen Sie es erneut." + +#: inc/ai-form-builder/field-mapping.php:90 +msgid "The AI returned a malformed form field. Please try again." +msgstr "Die KI hat ein fehlerhaftes Formularfeld zurückgegeben. Bitte versuchen Sie es erneut." + +#: inc/create-new-form.php:160 +#: inc/create-new-form.php:173 +msgid "Error creating SureForms Form." +msgstr "Fehler beim Erstellen des SureForms-Formulars." + +#. translators: %s represents the minimum number of characters required +#: inc/field-validation.php:289 +#: inc/translatable.php:94 +#, php-format +msgid "Please enter at least %s characters." +msgstr "Bitte geben Sie mindestens %s Zeichen ein." + +#: inc/fields/payment-markup.php:246 +msgid "One-Time Payment" +msgstr "Einmalige Zahlung" + +#: inc/fields/payment-markup.php:562 +msgid "Choose payment type" +msgstr "Wählen Sie die Zahlungsart" + +#: inc/payments/front-end.php:333 +msgid "Billing interval does not match the form configuration." +msgstr "Das Abrechnungsintervall stimmt nicht mit der Formular-Konfiguration überein." + +#: inc/payments/payment-helper.php:627 +msgid "Payment type does not match the form configuration." +msgstr "Zahlungsart stimmt nicht mit der Formular-Konfiguration überein." + +#: inc/payments/payment-helper.php:760 +msgid "Payment verification failed. Payment type mismatch." +msgstr "Zahlungsüberprüfung fehlgeschlagen. Zahlungsart stimmt nicht überein." + +#: assets/build/blocks.js:172 +msgid "Minimum Characters" +msgstr "Mindestanzahl von Zeichen" + +#: assets/build/blocks.js:172 +msgid "Minimum characters cannot exceed Maximum characters." +msgstr "Mindestanzahl an Zeichen darf die Höchstanzahl an Zeichen nicht überschreiten." + +#: assets/build/blocks.js:172 +msgid "Both" +msgstr "Beide" + +#: assets/build/blocks.js:172 +msgid "One-Time Label" +msgstr "Einmaliges Etikett" + +#: assets/build/blocks.js:172 +msgid "Label shown to users for the one-time payment option." +msgstr "Beschriftung, die den Benutzern für die Einmalzahlungsoption angezeigt wird." + +#: assets/build/blocks.js:172 +msgid "Subscription Label" +msgstr "Abonnementsetikett" + +#: assets/build/blocks.js:172 +msgid "Label shown to users for the subscription option." +msgstr "Beschriftung, die den Benutzern für die Abonnementoption angezeigt wird." + +#: assets/build/blocks.js:172 +msgid "Default Selection" +msgstr "Standardauswahl" + +#: assets/build/blocks.js:172 +msgid "Which option is pre-selected when the form loads." +msgstr "Welche Option ist vorausgewählt, wenn das Formular geladen wird." + +#: assets/build/blocks.js:172 +msgid "One-Time Amount Type" +msgstr "Einmaliger Betragstyp" + +#: assets/build/blocks.js:172 +msgid "Set how the one-time payment amount is determined." +msgstr "Legen Sie fest, wie der Einmalzahlungsbetrag bestimmt wird." + +#: assets/build/blocks.js:172 +msgid "One-Time Fixed Amount" +msgstr "Einmaliger Festbetrag" + +#: assets/build/blocks.js:172 +msgid "Amount charged for a one-time payment." +msgstr "Betrag, der für eine einmalige Zahlung berechnet wird." + +#: assets/build/blocks.js:172 +msgid "One-Time Amount Field" +msgstr "Einmaliger Betragsfeld" + +#: assets/build/blocks.js:172 +msgid "Pick a form field whose value determines the one-time payment amount." +msgstr "Wählen Sie ein Formularfeld aus, dessen Wert den Einmalzahlungsbetrag bestimmt." + +#: assets/build/blocks.js:172 +msgid "One-Time Minimum Amount" +msgstr "Einmaliger Mindestbetrag" + +#: assets/build/blocks.js:172 +msgid "Minimum amount users can enter for one-time payment (0 for no minimum)." +msgstr "Mindestbetrag, den Benutzer für eine einmalige Zahlung eingeben können (0 für kein Minimum)." + +#: assets/build/blocks.js:172 +msgid "Subscription Amount Type" +msgstr "Abonnementbetragstyp" + +#: assets/build/blocks.js:172 +msgid "Set how the subscription amount is determined." +msgstr "Legen Sie fest, wie der Abonnementbetrag bestimmt wird." + +#: assets/build/blocks.js:172 +msgid "Subscription Fixed Amount" +msgstr "Abonnement Festbetrag" + +#: assets/build/blocks.js:172 +msgid "Recurring amount charged per billing interval." +msgstr "Wiederkehrender Betrag, der pro Abrechnungsintervall berechnet wird." + +#: assets/build/blocks.js:172 +msgid "Subscription Amount Field" +msgstr "Feld für den Abonnementbetrag" + +#: assets/build/blocks.js:172 +msgid "Pick a form field whose value determines the subscription amount." +msgstr "Wählen Sie ein Formularfeld aus, dessen Wert den Abonnementbetrag bestimmt." + +#: assets/build/blocks.js:172 +msgid "Subscription Minimum Amount" +msgstr "Mindestbetrag für das Abonnement" + +#: assets/build/blocks.js:172 +msgid "Minimum amount users can enter for subscription (0 for no minimum)." +msgstr "Mindestbetrag, den Benutzer für das Abonnement eingeben können (0 für kein Minimum)." + +#: 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 "Wählen Sie ein Feld aus Ihrem Formular, wie eine Zahl, ein Dropdown-Menü, eine Mehrfachauswahl oder ein verstecktes Feld, dessen Wert den Zahlungsbetrag bestimmen soll." + +#: assets/build/templatePicker.js:172 +msgid "You do not have permission to create forms." +msgstr "Sie haben keine Berechtigung, Formulare zu erstellen." + +#: assets/build/templatePicker.js:172 +msgid "The form could not be saved. Please try again." +msgstr "Das Formular konnte nicht gespeichert werden. Bitte versuchen Sie es erneut." + +#: assets/build/templatePicker.js:172 +msgid "Unable to reach the SureForms AI service. Please check your connection and try again." +msgstr "Der SureForms AI-Dienst ist nicht erreichbar. Bitte überprüfen Sie Ihre Verbindung und versuchen Sie es erneut." + +#: assets/build/templatePicker.js:172 +msgid "The AI service did not return a response. Please try again." +msgstr "Der KI-Dienst hat keine Antwort zurückgegeben. Bitte versuchen Sie es erneut." + +#: assets/build/templatePicker.js:172 +msgid "Form generation failed. Please try again." +msgstr "Die Formularerstellung ist fehlgeschlagen. Bitte versuchen Sie es erneut." + +#: assets/build/templatePicker.js:172 +msgid "The AI response was empty. Please refine your prompt and try again." +msgstr "Die KI-Antwort war leer. Bitte verfeinern Sie Ihre Eingabeaufforderung und versuchen Sie es erneut." + +#: assets/build/templatePicker.js:172 +msgid "Unable to build form fields from the AI response." +msgstr "Formularfelder können nicht aus der KI-Antwort erstellt werden." + #: inc/post-types.php:205 msgctxt "post type general name" msgid "Forms" diff --git a/languages/sureforms-es_ES-120a6dad015d3891c70f578c2251576b.json b/languages/sureforms-es_ES-120a6dad015d3891c70f578c2251576b.json index b4b615981..c0686a551 100644 --- a/languages/sureforms-es_ES-120a6dad015d3891c70f578c2251576b.json +++ b/languages/sureforms-es_ES-120a6dad015d3891c70f578c2251576b.json @@ -1 +1 @@ -{"translation-revision-date":"2024-12-13T16:34:28+00:00","generator":"WP-CLI\/2.12.0","source":"assets\/build\/templatePicker.js","domain":"messages","locale_data":{"messages":{"":{"domain":"messages","lang":"en","plural-forms":"nplurals=2; plural=(n != 1);"},"Dashboard":["Tablero"],"Connect Now":["Conectar ahora"],"Authentication Failed":["Autenticaci\u00f3n fallida"],"Contact Support":["Contactar con el soporte"],"Click Here to Retry":["Haz clic aqu\u00ed para reintentar"],"Exit to Dashboard":["Salir al panel de control"],"AI Form Builder":["Constructor de Formularios de IA"],"Speech recognition is not supported in your current browser. Please use Google Chrome \/ Safari.":["El reconocimiento de voz no es compatible con su navegador actual. Por favor, use Google Chrome \/ Safari."],"Please allow microphone access to use voice input.":["Por favor, permite el acceso al micr\u00f3fono para usar la entrada de voz."],"Voice Input":["Entrada de voz"],"Try Again":["Int\u00e9ntalo de nuevo"],"Please try again after %s.":["Por favor, int\u00e9ntalo de nuevo despu\u00e9s de %s."],"You have reached the maximum number of form generations in your Free Plan.":["Has alcanzado el n\u00famero m\u00e1ximo de generaciones de formularios en tu Plan Gratis."],"Unlock Conversational Forms":["Desbloquear formularios conversacionales"],"Simple":["Sencillo"],"Upgrade Now":["Actualiza ahora"],"Generate with AI":["Generar con IA"],"Please check your username and password for the account, and try to reconnect again. Need help?":["Por favor, verifica tu nombre de usuario y contrase\u00f1a para la cuenta, e intenta reconectar de nuevo. \u00bfNecesitas ayuda?"],"Describe the form you want to create":["Describe el formulario que deseas crear"],"We are building your form\u2026":["Estamos construyendo tu formulario\u2026"],"Payment":["Pago"],"and ":["y"],"more\u2026":["m\u00e1s\u2026"],"Calculations":["C\u00e1lculos"],"Unlock Calculator Forms":["Desbloquear formularios de calculadora"],"Build Smart Forms That Calculate Instantly":["Construya formularios inteligentes que calculen al instante"],"Empower your forms with advanced calculations. From loan calculators to BMI checkers - create interactive forms that give real-time results.":["Potencia tus formularios con c\u00e1lculos avanzados. Desde calculadoras de pr\u00e9stamos hasta verificadores de IMC: crea formularios interactivos que ofrecen resultados en tiempo real."],"Add complex formulas with ease":["Agrega f\u00f3rmulas complejas con facilidad"],"Provide instant answers to users":["Proporciona respuestas instant\u00e1neas a los usuarios"],"Perfect for finance, health, and pricing forms":["Perfecto para formularios de finanzas, salud y precios"],"Conversational":["Conversacional"],"Turn Simple Forms Into Conversations":["Convierte Formularios Simples en Conversaciones"],"Transform boring forms into friendly, chat-like experiences. Ask one question at a time, just like a real conversation, and see higher engagement.":["Transforma formularios aburridos en experiencias amigables, similares a un chat. Haz una pregunta a la vez, como en una conversaci\u00f3n real, y observa un mayor compromiso."],"One question at a time, in chat flow":["Una pregunta a la vez, en el flujo de chat"],"More engaging than traditional forms":["M\u00e1s atractivo que las formas tradicionales"],"Boosts completion rates with a friendly interface":["Mejora las tasas de finalizaci\u00f3n con una interfaz amigable"],"Select this if you need calculations in your form. For example: Loan interest calculator.":["Seleccione esto si necesita c\u00e1lculos en su formulario. Por ejemplo: Calculadora de intereses de pr\u00e9stamos."],"Select this if you want your form to display one question at a time, like a chat.":["Selecciona esto si deseas que tu formulario muestre una pregunta a la vez, como en un chat."],"Select this if you want to collect payments through your form.":["Selecciona esto si deseas recibir pagos a trav\u00e9s de tu formulario."],"%d AI Generations Left. SureForms Premium allows:":["%d Generaciones de IA restantes. SureForms Premium permite:"],"%d AI Generations Left, Connect to SureForms AI to Get 10 More":["%d Generaciones de IA restantes, con\u00e9ctate a SureForms AI para obtener 10 m\u00e1s"],"%d AI Generations Left. Upgrade to SureForms Premium":["%d Generaciones de IA restantes. Actualiza a SureForms Premium"],"Contact form to collect name, email, and message from visitors":["Formulario de contacto para recopilar nombre, correo electr\u00f3nico y mensaje de los visitantes"],"Job application form for \"Marketing Manager\" with resume upload":["Formulario de solicitud de empleo para \"Gerente de Marketing\" con carga de curr\u00edculum"],"Feedback form to ask customers: \"How would you rate our product and what should we improve?\"":["Formulario de comentarios para preguntar a los clientes: \"\u00bfC\u00f3mo calificar\u00eda nuestro producto y qu\u00e9 deber\u00edamos mejorar?\""],"Event registration form for \"Photography Workshop\" with date and seat selection":["Formulario de inscripci\u00f3n para el evento \"Taller de Fotograf\u00eda\" con selecci\u00f3n de fecha y asiento"],"Newsletter signup form with name and email to join mailing list":["Formulario de suscripci\u00f3n al bolet\u00edn con nombre y correo electr\u00f3nico para unirse a la lista de correo"],"Order form for \"Custom T-Shirt\" with size, color, and quantity options":["Formulario de pedido para \"Camiseta personalizada\" con opciones de talla, color y cantidad"],"Survey form: \"How satisfied are you with our service? (1\u20135 stars)\"":["Formulario de encuesta: \"\u00bfQu\u00e9 tan satisfecho est\u00e1 con nuestro servicio? (1\u20135 estrellas)\""],"Appointment booking form for \"Consultation Call\" with preferred time":["Formulario de reserva de cita para \"Llamada de consulta\" con hora preferida"],"Describe the form that you want":["Describe la forma que deseas"],"Generate":["Generar"],"Create Unlimited Forms with AI":["Crea formularios ilimitados con IA"],"Add Advanced Field Types":["Agregar tipos de campos avanzados"],"Create Calculators, Surveys, etc.":["Crear calculadoras, encuestas, etc."],"Form Generation Limit Reached":["L\u00edmite de Generaci\u00f3n de Formularios Alcanzado"],"You have reached the maximum number of form generations in your Free Plan. SureForms Premium allows:":["Has alcanzado el n\u00famero m\u00e1ximo de generaciones de formularios en tu Plan Gratuito. SureForms Premium permite:"],"%s AI Generations Left.":["%s Generaciones de IA restantes."],"Unlock Unlimited Generations":["Desbloquea Generaciones Ilimitadas"],"Connect to SureForms AI":["Con\u00e9ctate a SureForms AI"],"You Have Hit Your Free Limit.":["Has alcanzado tu l\u00edmite gratuito."],"Connect to SureForms AI to Get 10 More.":["Con\u00e9ctate a SureForms AI para obtener 10 m\u00e1s."],"Or create it yourself":["O cr\u00e9alo t\u00fa mismo"],"Unable to create form":["No se puede crear el formulario"],"Something went wrong. Please try again.":["Algo sali\u00f3 mal. Por favor, int\u00e9ntalo de nuevo."],"Describe what kind of form you want":["Describe qu\u00e9 tipo de formulario deseas"],"Click to generate the form":["Haz clic para generar el formulario"],"Connecting to AI service":["Conectando al servicio de IA"],"Generating fields":["Generando campos"],"Finalizing your form":["Finalizando su formulario"],"Opening form editor":["Abriendo el editor de formularios"],"Design Multistep Forms":["Dise\u00f1ar formularios de varios pasos"],"Send Form Entries to Your CRM or Any App":["Env\u00eda las entradas del formulario a tu CRM o a cualquier aplicaci\u00f3n"],"You've reached your daily generation limit.":["Has alcanzado tu l\u00edmite diario de generaci\u00f3n."],"You've reached your daily limit for AI form generations.":["Has alcanzado tu l\u00edmite diario para la generaci\u00f3n de formularios de IA."],"Quiz":["Cuestionario"],"Unlock Quiz Forms":["Desbloquear formularios de cuestionarios"],"Create Engaging Quizzes That Score Automatically":["Crea cuestionarios atractivos que se califiquen autom\u00e1ticamente"],"Build interactive quizzes with scored questions and graded results. Perfect for assessments, trivia, and educational content.":["Crea cuestionarios interactivos con preguntas puntuadas y resultados calificados. Perfecto para evaluaciones, trivia y contenido educativo."],"Auto-score responses instantly":["Autoevaluar respuestas al instante"],"Display graded results to users":["Mostrar resultados calificados a los usuarios"],"Perfect for education, training, and fun trivia":["Perfecto para educaci\u00f3n, formaci\u00f3n y trivia divertida"],"Select this to create a quiz with scored questions and graded results.":["Selecciona esto para crear un cuestionario con preguntas puntuadas y resultados calificados."],"Select this to create a survey to collect responses and opinions.":["Selecciona esto para crear una encuesta y recopilar respuestas y opiniones."],"Survey":["Encuesta"],"Unlock Survey Forms":["Desbloquear formularios de encuesta"],"Collect Insights with Powerful Surveys":["Recopila informaci\u00f3n con encuestas poderosas"],"Create surveys to collect responses and opinions. Visualize results with charts and share aggregated insights with your audience.":["Crea encuestas para recopilar respuestas y opiniones. Visualiza los resultados con gr\u00e1ficos y comparte conocimientos agregados con tu audiencia."],"Aggregate and visualize responses":["Agrega y visualiza respuestas"],"Show live results to respondents":["Mostrar resultados en vivo a los encuestados"],"Perfect for feedback, polls, and research":["Perfecto para comentarios, encuestas e investigaci\u00f3n"]}}} \ No newline at end of file +{"translation-revision-date":"2024-12-13T16:34:28+00:00","generator":"WP-CLI\/2.12.0","source":"assets\/build\/templatePicker.js","domain":"messages","locale_data":{"messages":{"":{"domain":"messages","lang":"en","plural-forms":"nplurals=2; plural=(n != 1);"},"Dashboard":["Tablero"],"Connect Now":["Conectar ahora"],"Authentication Failed":["Autenticaci\u00f3n fallida"],"Contact Support":["Contactar con el soporte"],"Click Here to Retry":["Haz clic aqu\u00ed para reintentar"],"Exit to Dashboard":["Salir al panel de control"],"AI Form Builder":["Constructor de Formularios de IA"],"Speech recognition is not supported in your current browser. Please use Google Chrome \/ Safari.":["El reconocimiento de voz no es compatible con su navegador actual. Por favor, use Google Chrome \/ Safari."],"Please allow microphone access to use voice input.":["Por favor, permite el acceso al micr\u00f3fono para usar la entrada de voz."],"Voice Input":["Entrada de voz"],"Try Again":["Int\u00e9ntalo de nuevo"],"Please try again after %s.":["Por favor, int\u00e9ntalo de nuevo despu\u00e9s de %s."],"You have reached the maximum number of form generations in your Free Plan.":["Has alcanzado el n\u00famero m\u00e1ximo de generaciones de formularios en tu Plan Gratis."],"Unlock Conversational Forms":["Desbloquear formularios conversacionales"],"Simple":["Sencillo"],"Upgrade Now":["Actualiza ahora"],"Generate with AI":["Generar con IA"],"Please check your username and password for the account, and try to reconnect again. Need help?":["Por favor, verifica tu nombre de usuario y contrase\u00f1a para la cuenta, e intenta reconectar de nuevo. \u00bfNecesitas ayuda?"],"Describe the form you want to create":["Describe el formulario que deseas crear"],"We are building your form\u2026":["Estamos construyendo tu formulario\u2026"],"Payment":["Pago"],"and ":["y"],"more\u2026":["m\u00e1s\u2026"],"Calculations":["C\u00e1lculos"],"Unlock Calculator Forms":["Desbloquear formularios de calculadora"],"Build Smart Forms That Calculate Instantly":["Construya formularios inteligentes que calculen al instante"],"Empower your forms with advanced calculations. From loan calculators to BMI checkers - create interactive forms that give real-time results.":["Potencia tus formularios con c\u00e1lculos avanzados. Desde calculadoras de pr\u00e9stamos hasta verificadores de IMC: crea formularios interactivos que ofrecen resultados en tiempo real."],"Add complex formulas with ease":["Agrega f\u00f3rmulas complejas con facilidad"],"Provide instant answers to users":["Proporciona respuestas instant\u00e1neas a los usuarios"],"Perfect for finance, health, and pricing forms":["Perfecto para formularios de finanzas, salud y precios"],"Conversational":["Conversacional"],"Turn Simple Forms Into Conversations":["Convierte Formularios Simples en Conversaciones"],"Transform boring forms into friendly, chat-like experiences. Ask one question at a time, just like a real conversation, and see higher engagement.":["Transforma formularios aburridos en experiencias amigables, similares a un chat. Haz una pregunta a la vez, como en una conversaci\u00f3n real, y observa un mayor compromiso."],"One question at a time, in chat flow":["Una pregunta a la vez, en el flujo de chat"],"More engaging than traditional forms":["M\u00e1s atractivo que las formas tradicionales"],"Boosts completion rates with a friendly interface":["Mejora las tasas de finalizaci\u00f3n con una interfaz amigable"],"Select this if you need calculations in your form. For example: Loan interest calculator.":["Seleccione esto si necesita c\u00e1lculos en su formulario. Por ejemplo: Calculadora de intereses de pr\u00e9stamos."],"Select this if you want your form to display one question at a time, like a chat.":["Selecciona esto si deseas que tu formulario muestre una pregunta a la vez, como en un chat."],"Select this if you want to collect payments through your form.":["Selecciona esto si deseas recibir pagos a trav\u00e9s de tu formulario."],"%d AI Generations Left. SureForms Premium allows:":["%d Generaciones de IA restantes. SureForms Premium permite:"],"%d AI Generations Left, Connect to SureForms AI to Get 10 More":["%d Generaciones de IA restantes, con\u00e9ctate a SureForms AI para obtener 10 m\u00e1s"],"%d AI Generations Left. Upgrade to SureForms Premium":["%d Generaciones de IA restantes. Actualiza a SureForms Premium"],"Contact form to collect name, email, and message from visitors":["Formulario de contacto para recopilar nombre, correo electr\u00f3nico y mensaje de los visitantes"],"Job application form for \"Marketing Manager\" with resume upload":["Formulario de solicitud de empleo para \"Gerente de Marketing\" con carga de curr\u00edculum"],"Feedback form to ask customers: \"How would you rate our product and what should we improve?\"":["Formulario de comentarios para preguntar a los clientes: \"\u00bfC\u00f3mo calificar\u00eda nuestro producto y qu\u00e9 deber\u00edamos mejorar?\""],"Event registration form for \"Photography Workshop\" with date and seat selection":["Formulario de inscripci\u00f3n para el evento \"Taller de Fotograf\u00eda\" con selecci\u00f3n de fecha y asiento"],"Newsletter signup form with name and email to join mailing list":["Formulario de suscripci\u00f3n al bolet\u00edn con nombre y correo electr\u00f3nico para unirse a la lista de correo"],"Order form for \"Custom T-Shirt\" with size, color, and quantity options":["Formulario de pedido para \"Camiseta personalizada\" con opciones de talla, color y cantidad"],"Survey form: \"How satisfied are you with our service? (1\u20135 stars)\"":["Formulario de encuesta: \"\u00bfQu\u00e9 tan satisfecho est\u00e1 con nuestro servicio? (1\u20135 estrellas)\""],"Appointment booking form for \"Consultation Call\" with preferred time":["Formulario de reserva de cita para \"Llamada de consulta\" con hora preferida"],"Describe the form that you want":["Describe la forma que deseas"],"Generate":["Generar"],"Create Unlimited Forms with AI":["Crea formularios ilimitados con IA"],"Add Advanced Field Types":["Agregar tipos de campos avanzados"],"Create Calculators, Surveys, etc.":["Crear calculadoras, encuestas, etc."],"Form Generation Limit Reached":["L\u00edmite de Generaci\u00f3n de Formularios Alcanzado"],"You have reached the maximum number of form generations in your Free Plan. SureForms Premium allows:":["Has alcanzado el n\u00famero m\u00e1ximo de generaciones de formularios en tu Plan Gratuito. SureForms Premium permite:"],"%s AI Generations Left.":["%s Generaciones de IA restantes."],"Unlock Unlimited Generations":["Desbloquea Generaciones Ilimitadas"],"Connect to SureForms AI":["Con\u00e9ctate a SureForms AI"],"You Have Hit Your Free Limit.":["Has alcanzado tu l\u00edmite gratuito."],"Connect to SureForms AI to Get 10 More.":["Con\u00e9ctate a SureForms AI para obtener 10 m\u00e1s."],"Or create it yourself":["O cr\u00e9alo t\u00fa mismo"],"Unable to create form":["No se puede crear el formulario"],"Something went wrong. Please try again.":["Algo sali\u00f3 mal. Por favor, int\u00e9ntalo de nuevo."],"Describe what kind of form you want":["Describe qu\u00e9 tipo de formulario deseas"],"Click to generate the form":["Haz clic para generar el formulario"],"Connecting to AI service":["Conectando al servicio de IA"],"Generating fields":["Generando campos"],"Finalizing your form":["Finalizando su formulario"],"Opening form editor":["Abriendo el editor de formularios"],"Design Multistep Forms":["Dise\u00f1ar formularios de varios pasos"],"Send Form Entries to Your CRM or Any App":["Env\u00eda las entradas del formulario a tu CRM o a cualquier aplicaci\u00f3n"],"You've reached your daily generation limit.":["Has alcanzado tu l\u00edmite diario de generaci\u00f3n."],"You've reached your daily limit for AI form generations.":["Has alcanzado tu l\u00edmite diario para la generaci\u00f3n de formularios de IA."],"Quiz":["Cuestionario"],"Unlock Quiz Forms":["Desbloquear formularios de cuestionarios"],"Create Engaging Quizzes That Score Automatically":["Crea cuestionarios atractivos que se califiquen autom\u00e1ticamente"],"Build interactive quizzes with scored questions and graded results. Perfect for assessments, trivia, and educational content.":["Crea cuestionarios interactivos con preguntas puntuadas y resultados calificados. Perfecto para evaluaciones, trivia y contenido educativo."],"Auto-score responses instantly":["Autoevaluar respuestas al instante"],"Display graded results to users":["Mostrar resultados calificados a los usuarios"],"Perfect for education, training, and fun trivia":["Perfecto para educaci\u00f3n, formaci\u00f3n y trivia divertida"],"Select this to create a quiz with scored questions and graded results.":["Selecciona esto para crear un cuestionario con preguntas puntuadas y resultados calificados."],"Select this to create a survey to collect responses and opinions.":["Selecciona esto para crear una encuesta y recopilar respuestas y opiniones."],"Survey":["Encuesta"],"Unlock Survey Forms":["Desbloquear formularios de encuesta"],"Collect Insights with Powerful Surveys":["Recopila informaci\u00f3n con encuestas poderosas"],"Create surveys to collect responses and opinions. Visualize results with charts and share aggregated insights with your audience.":["Crea encuestas para recopilar respuestas y opiniones. Visualiza los resultados con gr\u00e1ficos y comparte conocimientos agregados con tu audiencia."],"Aggregate and visualize responses":["Agrega y visualiza respuestas"],"Show live results to respondents":["Mostrar resultados en vivo a los encuestados"],"Perfect for feedback, polls, and research":["Perfecto para comentarios, encuestas e investigaci\u00f3n"],"You do not have permission to create forms.":["No tienes permiso para crear formularios."],"The form could not be saved. Please try again.":["El formulario no se pudo guardar. Por favor, int\u00e9ntelo de nuevo."],"Unable to reach the SureForms AI service. Please check your connection and try again.":["No se puede acceder al servicio de SureForms AI. Por favor, verifique su conexi\u00f3n e int\u00e9ntelo de nuevo."],"The AI service did not return a response. Please try again.":["El servicio de IA no devolvi\u00f3 una respuesta. Por favor, int\u00e9ntelo de nuevo."],"Form generation failed. Please try again.":["La generaci\u00f3n del formulario fall\u00f3. Por favor, int\u00e9ntelo de nuevo."],"The AI response was empty. Please refine your prompt and try again.":["La respuesta de la IA estaba vac\u00eda. Por favor, refine su solicitud y vuelva a intentarlo."],"Unable to build form fields from the AI response.":["No se pueden construir los campos del formulario a partir de la respuesta de la IA."]}}} \ No newline at end of file diff --git a/languages/sureforms-es_ES-4b62e3f004dea2c587b5a3069263d994.json b/languages/sureforms-es_ES-4b62e3f004dea2c587b5a3069263d994.json index 370d58025..fe1d80b9a 100644 --- a/languages/sureforms-es_ES-4b62e3f004dea2c587b5a3069263d994.json +++ b/languages/sureforms-es_ES-4b62e3f004dea2c587b5a3069263d994.json @@ -1 +1 @@ -{"translation-revision-date":"2024-12-13T16:34:28+00:00","generator":"WP-CLI\/2.12.0","source":"assets\/build\/blocks.js","domain":"messages","locale_data":{"messages":{"":{"domain":"messages","lang":"en","plural-forms":"nplurals=2; plural=(n != 1);"},"Settings":["Configuraciones"],"Search":["Buscar"],"Fields":["Campos"],"Image":["Imagen"],"Submit":["Enviar"],"Required":["Requerido"],"Form Title":["T\u00edtulo del formulario"],"Show":["Mostrar"],"Hide":["Ocultar"],"Edit Form":["Editar formulario"],"Icon":["Icono"],"Desktop":["Escritorio"],"Medium":["Medio"],"Mobile":["M\u00f3vil"],"Repeat":["Repetir"],"Scroll":["Desplazar"],"Tablet":["Tableta"],"Basic":["B\u00e1sico"],"(no title)":["(sin t\u00edtulo)"],"Select a Form":["Selecciona un formulario"],"No forms found\u2026":["No se encontraron formularios\u2026"],"Choose":["Elegir"],"Create New":["Crear nuevo"],"Change Form":["Cambiar formulario"],"This form has been deleted or is unavailable.":["Este formulario ha sido eliminado o no est\u00e1 disponible."],"Form Settings":["Configuraci\u00f3n del formulario"],"Show Form Title on this Page":["Mostrar el t\u00edtulo del formulario en esta p\u00e1gina"],"Note: For editing SureForms, please refer to the SureForms Editor - ":["Nota: Para editar SureForms, consulte el Editor de SureForms -"],"Field preview":["Vista previa del campo"],"General":["General"],"Style":["Estilo"],"Advanced":["Avanzado"],"No tags available":["No hay etiquetas disponibles"],"Device":["Dispositivo"],"Select Shortcodes":["Seleccionar c\u00f3digos cortos"],"Page Break Label":["Etiqueta de salto de p\u00e1gina"],"Next":["Siguiente"],"Back":["Atr\u00e1s"],"Reset":["Restablecer"],"Generic tags":["Etiquetas gen\u00e9ricas"],"Pixel":["P\u00edxel"],"Em":["Em"],"Select Units":["Seleccionar unidades"],"%s units":["%s unidades"],"Margin":["Margen"],"Attributes":["Atributos"],"Input Pattern":["Patr\u00f3n de entrada"],"None":["Ninguno"],"(###) ###-####":["(###) ###-####"],"(##) ####-####":["(##) ####-####"],"27\/08\/2024":["27\/08\/2024"],"23:59:59":["23:59:59"],"27\/08\/2024 23:59:59":["27\/08\/2024 23:59:59"],"Custom":["Personalizado"],"Custom Mask":["M\u00e1scara personalizada"],"Please check the documentation to manage custom input pattern ":["Por favor, consulte la documentaci\u00f3n para gestionar el patr\u00f3n de entrada personalizado"],"here":["aqu\u00ed"],"Default Value":["Valor predeterminado"],"Error Message":["Mensaje de error"],"Help Text":["Texto de ayuda"],"Number Format":["Formato de n\u00famero"],"US Style (Eg: 9,999.99)":["Estilo estadounidense (Ej: 9,999.99)"],"EU Style (Eg: 9.999,99)":["Estilo UE (Ej: 9.999,99)"],"Minimum Value":["Valor m\u00ednimo"],"Maximum Value":["Valor m\u00e1ximo"],"Please check the Minimum and Maximum value":["Por favor, verifica el valor M\u00ednimo y M\u00e1ximo"],"Enable Email Confirmation":["Habilitar confirmaci\u00f3n de correo electr\u00f3nico"],"Checked by Default":["Marcado por defecto"],"Error message":["Mensaje de error"],"Checked by default":["Marcado por defecto"],"Please add a option props to MultiButtonsControl":["Por favor, a\u00f1ade una opci\u00f3n de propiedades a MultiButtonsControl"],"Icon Library":["Biblioteca de Iconos"],"Close":["Cerrar"],"All Icons":["Todos los iconos"],"Other":["Otro"],"No Icons Found":["No se encontraron iconos"],"Insert Icon":["Insertar icono"],"Change Icon":["Cambiar \u00edcono"],"Choose Icon":["Elegir \u00edcono"],"Confirm":["Confirmar"],"Cancel":["Cancelar"],"Processing\u2026":["Procesando\u2026"],"Select Video":["Seleccionar video"],"Change Video":["Cambiar video"],"Select Lottie Animation":["Seleccionar animaci\u00f3n Lottie"],"Change Lottie Animation":["Cambiar animaci\u00f3n Lottie"],"Upload SVG":["Subir SVG"],"Change SVG":["Cambiar SVG"],"Select Image":["Seleccionar imagen"],"Change Image":["Cambiar imagen"],"Upload SVG?":["\u00bfSubir SVG?"],"Upload SVG can be potentially risky. Are you sure?":["Subir SVG puede ser potencialmente arriesgado. \u00bfEst\u00e1s seguro?"],"Upload Anyway":["Subir de todos modos"],"Bulk Add":["Agregar en masa"],"Bulk Add Options":["Agregar Opciones en Masa"],"Enter each option on a new line.":["Ingrese cada opci\u00f3n en una nueva l\u00ednea."],"Insert Options":["Insertar opciones"],"Full Width":["Ancho completo"],"Option Type":["Tipo de opci\u00f3n"],"Edit Options":["Opciones de edici\u00f3n"],"Add New Option":["Agregar nueva opci\u00f3n"],"ADD":["A\u00d1ADIR"],"Enable Auto Country Detection":["Habilitar la detecci\u00f3n autom\u00e1tica de pa\u00eds"],"%s Width":["Ancho %s"],"Upgrade":["Actualizar"],"Clear":["Claro"],"Select Color":["Seleccionar color"],"Primary Color":["Color primario"],"Text Color":["Color del texto"],"Field Spacing":["Espaciado de campo"],"Small":["Peque\u00f1o"],"Large":["Grande"],"Left":["Izquierda"],"Center":["Centro"],"Right":["Correcto"],"Color":["Color"],"Background Color":["Color de fondo"],"Auto":["Auto"],"Default":["Predeterminado"],"Normal":["Normal"],"%":["%"],"Top":["Superior"],"Bottom":["Fondo"],"Width":["Ancho"],"Size":["Tama\u00f1o"],"EM":["EM"],"Padding":["Relleno"],"Color 1":["Color 1"],"Color 2":["Color 2"],"Type":["Tipo"],"Linear":["Lineal"],"Radial":["Radial"],"Location 1":["Ubicaci\u00f3n 1"],"Location 2":["Ubicaci\u00f3n 2"],"Angle":["\u00c1ngulo"],"Classic":["Cl\u00e1sico"],"Gradient":["Gradiente"],"Horizontal":["Horizontal"],"Vertical":["Vertical"],"Background":["Antecedentes"],"Cover":["Cubrir"],"Contain":["Contener"],"Layout":["Dise\u00f1o"],"Overlay":["Superposici\u00f3n"],"No Repeat":["No repetir"],"Overlay Opacity":["Opacidad de superposici\u00f3n"],"Conditional Logic":["L\u00f3gica condicional"],"Upgrade to the SureForms Starter Plan to create dynamic forms that adapt based on user input, offering a personalised and efficient form experience.":["Actualiza al Plan Starter de SureForms para crear formularios din\u00e1micos que se adaptan seg\u00fan la entrada del usuario, ofreciendo una experiencia de formulario personalizada y eficiente."],"Enable Conditional Logic":["Habilitar l\u00f3gica condicional"],"this field if":["este campo si"],"Configure Conditions":["Configurar condiciones"],"Premium":["Premium"],"Overlay Type":["Tipo de superposici\u00f3n"],"Image Overlay Color":["Color de superposici\u00f3n de imagen"],"Image Position":["Posici\u00f3n de la imagen"],"Attachment":["Adjunto"],"Fixed":["Fijo"],"Blend Mode":["Modo de fusi\u00f3n"],"Multiply":["Multiplicar"],"Screen":["Pantalla"],"Darken":["Oscurecer"],"Lighten":["Aligerar"],"Color Dodge":["Sobreexponer color"],"Saturation":["Saturaci\u00f3n"],"Repeat-x":["Repetir-x"],"Repeat-y":["Repetir-y"],"PX":["PX"],"Button":["Bot\u00f3n"],"Prefix Label":["Etiqueta de prefijo"],"Suffix Label":["Etiqueta de sufijo"],"Border Radius":["Radio de borde"],"Form Theme":["Tema del formulario"],"Select Gradient":["Seleccionar degradado"],"Unlock Conditional Logic Editor":["Desbloquear el Editor de L\u00f3gica Condicional"],"Rich Text Editor":["Editor de texto enriquecido"],"Read Only":["Solo lectura"],"Select Country":["Seleccionar pa\u00eds"],"Default Country":["Pa\u00eds predeterminado"],"Subscription":["Suscripci\u00f3n"],"One Time":["Una vez"],"Unique Entry":["Entrada \u00danica"],"Maximum Characters":["M\u00e1ximo de caracteres"],"Textarea Height":["Altura del \u00e1rea de texto"],"Minimum Selections":["Selecciones M\u00ednimas"],"Maximum Selections":["Selecciones M\u00e1ximas"],"Add Numeric Values to Options":["Agregar valores num\u00e9ricos a las opciones"],"Single Choice Only":["Solo una opci\u00f3n"],"Enable Dropdown Search":["Habilitar b\u00fasqueda desplegable"],"Allow Multiple":["Permitir m\u00faltiples"],"%1$s fields are required. Please configure these fields in the block settings.":["Se requieren los campos %1$s. Por favor, configure estos campos en la configuraci\u00f3n del bloque."],"%1$s field is required. Please configure this field in the block settings.":["El campo %1$s es obligatorio. Por favor, configure este campo en la configuraci\u00f3n del bloque."],"You need to configure a payment account to collect payments from this form. Please configure your payment provider to proceed.":["Necesitas configurar una cuenta de pago para recibir pagos de este formulario. Por favor, configura tu proveedor de pagos para continuar."],"Configure Payment Account":["Configurar cuenta de pago"],"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.":["Este es un marcador de posici\u00f3n para el bloque de Pago. Los campos de pago reales para su(s) proveedor(es) de pago configurado(s) solo aparecer\u00e1n cuando previsualice o publique el formulario."],"2 Payments":["2 Pagos"],"3 Payments":["3 Pagos"],"4 Payments":["4 Pagos"],"5 Payments":["5 Pagos"],"Never":["Nunca"],"Stop Subscription After":["Detener suscripci\u00f3n despu\u00e9s"],"Choose when to automatically stop the subscription":["Elige cu\u00e1ndo detener autom\u00e1ticamente la suscripci\u00f3n"],"Number of Payments":["N\u00famero de pagos"],"Enter a number between 1 to 100":["Introduce un n\u00famero entre 1 y 100"],"Form Field":["Campo de formulario"],"Payment Type":["Tipo de pago"],"Subscription Plan Name":["Nombre del Plan de Suscripci\u00f3n"],"Billing Interval":["Intervalo de facturaci\u00f3n"],"Daily":["Diario"],"Weekly":["Semanal"],"Monthly":["Mensual"],"Quarterly":["Trimestral"],"Yearly":["Anual"],"Amount Type":["Tipo de Monto"],"Fixed Amount":["Cantidad Fija"],"Dynamic Amount":["Cantidad Din\u00e1mica"],"Choose whether to charge a fixed amount or charge the amount based on user input in other form fields.":["Elija si desea cobrar una cantidad fija o cobrar la cantidad basada en la entrada del usuario en otros campos del formulario."],"Set the exact amount you want to charge. Users won\u2019t be able to change it":["Establece la cantidad exacta que deseas cobrar. Los usuarios no podr\u00e1n cambiarla"],"Choose Amount Field":["Elegir campo de cantidad"],"Select a field\u2026":["Seleccione un campo\u2026"],"Pick a field from your form like a number, dropdown, or multichoice whose value should decide the payment amount.":["Elige un campo de tu formulario como un n\u00famero, un desplegable o una opci\u00f3n m\u00faltiple cuyo valor deba decidir el monto del pago."],"Minimum Amount":["Cantidad m\u00ednima"],"Set the minimum amount users can enter (0 for no minimum)":["Establezca la cantidad m\u00ednima que los usuarios pueden ingresar (0 para sin m\u00ednimo)"],"Customer Name Field (Required)":["Campo de Nombre del Cliente (Obligatorio)"],"Customer Name Field (Optional)":["Campo de Nombre del Cliente (Opcional)"],"Select the input field that contains the customer name (Required for subscriptions)":["Seleccione el campo de entrada que contiene el nombre del cliente (Requerido para suscripciones)"],"Select the input field that contains the customer name":["Seleccione el campo de entrada que contiene el nombre del cliente"],"Customer Email Field (Required)":["Campo de correo electr\u00f3nico del cliente (obligatorio)"],"Select the email field that contains the customer email":["Seleccione el campo de correo electr\u00f3nico que contiene el correo electr\u00f3nico del cliente"],"Payment":["Pago"],"%s - Order ID":["%s - ID de pedido"],"%s - Amount":["%s - Cantidad"],"%s - Customer Email":["%s - Correo Electr\u00f3nico del Cliente"],"%s - Customer Name":["%s - Nombre del Cliente"],"%s - Status":["%s - Estado"],"Button Alignment":["Alineaci\u00f3n del bot\u00f3n"],"Placeholder":["Marcador de posici\u00f3n"],"Preselect this option":["Preselecciona esta opci\u00f3n"],"Restrict Country Codes":["Restringir c\u00f3digos de pa\u00eds"],"Restriction Type":["Tipo de restricci\u00f3n"],"Allow":["Permitir"],"Block":["Bloque"],"Select Allowed Countries":["Seleccionar pa\u00edses permitidos"],"Choose countries\u2026":["Elige pa\u00edses\u2026"],"Choose which country codes users can select in the phone number field. Leave empty to allow all country codes.":["Elija qu\u00e9 c\u00f3digos de pa\u00eds pueden seleccionar los usuarios en el campo del n\u00famero de tel\u00e9fono. Deje vac\u00edo para permitir todos los c\u00f3digos de pa\u00eds."],"Select Blocked Countries":["Seleccionar pa\u00edses bloqueados"],"These countries will be hidden from the dropdown.":["Estos pa\u00edses se ocultar\u00e1n del men\u00fa desplegable."],"Bulk Edit":["Edici\u00f3n masiva"],"Select Layout":["Seleccionar dise\u00f1o"],"Number of Columns":["N\u00famero de columnas"],"Validation Message for Duplicate":["Mensaje de validaci\u00f3n para duplicado"],"Click here to insert a form":["Haga clic aqu\u00ed para insertar un formulario"],"Inherit Form's Original Style":["Heredar el estilo original del formulario"],"Text on Primary":["Texto en Primario"],"%s - Description":["%s - Descripci\u00f3n"],"Upgrade to Unlock":["Actualiza para desbloquear"],"Custom (Premium)":["Personalizado (Premium)"],"Select a theme style for this form embed.":["Seleccione un estilo de tema para este formulario incrustado."],"Colors":["Colores"],"Advanced Styling":["Estilo Avanzado"],"Unlock Custom Styling":["Desbloquear estilo personalizado"],"Switch to Custom Mode to take full control of your form's design and spacing.":["Cambia a Modo Personalizado para tener control total sobre el dise\u00f1o y el espaciado de tu formulario."],"Full color control (buttons, fields, text)":["Control total del color (botones, campos, texto)"],"Row and column gap control":["Control de separaci\u00f3n de filas y columnas"],"Field spacing and layout precision":["Precisi\u00f3n en el espaciado y dise\u00f1o de campos"],"Complete button styling":["Estilo completo del bot\u00f3n"],"Payment Description":["Descripci\u00f3n del pago"],"Shown on payment receipts and in your payment dashboard (Stripe and PayPal). Leave blank to use the default.":["Se muestra en los recibos de pago y en su panel de pagos (Stripe y PayPal). Deje en blanco para usar el valor predeterminado."],"Slug":["Babosa"],"Auto-generated on save":["Generado autom\u00e1ticamente al guardar"],"This slug is already used by another field. It will revert to the previous value.":["Este slug ya est\u00e1 siendo utilizado por otro campo. Volver\u00e1 al valor anterior."],"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.":["Cambiar el slug puede romper los env\u00edos de formularios, la l\u00f3gica condicional, las integraciones o cualquier otra caracter\u00edstica que actualmente haga referencia a este slug. Necesitar\u00e1s actualizar todas esas referencias manualmente."],"Field Slug":["Identificador de campo"],"Location Services":["Servicios de ubicaci\u00f3n"],"Unlock Address Autocomplete":["Desbloquear la autocompletaci\u00f3n de direcciones"],"Upgrade to enable Google Address Autocomplete with interactive map preview, making address entry faster and more accurate for your users.":["Actualiza para habilitar la autocompletaci\u00f3n de direcciones de Google con vista previa de mapa interactivo, haciendo que la entrada de direcciones sea m\u00e1s r\u00e1pida y precisa para tus usuarios."],"Enable Google Autocomplete":["Habilitar la autocompletar de Google"],"Show Interactive Map":["Mostrar mapa interactivo"],"Payments Per Page":["Pagos por p\u00e1gina"],"Show Subscriptions Section":["Mostrar secci\u00f3n de suscripciones"],"Show a dedicated subscriptions section above payment history.":["Muestra una secci\u00f3n dedicada a suscripciones por encima del historial de pagos."],"Payment Dashboard":["Panel de Pagos"],"View your payments and manage subscriptions in a single dashboard.":["Vea sus pagos y gestione sus suscripciones en un solo panel."],"Dynamic Default Value":["Valor Predeterminado Din\u00e1mico"]}}} \ No newline at end of file +{"translation-revision-date":"2024-12-13T16:34:28+00:00","generator":"WP-CLI\/2.12.0","source":"assets\/build\/blocks.js","domain":"messages","locale_data":{"messages":{"":{"domain":"messages","lang":"en","plural-forms":"nplurals=2; plural=(n != 1);"},"Settings":["Configuraciones"],"Search":["Buscar"],"Fields":["Campos"],"Image":["Imagen"],"Submit":["Enviar"],"Required":["Requerido"],"Form Title":["T\u00edtulo del formulario"],"Show":["Mostrar"],"Hide":["Ocultar"],"Edit Form":["Editar formulario"],"Icon":["Icono"],"Desktop":["Escritorio"],"Medium":["Medio"],"Mobile":["M\u00f3vil"],"Repeat":["Repetir"],"Scroll":["Desplazar"],"Tablet":["Tableta"],"Basic":["B\u00e1sico"],"(no title)":["(sin t\u00edtulo)"],"Select a Form":["Selecciona un formulario"],"No forms found\u2026":["No se encontraron formularios\u2026"],"Choose":["Elegir"],"Create New":["Crear nuevo"],"Change Form":["Cambiar formulario"],"This form has been deleted or is unavailable.":["Este formulario ha sido eliminado o no est\u00e1 disponible."],"Form Settings":["Configuraci\u00f3n del formulario"],"Show Form Title on this Page":["Mostrar el t\u00edtulo del formulario en esta p\u00e1gina"],"Note: For editing SureForms, please refer to the SureForms Editor - ":["Nota: Para editar SureForms, consulte el Editor de SureForms -"],"Field preview":["Vista previa del campo"],"General":["General"],"Style":["Estilo"],"Advanced":["Avanzado"],"No tags available":["No hay etiquetas disponibles"],"Device":["Dispositivo"],"Select Shortcodes":["Seleccionar c\u00f3digos cortos"],"Page Break Label":["Etiqueta de salto de p\u00e1gina"],"Next":["Siguiente"],"Back":["Atr\u00e1s"],"Reset":["Restablecer"],"Generic tags":["Etiquetas gen\u00e9ricas"],"Pixel":["P\u00edxel"],"Em":["Em"],"Select Units":["Seleccionar unidades"],"%s units":["%s unidades"],"Margin":["Margen"],"Attributes":["Atributos"],"Input Pattern":["Patr\u00f3n de entrada"],"None":["Ninguno"],"(###) ###-####":["(###) ###-####"],"(##) ####-####":["(##) ####-####"],"27\/08\/2024":["27\/08\/2024"],"23:59:59":["23:59:59"],"27\/08\/2024 23:59:59":["27\/08\/2024 23:59:59"],"Custom":["Personalizado"],"Custom Mask":["M\u00e1scara personalizada"],"Please check the documentation to manage custom input pattern ":["Por favor, consulte la documentaci\u00f3n para gestionar el patr\u00f3n de entrada personalizado"],"here":["aqu\u00ed"],"Default Value":["Valor predeterminado"],"Error Message":["Mensaje de error"],"Help Text":["Texto de ayuda"],"Number Format":["Formato de n\u00famero"],"US Style (Eg: 9,999.99)":["Estilo estadounidense (Ej: 9,999.99)"],"EU Style (Eg: 9.999,99)":["Estilo UE (Ej: 9.999,99)"],"Minimum Value":["Valor m\u00ednimo"],"Maximum Value":["Valor m\u00e1ximo"],"Please check the Minimum and Maximum value":["Por favor, verifica el valor M\u00ednimo y M\u00e1ximo"],"Enable Email Confirmation":["Habilitar confirmaci\u00f3n de correo electr\u00f3nico"],"Checked by Default":["Marcado por defecto"],"Error message":["Mensaje de error"],"Checked by default":["Marcado por defecto"],"Please add a option props to MultiButtonsControl":["Por favor, a\u00f1ade una opci\u00f3n de propiedades a MultiButtonsControl"],"Icon Library":["Biblioteca de Iconos"],"Close":["Cerrar"],"All Icons":["Todos los iconos"],"Other":["Otro"],"No Icons Found":["No se encontraron iconos"],"Insert Icon":["Insertar icono"],"Change Icon":["Cambiar \u00edcono"],"Choose Icon":["Elegir \u00edcono"],"Confirm":["Confirmar"],"Cancel":["Cancelar"],"Processing\u2026":["Procesando\u2026"],"Select Video":["Seleccionar video"],"Change Video":["Cambiar video"],"Select Lottie Animation":["Seleccionar animaci\u00f3n Lottie"],"Change Lottie Animation":["Cambiar animaci\u00f3n Lottie"],"Upload SVG":["Subir SVG"],"Change SVG":["Cambiar SVG"],"Select Image":["Seleccionar imagen"],"Change Image":["Cambiar imagen"],"Upload SVG?":["\u00bfSubir SVG?"],"Upload SVG can be potentially risky. Are you sure?":["Subir SVG puede ser potencialmente arriesgado. \u00bfEst\u00e1s seguro?"],"Upload Anyway":["Subir de todos modos"],"Bulk Add":["Agregar en masa"],"Bulk Add Options":["Agregar Opciones en Masa"],"Enter each option on a new line.":["Ingrese cada opci\u00f3n en una nueva l\u00ednea."],"Insert Options":["Insertar opciones"],"Full Width":["Ancho completo"],"Option Type":["Tipo de opci\u00f3n"],"Edit Options":["Opciones de edici\u00f3n"],"Add New Option":["Agregar nueva opci\u00f3n"],"ADD":["A\u00d1ADIR"],"Enable Auto Country Detection":["Habilitar la detecci\u00f3n autom\u00e1tica de pa\u00eds"],"%s Width":["Ancho %s"],"Upgrade":["Actualizar"],"Clear":["Claro"],"Select Color":["Seleccionar color"],"Primary Color":["Color primario"],"Text Color":["Color del texto"],"Field Spacing":["Espaciado de campo"],"Small":["Peque\u00f1o"],"Large":["Grande"],"Left":["Izquierda"],"Center":["Centro"],"Right":["Correcto"],"Color":["Color"],"Background Color":["Color de fondo"],"Auto":["Auto"],"Default":["Predeterminado"],"Normal":["Normal"],"%":["%"],"Top":["Superior"],"Bottom":["Fondo"],"Width":["Ancho"],"Size":["Tama\u00f1o"],"EM":["EM"],"Padding":["Relleno"],"Color 1":["Color 1"],"Color 2":["Color 2"],"Type":["Tipo"],"Linear":["Lineal"],"Radial":["Radial"],"Location 1":["Ubicaci\u00f3n 1"],"Location 2":["Ubicaci\u00f3n 2"],"Angle":["\u00c1ngulo"],"Classic":["Cl\u00e1sico"],"Gradient":["Gradiente"],"Horizontal":["Horizontal"],"Vertical":["Vertical"],"Background":["Antecedentes"],"Cover":["Cubrir"],"Contain":["Contener"],"Layout":["Dise\u00f1o"],"Overlay":["Superposici\u00f3n"],"No Repeat":["No repetir"],"Overlay Opacity":["Opacidad de superposici\u00f3n"],"Conditional Logic":["L\u00f3gica condicional"],"Upgrade to the SureForms Starter Plan to create dynamic forms that adapt based on user input, offering a personalised and efficient form experience.":["Actualiza al Plan Starter de SureForms para crear formularios din\u00e1micos que se adaptan seg\u00fan la entrada del usuario, ofreciendo una experiencia de formulario personalizada y eficiente."],"Enable Conditional Logic":["Habilitar l\u00f3gica condicional"],"this field if":["este campo si"],"Configure Conditions":["Configurar condiciones"],"Premium":["Premium"],"Overlay Type":["Tipo de superposici\u00f3n"],"Image Overlay Color":["Color de superposici\u00f3n de imagen"],"Image Position":["Posici\u00f3n de la imagen"],"Attachment":["Adjunto"],"Fixed":["Fijo"],"Blend Mode":["Modo de fusi\u00f3n"],"Multiply":["Multiplicar"],"Screen":["Pantalla"],"Darken":["Oscurecer"],"Lighten":["Aligerar"],"Color Dodge":["Sobreexponer color"],"Saturation":["Saturaci\u00f3n"],"Repeat-x":["Repetir-x"],"Repeat-y":["Repetir-y"],"PX":["PX"],"Button":["Bot\u00f3n"],"Prefix Label":["Etiqueta de prefijo"],"Suffix Label":["Etiqueta de sufijo"],"Border Radius":["Radio de borde"],"Form Theme":["Tema del formulario"],"Select Gradient":["Seleccionar degradado"],"Unlock Conditional Logic Editor":["Desbloquear el Editor de L\u00f3gica Condicional"],"Rich Text Editor":["Editor de texto enriquecido"],"Read Only":["Solo lectura"],"Select Country":["Seleccionar pa\u00eds"],"Default Country":["Pa\u00eds predeterminado"],"Subscription":["Suscripci\u00f3n"],"One Time":["Una vez"],"Unique Entry":["Entrada \u00danica"],"Maximum Characters":["M\u00e1ximo de caracteres"],"Textarea Height":["Altura del \u00e1rea de texto"],"Minimum Selections":["Selecciones M\u00ednimas"],"Maximum Selections":["Selecciones M\u00e1ximas"],"Add Numeric Values to Options":["Agregar valores num\u00e9ricos a las opciones"],"Single Choice Only":["Solo una opci\u00f3n"],"Enable Dropdown Search":["Habilitar b\u00fasqueda desplegable"],"Allow Multiple":["Permitir m\u00faltiples"],"%1$s fields are required. Please configure these fields in the block settings.":["Se requieren los campos %1$s. Por favor, configure estos campos en la configuraci\u00f3n del bloque."],"%1$s field is required. Please configure this field in the block settings.":["El campo %1$s es obligatorio. Por favor, configure este campo en la configuraci\u00f3n del bloque."],"You need to configure a payment account to collect payments from this form. Please configure your payment provider to proceed.":["Necesitas configurar una cuenta de pago para recibir pagos de este formulario. Por favor, configura tu proveedor de pagos para continuar."],"Configure Payment Account":["Configurar cuenta de pago"],"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.":["Este es un marcador de posici\u00f3n para el bloque de Pago. Los campos de pago reales para su(s) proveedor(es) de pago configurado(s) solo aparecer\u00e1n cuando previsualice o publique el formulario."],"2 Payments":["2 Pagos"],"3 Payments":["3 Pagos"],"4 Payments":["4 Pagos"],"5 Payments":["5 Pagos"],"Never":["Nunca"],"Stop Subscription After":["Detener suscripci\u00f3n despu\u00e9s"],"Choose when to automatically stop the subscription":["Elige cu\u00e1ndo detener autom\u00e1ticamente la suscripci\u00f3n"],"Number of Payments":["N\u00famero de pagos"],"Enter a number between 1 to 100":["Introduce un n\u00famero entre 1 y 100"],"Form Field":["Campo de formulario"],"Payment Type":["Tipo de pago"],"Subscription Plan Name":["Nombre del Plan de Suscripci\u00f3n"],"Billing Interval":["Intervalo de facturaci\u00f3n"],"Daily":["Diario"],"Weekly":["Semanal"],"Monthly":["Mensual"],"Quarterly":["Trimestral"],"Yearly":["Anual"],"Amount Type":["Tipo de Monto"],"Fixed Amount":["Cantidad Fija"],"Dynamic Amount":["Cantidad Din\u00e1mica"],"Choose whether to charge a fixed amount or charge the amount based on user input in other form fields.":["Elija si desea cobrar una cantidad fija o cobrar la cantidad basada en la entrada del usuario en otros campos del formulario."],"Set the exact amount you want to charge. Users won\u2019t be able to change it":["Establece la cantidad exacta que deseas cobrar. Los usuarios no podr\u00e1n cambiarla"],"Choose Amount Field":["Elegir campo de cantidad"],"Select a field\u2026":["Seleccione un campo\u2026"],"Minimum Amount":["Cantidad m\u00ednima"],"Set the minimum amount users can enter (0 for no minimum)":["Establezca la cantidad m\u00ednima que los usuarios pueden ingresar (0 para sin m\u00ednimo)"],"Customer Name Field (Required)":["Campo de Nombre del Cliente (Obligatorio)"],"Customer Name Field (Optional)":["Campo de Nombre del Cliente (Opcional)"],"Select the input field that contains the customer name (Required for subscriptions)":["Seleccione el campo de entrada que contiene el nombre del cliente (Requerido para suscripciones)"],"Select the input field that contains the customer name":["Seleccione el campo de entrada que contiene el nombre del cliente"],"Customer Email Field (Required)":["Campo de correo electr\u00f3nico del cliente (obligatorio)"],"Select the email field that contains the customer email":["Seleccione el campo de correo electr\u00f3nico que contiene el correo electr\u00f3nico del cliente"],"Payment":["Pago"],"%s - Order ID":["%s - ID de pedido"],"%s - Amount":["%s - Cantidad"],"%s - Customer Email":["%s - Correo Electr\u00f3nico del Cliente"],"%s - Customer Name":["%s - Nombre del Cliente"],"%s - Status":["%s - Estado"],"Button Alignment":["Alineaci\u00f3n del bot\u00f3n"],"Placeholder":["Marcador de posici\u00f3n"],"Preselect this option":["Preselecciona esta opci\u00f3n"],"Restrict Country Codes":["Restringir c\u00f3digos de pa\u00eds"],"Restriction Type":["Tipo de restricci\u00f3n"],"Allow":["Permitir"],"Block":["Bloque"],"Select Allowed Countries":["Seleccionar pa\u00edses permitidos"],"Choose countries\u2026":["Elige pa\u00edses\u2026"],"Choose which country codes users can select in the phone number field. Leave empty to allow all country codes.":["Elija qu\u00e9 c\u00f3digos de pa\u00eds pueden seleccionar los usuarios en el campo del n\u00famero de tel\u00e9fono. Deje vac\u00edo para permitir todos los c\u00f3digos de pa\u00eds."],"Select Blocked Countries":["Seleccionar pa\u00edses bloqueados"],"These countries will be hidden from the dropdown.":["Estos pa\u00edses se ocultar\u00e1n del men\u00fa desplegable."],"Bulk Edit":["Edici\u00f3n masiva"],"Select Layout":["Seleccionar dise\u00f1o"],"Number of Columns":["N\u00famero de columnas"],"Validation Message for Duplicate":["Mensaje de validaci\u00f3n para duplicado"],"Click here to insert a form":["Haga clic aqu\u00ed para insertar un formulario"],"Inherit Form's Original Style":["Heredar el estilo original del formulario"],"Text on Primary":["Texto en Primario"],"%s - Description":["%s - Descripci\u00f3n"],"Upgrade to Unlock":["Actualiza para desbloquear"],"Custom (Premium)":["Personalizado (Premium)"],"Select a theme style for this form embed.":["Seleccione un estilo de tema para este formulario incrustado."],"Colors":["Colores"],"Advanced Styling":["Estilo Avanzado"],"Unlock Custom Styling":["Desbloquear estilo personalizado"],"Switch to Custom Mode to take full control of your form's design and spacing.":["Cambia a Modo Personalizado para tener control total sobre el dise\u00f1o y el espaciado de tu formulario."],"Full color control (buttons, fields, text)":["Control total del color (botones, campos, texto)"],"Row and column gap control":["Control de separaci\u00f3n de filas y columnas"],"Field spacing and layout precision":["Precisi\u00f3n en el espaciado y dise\u00f1o de campos"],"Complete button styling":["Estilo completo del bot\u00f3n"],"Payment Description":["Descripci\u00f3n del pago"],"Shown on payment receipts and in your payment dashboard (Stripe and PayPal). Leave blank to use the default.":["Se muestra en los recibos de pago y en su panel de pagos (Stripe y PayPal). Deje en blanco para usar el valor predeterminado."],"Slug":["Babosa"],"Auto-generated on save":["Generado autom\u00e1ticamente al guardar"],"This slug is already used by another field. It will revert to the previous value.":["Este slug ya est\u00e1 siendo utilizado por otro campo. Volver\u00e1 al valor anterior."],"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.":["Cambiar el slug puede romper los env\u00edos de formularios, la l\u00f3gica condicional, las integraciones o cualquier otra caracter\u00edstica que actualmente haga referencia a este slug. Necesitar\u00e1s actualizar todas esas referencias manualmente."],"Field Slug":["Identificador de campo"],"Location Services":["Servicios de ubicaci\u00f3n"],"Unlock Address Autocomplete":["Desbloquear la autocompletaci\u00f3n de direcciones"],"Upgrade to enable Google Address Autocomplete with interactive map preview, making address entry faster and more accurate for your users.":["Actualiza para habilitar la autocompletaci\u00f3n de direcciones de Google con vista previa de mapa interactivo, haciendo que la entrada de direcciones sea m\u00e1s r\u00e1pida y precisa para tus usuarios."],"Enable Google Autocomplete":["Habilitar la autocompletar de Google"],"Show Interactive Map":["Mostrar mapa interactivo"],"Payments Per Page":["Pagos por p\u00e1gina"],"Show Subscriptions Section":["Mostrar secci\u00f3n de suscripciones"],"Show a dedicated subscriptions section above payment history.":["Muestra una secci\u00f3n dedicada a suscripciones por encima del historial de pagos."],"Payment Dashboard":["Panel de Pagos"],"View your payments and manage subscriptions in a single dashboard.":["Vea sus pagos y gestione sus suscripciones en un solo panel."],"Dynamic Default Value":["Valor Predeterminado Din\u00e1mico"],"Minimum Characters":["Caracteres m\u00ednimos"],"Minimum characters cannot exceed Maximum characters.":["Los caracteres m\u00ednimos no pueden exceder los caracteres m\u00e1ximos."],"Both":["Ambos"],"One-Time Label":["Etiqueta de un solo uso"],"Label shown to users for the one-time payment option.":["Etiqueta mostrada a los usuarios para la opci\u00f3n de pago \u00fanico."],"Subscription Label":["Etiqueta de suscripci\u00f3n"],"Label shown to users for the subscription option.":["Etiqueta mostrada a los usuarios para la opci\u00f3n de suscripci\u00f3n."],"Default Selection":["Selecci\u00f3n predeterminada"],"Which option is pre-selected when the form loads.":["\u00bfQu\u00e9 opci\u00f3n est\u00e1 preseleccionada cuando se carga el formulario?"],"One-Time Amount Type":["Tipo de Monto \u00danico"],"Set how the one-time payment amount is determined.":["Establezca c\u00f3mo se determina el monto del pago \u00fanico."],"One-Time Fixed Amount":["Monto fijo \u00fanico"],"Amount charged for a one-time payment.":["Cantidad cobrada por un pago \u00fanico."],"One-Time Amount Field":["Campo de Monto \u00danico"],"Pick a form field whose value determines the one-time payment amount.":["Elija un campo de formulario cuyo valor determine el monto del pago \u00fanico."],"One-Time Minimum Amount":["Monto m\u00ednimo \u00fanico"],"Minimum amount users can enter for one-time payment (0 for no minimum).":["Monto m\u00ednimo que los usuarios pueden ingresar para un pago \u00fanico (0 para sin m\u00ednimo)."],"Subscription Amount Type":["Tipo de Monto de Suscripci\u00f3n"],"Set how the subscription amount is determined.":["Establezca c\u00f3mo se determina el monto de la suscripci\u00f3n."],"Subscription Fixed Amount":["Monto fijo de suscripci\u00f3n"],"Recurring amount charged per billing interval.":["Monto recurrente cobrado por intervalo de facturaci\u00f3n."],"Subscription Amount Field":["Campo de Monto de Suscripci\u00f3n"],"Pick a form field whose value determines the subscription amount.":["Elija un campo de formulario cuyo valor determine el monto de la suscripci\u00f3n."],"Subscription Minimum Amount":["Monto M\u00ednimo de Suscripci\u00f3n"],"Minimum amount users can enter for subscription (0 for no minimum).":["Cantidad m\u00ednima que los usuarios pueden ingresar para la suscripci\u00f3n (0 para sin m\u00ednimo)."],"Pick a field from your form like a number, dropdown, multichoice, or hidden whose value should decide the payment amount.":["Elige un campo de tu formulario como un n\u00famero, un desplegable, una opci\u00f3n m\u00faltiple o un campo oculto cuyo valor deba determinar el monto del pago."]}}} \ No newline at end of file diff --git a/languages/sureforms-es_ES.mo b/languages/sureforms-es_ES.mo index 0a90dd027..bb4142e7f 100644 Binary files a/languages/sureforms-es_ES.mo and b/languages/sureforms-es_ES.mo differ diff --git a/languages/sureforms-es_ES.po b/languages/sureforms-es_ES.po index 0d8d897bd..585447fd5 100644 --- a/languages/sureforms-es_ES.po +++ b/languages/sureforms-es_ES.po @@ -106,13 +106,13 @@ msgstr "Editar %1$s" #: inc/ai-form-builder/ai-auth.php:93 #: inc/ai-form-builder/ai-auth.php:167 #: inc/background-process.php:112 -#: inc/create-new-form.php:101 +#: inc/create-new-form.php:102 #: inc/duplicate-form.php:176 #: inc/export.php:118 #: inc/export.php:176 #: inc/forms-data.php:88 #: inc/global-settings/global-settings.php:86 -#: inc/global-settings/global-settings.php:403 +#: inc/global-settings/global-settings.php:404 #: inc/rest-api.php:177 msgid "Nonce verification failed." msgstr "La verificación del nonce falló." @@ -388,7 +388,7 @@ msgid "Selected radio option" msgstr "Opción de radio seleccionada" #: inc/admin-ajax.php:341 -#: inc/create-new-form.php:63 +#: inc/create-new-form.php:64 #: assets/build/blocks.js:172 #: assets/build/formEditor.js:172 msgid "Submit" @@ -427,53 +427,53 @@ msgid "The message array was not supplied" msgstr "El arreglo de mensajes no fue proporcionado" #: inc/ai-form-builder/ai-form-builder.php:68 -#: inc/ai-form-builder/ai-form-builder.php:78 -#: inc/ai-form-builder/ai-helper.php:73 +#: inc/ai-form-builder/ai-form-builder.php:87 +#: inc/ai-form-builder/ai-helper.php:294 msgid "The SureForms AI Middleware encountered an error." msgstr "El middleware de SureForms AI encontró un error." -#: inc/ai-form-builder/ai-helper.php:95 +#: inc/ai-form-builder/ai-helper.php:91 msgid "Unable to get usage response." msgstr "No se puede obtener la respuesta de uso." -#: inc/ai-form-builder/ai-helper.php:148 +#: inc/ai-form-builder/ai-helper.php:145 msgid "The SureForms API server encountered an error." msgstr "El servidor de la API de SureForms encontró un error." -#: inc/ai-form-builder/ai-helper.php:174 -#: inc/ai-form-builder/ai-helper.php:206 +#: inc/ai-form-builder/ai-helper.php:167 +#: inc/ai-form-builder/ai-helper.php:199 msgid "An unknown error occurred." msgstr "Ocurrió un error desconocido." -#: inc/ai-form-builder/ai-helper.php:181 +#: inc/ai-form-builder/ai-helper.php:174 msgid "HTTP Request Failed" msgstr "Solicitud HTTP fallida" -#: inc/ai-form-builder/ai-helper.php:185 +#: inc/ai-form-builder/ai-helper.php:178 msgid "License Verification Failed" msgstr "Fallo en la verificación de la licencia" -#: inc/ai-form-builder/ai-helper.php:189 +#: inc/ai-form-builder/ai-helper.php:182 msgid "User Verification Failed" msgstr "Verificación de usuario fallida" -#: inc/ai-form-builder/ai-helper.php:193 +#: inc/ai-form-builder/ai-helper.php:186 msgid "Referer Mismatch" msgstr "Desajuste de Referente" -#: inc/ai-form-builder/ai-helper.php:197 +#: inc/ai-form-builder/ai-helper.php:190 msgid "Invalid Website URL" msgstr "URL del sitio web no válida" -#: inc/ai-form-builder/ai-helper.php:198 +#: inc/ai-form-builder/ai-helper.php:191 msgid "AI Form Builder does not work on localhost. Please try on a live website." msgstr "El constructor de formularios de IA no funciona en localhost. Por favor, inténtelo en un sitio web en vivo." -#: inc/ai-form-builder/ai-helper.php:201 +#: inc/ai-form-builder/ai-helper.php:194 msgid "Domain Verification Failed" msgstr "La verificación del dominio falló" -#: inc/ai-form-builder/ai-helper.php:205 +#: inc/ai-form-builder/ai-helper.php:198 msgid "Unknown Error" msgstr "Error desconocido" @@ -481,22 +481,18 @@ msgstr "Error desconocido" msgid "Submission id missing." msgstr "Falta el id de la presentación." -#: inc/create-new-form.php:113 +#: inc/create-new-form.php:114 msgid "Invalid JSON format." msgstr "Formato JSON inválido." -#: inc/create-new-form.php:125 +#: inc/create-new-form.php:126 msgid "Missing required properties in form info." msgstr "Faltan propiedades requeridas en la información del formulario." -#: inc/create-new-form.php:161 +#: inc/create-new-form.php:187 msgid "SureForms Form created successfully." msgstr "SureForms Formulario creado con éxito." -#: inc/create-new-form.php:168 -msgid "Error creating SureForms Form, " -msgstr "Error al crear el formulario de SureForms," - #: inc/email/email-template.php:46 msgid "New form submission" msgstr "Nueva presentación de formulario" @@ -558,7 +554,7 @@ msgstr "Número" msgid "Phone" msgstr "Teléfono" -#: inc/fields/textarea-markup.php:95 +#: inc/fields/textarea-markup.php:111 msgid "Textarea" msgstr "Área de texto" @@ -601,8 +597,8 @@ msgstr "No se encontraron formularios." #: inc/abilities/settings/get-global-settings.php:192 #: inc/global-settings/email-summary.php:571 -#: inc/global-settings/global-settings.php:250 -#: inc/global-settings/global-settings.php:456 +#: inc/global-settings/global-settings.php:251 +#: inc/global-settings/global-settings.php:457 #: assets/build/settings.js:172 msgid "Monday" msgstr "Lunes" @@ -7005,7 +7001,7 @@ msgstr "Vista de la calle" msgid "Strikethrough" msgstr "Tachado" -#: inc/fields/payment-markup.php:412 +#: inc/fields/payment-markup.php:513 #: modules/gutenberg/icons/icons-v6-3.php:1812 #: assets/build/payments.js:172 msgid "Stripe" @@ -11593,6 +11589,7 @@ msgstr "Construye tu primer formulario" msgid "Invalid nonce action or name." msgstr "Acción o nombre de nonce no válido." +#: inc/admin/editor-nudge.php:216 #: inc/helper.php:2029 #: inc/helper.php:2037 msgid "Invalid security token." @@ -11776,7 +11773,7 @@ msgstr "Explora SureDash" msgid "Something went wrong. We have logged the error for further investigation" msgstr "Algo salió mal. Hemos registrado el error para una investigación posterior." -#: inc/field-validation.php:273 +#: inc/field-validation.php:276 msgid "Field is not valid." msgstr "El campo no es válido." @@ -11934,82 +11931,82 @@ msgstr "No se proporcionaron datos de formularios para la importación." msgid "Invalid form data structure provided." msgstr "Estructura de datos del formulario no válida proporcionada." -#: inc/fields/payment-markup.php:249 +#: inc/fields/payment-markup.php:346 #: inc/payments/payment-helper.php:543 msgid "Subscription Plan" msgstr "Plan de suscripción" #. translators: 1: Amount with currency, 2: Interval (day/week/month/quarter/year) -#: inc/fields/payment-markup.php:288 +#: inc/fields/payment-markup.php:672 #, php-format msgid "%1$s per %2$s (until cancelled)" msgstr "%1$s por %2$s (hasta que se cancele)" #. translators: 1: Amount with currency, 2: Interval (day/week/month/quarter/year), 3: Number of billing cycles -#: inc/fields/payment-markup.php:297 +#: inc/fields/payment-markup.php:681 #, php-format msgid "%1$s per %2$s (%3$s payments)" msgstr "%1$s por %2$s (%3$s pagos)" #. translators: 1: Amount with currency, 2: Interval (day/week/month/quarter/year) -#: inc/fields/payment-markup.php:307 +#: inc/fields/payment-markup.php:691 #, php-format msgid "%1$s per %2$s" msgstr "%1$s por %2$s" #. translators: 1: Amount with currency placeholder, 2: Interval (day/week/month/quarter/year) -#: inc/fields/payment-markup.php:334 +#: inc/fields/payment-markup.php:714 #, php-format msgid "{amount} per %s (until cancelled)" msgstr "{amount} por %s (hasta que se cancele)" #. translators: 1: Amount with currency placeholder, 2: Interval (day/week/month/quarter/year), 3: Number of billing cycles -#: inc/fields/payment-markup.php:337 +#: inc/fields/payment-markup.php:717 #, php-format msgid "{amount} per %1$s (%2$s payments)" msgstr "{amount} por %1$s (%2$s pagos)" #. translators: 1: Amount with currency placeholder, 2: Interval (day/week/month/quarter/year) -#: inc/fields/payment-markup.php:340 +#: inc/fields/payment-markup.php:720 #, php-format msgid "{amount} per %s" msgstr "{amount} por %s" #. translators: %s: Minimum amount with currency -#: inc/fields/payment-markup.php:353 +#: inc/fields/payment-markup.php:740 #, php-format msgid "Minimum amount: %s" msgstr "Cantidad mínima: %s" -#: inc/fields/payment-markup.php:385 +#: inc/fields/payment-markup.php:486 msgid "Processing payment..." msgstr "Procesando el pago..." -#: inc/fields/payment-markup.php:579 +#: inc/fields/payment-markup.php:906 msgid "day" msgstr "día" -#: inc/fields/payment-markup.php:580 +#: inc/fields/payment-markup.php:907 msgid "week" msgstr "semana" -#: inc/fields/payment-markup.php:581 +#: inc/fields/payment-markup.php:908 msgid "month" msgstr "mes" -#: inc/fields/payment-markup.php:582 +#: inc/fields/payment-markup.php:909 msgid "quarter" msgstr "cuarto" -#: inc/fields/payment-markup.php:583 +#: inc/fields/payment-markup.php:910 msgid "year" msgstr "año" -#: inc/fields/payment-markup.php:608 +#: inc/fields/payment-markup.php:935 msgid "Test mode is enabled:" msgstr "El modo de prueba está habilitado:" -#: inc/fields/payment-markup.php:610 +#: inc/fields/payment-markup.php:937 msgid "Click here to enable live mode and accept payment" msgstr "Haz clic aquí para activar el modo en vivo y aceptar pagos" @@ -12192,6 +12189,7 @@ msgstr "Formulario desconocido" msgid "N/A" msgstr "No disponible" +#: inc/fields/payment-markup.php:247 #: inc/payments/admin/admin-handler.php:975 #: inc/payments/payment-history-shortcode.php:306 #: assets/build/blocks.js:172 @@ -12220,21 +12218,21 @@ msgstr "Desconocido" #: inc/payments/admin/admin-handler.php:1468 #: inc/payments/admin/admin-handler.php:1472 #: inc/payments/admin/admin-handler.php:1476 -#: inc/payments/front-end.php:811 -#: inc/payments/front-end.php:1209 +#: inc/payments/front-end.php:854 +#: inc/payments/front-end.php:1253 msgid "Guest User" msgstr "Usuario invitado" -#: inc/payments/front-end.php:91 +#: inc/payments/front-end.php:92 msgid "Invalid payment amount." msgstr "Monto de pago inválido." -#: inc/payments/front-end.php:107 +#: inc/payments/front-end.php:109 msgid "Valid customer email is required for payments." msgstr "Se requiere un correo electrónico válido del cliente para los pagos." -#: inc/payments/front-end.php:113 -#: inc/payments/front-end.php:320 +#: inc/payments/front-end.php:115 +#: inc/payments/front-end.php:340 #: inc/payments/stripe/admin-stripe-handler.php:877 #: inc/payments/stripe/payments-settings.php:349 #: inc/payments/stripe/payments-settings.php:474 @@ -12244,137 +12242,137 @@ msgstr "Se requiere un correo electrónico válido del cliente para los pagos." msgid "Stripe is not connected." msgstr "Stripe no está conectado." -#: inc/payments/front-end.php:119 -#: inc/payments/front-end.php:326 -#: inc/payments/front-end.php:610 -#: inc/payments/front-end.php:1099 +#: inc/payments/front-end.php:121 +#: inc/payments/front-end.php:346 +#: inc/payments/front-end.php:634 +#: inc/payments/front-end.php:1142 msgid "Stripe secret key not found." msgstr "Clave secreta de Stripe no encontrada." #. translators: %s: formatted payment amount -#: inc/payments/front-end.php:201 +#: inc/payments/front-end.php:203 #, php-format msgid "The payment amount (%s) is below the minimum allowed. Stripe only processes amounts above 50¢." msgstr "El monto del pago (%s) está por debajo del mínimo permitido. Stripe solo procesa montos superiores a 50¢." #. translators: %s: Field name -#: inc/payments/front-end.php:268 +#: inc/payments/front-end.php:273 #, php-format msgid "Missing required field: %s" msgstr "Falta el campo requerido: %s" -#: inc/payments/front-end.php:287 +#: inc/payments/front-end.php:292 msgid "Valid customer email is required for subscriptions." msgstr "Se requiere un correo electrónico válido del cliente para las suscripciones." -#: inc/payments/front-end.php:292 +#: inc/payments/front-end.php:297 msgid "Customer name is required for subscriptions." msgstr "Se requiere el nombre del cliente para las suscripciones." -#: inc/payments/front-end.php:308 +#: inc/payments/front-end.php:314 msgid "Amount must be greater than 0" msgstr "La cantidad debe ser mayor que 0" -#: inc/payments/front-end.php:314 +#: inc/payments/front-end.php:322 msgid "Invalid billing interval" msgstr "Intervalo de facturación no válido" -#: inc/payments/front-end.php:337 +#: inc/payments/front-end.php:357 msgid "Failed to create customer for subscription." msgstr "Error al crear el cliente para la suscripción." -#: inc/payments/front-end.php:370 -#: inc/payments/front-end.php:386 +#: inc/payments/front-end.php:390 +#: inc/payments/front-end.php:406 msgid "Failed to create subscription through middleware." msgstr "Error al crear la suscripción a través del middleware." -#: inc/payments/front-end.php:391 +#: inc/payments/front-end.php:411 msgid "Empty response from subscription creation." msgstr "Respuesta vacía de la creación de la suscripción." -#: inc/payments/front-end.php:396 +#: inc/payments/front-end.php:416 msgid "Invalid JSON response from subscription creation." msgstr "Respuesta JSON no válida de la creación de la suscripción." -#: inc/payments/front-end.php:400 -#: inc/payments/front-end.php:404 +#: inc/payments/front-end.php:420 +#: inc/payments/front-end.php:424 msgid "Invalid subscription data." msgstr "Datos de suscripción no válidos." -#: inc/payments/front-end.php:411 +#: inc/payments/front-end.php:431 msgid "Failed to create subscription." msgstr "Error al crear la suscripción." #. translators: %s: Error message -#: inc/payments/front-end.php:441 +#: inc/payments/front-end.php:464 #, php-format msgid "Unexpected error: %s" msgstr "Error inesperado: %s" -#: inc/payments/front-end.php:581 +#: inc/payments/front-end.php:604 #: inc/payments/stripe/admin-stripe-handler.php:103 #: inc/payments/stripe/admin-stripe-handler.php:184 #: inc/payments/stripe/admin-stripe-handler.php:489 msgid "Subscription ID not found." msgstr "ID de suscripción no encontrado." -#: inc/payments/front-end.php:599 +#: inc/payments/front-end.php:623 msgid "Customer ID not found for the payment." msgstr "ID de cliente no encontrado para el pago." -#: inc/payments/front-end.php:627 +#: inc/payments/front-end.php:651 msgid "Failed to retrieve setup intent." msgstr "Error al recuperar la intención de configuración." -#: inc/payments/front-end.php:656 +#: inc/payments/front-end.php:699 msgid "Failed to update subscription." msgstr "Error al actualizar la suscripción." -#: inc/payments/front-end.php:664 +#: inc/payments/front-end.php:707 msgid "Latest invoice not found on subscription." msgstr "Última factura no encontrada en la suscripción." -#: inc/payments/front-end.php:677 +#: inc/payments/front-end.php:720 msgid "Failed to retrieve invoice." msgstr "Error al recuperar la factura." -#: inc/payments/front-end.php:699 +#: inc/payments/front-end.php:742 msgid "Payment intent not found on invoice." msgstr "Intención de pago no encontrada en la factura." -#: inc/payments/front-end.php:714 +#: inc/payments/front-end.php:757 msgid "Failed to confirm payment." msgstr "Error al confirmar el pago." -#: inc/payments/front-end.php:730 +#: inc/payments/front-end.php:773 msgid "Failed to retrieve subscription." msgstr "Error al recuperar la suscripción." -#: inc/payments/front-end.php:745 +#: inc/payments/front-end.php:788 msgid "Subscription not found for the payment." msgstr "Suscripción no encontrada para el pago." #. translators: %d: User ID -#: inc/payments/front-end.php:809 -#: inc/payments/front-end.php:1209 +#: inc/payments/front-end.php:852 +#: inc/payments/front-end.php:1253 #, php-format msgid "User ID: %d" msgstr "ID de usuario: %d" #. translators: %s: Invoice status -#: inc/payments/front-end.php:817 +#: inc/payments/front-end.php:860 #, php-format msgid "Invoice Status: %s" msgstr "Estado de la factura: %s" #. translators: Title for subscription verification log -#: inc/payments/front-end.php:824 +#: inc/payments/front-end.php:867 msgid "Subscription Verification" msgstr "Verificación de suscripción" #. translators: %s: Subscription ID #. translators: %s: Stripe subscription ID -#: inc/payments/front-end.php:828 +#: inc/payments/front-end.php:871 #: inc/payments/stripe/admin-stripe-handler.php:119 #: inc/payments/stripe/admin-stripe-handler.php:204 #: inc/payments/stripe/admin-stripe-handler.php:505 @@ -12390,8 +12388,8 @@ msgstr "ID de suscripción: %s" #. 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:830 -#: inc/payments/front-end.php:1220 +#: inc/payments/front-end.php:873 +#: inc/payments/front-end.php:1264 #: inc/payments/stripe/admin-stripe-handler.php:124 #: inc/payments/stripe/admin-stripe-handler.php:209 #: inc/payments/stripe/admin-stripe-handler.php:510 @@ -12406,13 +12404,13 @@ msgid "Payment Gateway: %s" msgstr "Pasarela de Pago: %s" #. translators: %s: Payment Intent ID -#: inc/payments/front-end.php:832 +#: inc/payments/front-end.php:875 #, php-format msgid "Payment Intent ID: %s" msgstr "ID de intención de pago: %s" #. translators: %s: Charge ID -#: inc/payments/front-end.php:834 +#: inc/payments/front-end.php:877 #: inc/payments/stripe/stripe-webhook.php:1048 #, php-format msgid "Charge ID: %s" @@ -12420,7 +12418,7 @@ msgstr "ID de cargo: %s" #. translators: %s: Subscription Status #. translators: %s: subscription status -#: inc/payments/front-end.php:836 +#: inc/payments/front-end.php:879 #: inc/payments/stripe/admin-stripe-handler.php:129 #: inc/payments/stripe/admin-stripe-handler.php:214 #: inc/payments/stripe/admin-stripe-handler.php:515 @@ -12429,7 +12427,7 @@ msgid "Subscription Status: %s" msgstr "Estado de la suscripción: %s" #. translators: %s: Customer ID -#: inc/payments/front-end.php:838 +#: inc/payments/front-end.php:881 #: inc/payments/stripe/stripe-webhook.php:1122 #, php-format msgid "Customer ID: %s" @@ -12437,8 +12435,8 @@ msgstr "ID de cliente: %s" #. translators: 1: Amount, 2: Currency #. translators: %1$s: amount, %2$s: currency. -#: inc/payments/front-end.php:840 -#: inc/payments/front-end.php:1222 +#: inc/payments/front-end.php:883 +#: inc/payments/front-end.php:1266 #: inc/payments/stripe/stripe-webhook.php:1053 #: inc/payments/stripe/stripe-webhook.php:1114 #, php-format @@ -12447,34 +12445,34 @@ msgstr "Cantidad: %1$s %2$s" #. translators: %s: Payment mode (e.g. Live or Test) #. translators: %s: payment mode -#: inc/payments/front-end.php:843 -#: inc/payments/front-end.php:1227 +#: inc/payments/front-end.php:886 +#: inc/payments/front-end.php:1271 #, php-format msgid "Mode: %s" msgstr "Modo: %s" -#: inc/payments/front-end.php:877 +#: inc/payments/front-end.php:920 msgid "Failed to verify subscription." msgstr "Error al verificar la suscripción." -#: inc/payments/front-end.php:1131 -#: inc/payments/front-end.php:1149 -#: inc/payments/front-end.php:1157 -#: inc/payments/front-end.php:1164 +#: inc/payments/front-end.php:1175 +#: inc/payments/front-end.php:1193 +#: inc/payments/front-end.php:1201 +#: inc/payments/front-end.php:1208 msgid "Failed to retrieve payment intent." msgstr "Error al recuperar la intención de pago." -#: inc/payments/front-end.php:1172 +#: inc/payments/front-end.php:1216 msgid "Payment was not confirmed successfully." msgstr "El pago no se confirmó con éxito." -#: inc/payments/front-end.php:1214 +#: inc/payments/front-end.php:1258 msgid "Payment Verification" msgstr "Verificación de Pago" #. translators: %s: Stripe transaction ID #. translators: %s: Charge ID -#: inc/payments/front-end.php:1218 +#: inc/payments/front-end.php:1262 #: inc/payments/stripe/stripe-webhook.php:1110 #, php-format msgid "Transaction ID: %s" @@ -12482,18 +12480,18 @@ msgstr "ID de transacción: %s" #. translators: %s: payment status #. translators: %s: Status -#: inc/payments/front-end.php:1224 +#: inc/payments/front-end.php:1268 #: inc/payments/stripe/stripe-webhook.php:576 #: inc/payments/stripe/stripe-webhook.php:1116 #, php-format msgid "Status: %s" msgstr "Estado: %s" -#: inc/payments/front-end.php:1330 +#: inc/payments/front-end.php:1374 msgid "Failed to create Stripe customer." msgstr "Error al crear el cliente de Stripe." -#: inc/payments/front-end.php:1394 +#: inc/payments/front-end.php:1438 msgid "Failed to create Stripe guest customer." msgstr "Error al crear un cliente invitado de Stripe." @@ -12856,6 +12854,7 @@ msgstr "Error desconocido" msgid "Missing payment ID." msgstr "Falta el ID de pago." +#: inc/admin/editor-nudge.php:209 #: inc/payments/stripe/admin-stripe-handler.php:84 #: inc/payments/stripe/admin-stripe-handler.php:470 msgid "You are not allowed to perform this action." @@ -13535,10 +13534,6 @@ msgstr "Elegir campo de cantidad" msgid "Select a field…" msgstr "Seleccione un campo…" -#: assets/build/blocks.js:172 -msgid "Pick a field from your form like a number, dropdown, or multichoice whose value should decide the payment amount." -msgstr "Elige un campo de tu formulario como un número, un desplegable o una opción múltiple cuyo valor deba decidir el monto del pago." - #: assets/build/blocks.js:172 msgid "Minimum Amount" msgstr "Cantidad mínima" @@ -14118,6 +14113,7 @@ msgstr "Utiliza la IA para generar formularios al instante a partir de un simple msgid "Build engaging conversational, calculation, and multi-step forms." msgstr "Construye formularios conversacionales, de cálculo y de múltiples pasos atractivos." +#: inc/admin/editor-nudge.php:192 #: assets/build/forms.js:172 msgid "Create Form" msgstr "Crear formulario" @@ -14976,76 +14972,78 @@ msgstr "La publicación especificada no es un formulario de SureForms." msgid "Failed to create duplicate form." msgstr "Error al crear un formulario duplicado." -#: inc/payments/front-end.php:97 -#: inc/payments/front-end.php:298 -#: inc/payments/payment-helper.php:594 +#: inc/payments/front-end.php:98 +#: inc/payments/front-end.php:303 +#: inc/payments/payment-helper.php:595 msgid "Invalid form configuration." msgstr "Configuración de formulario no válida." -#: inc/payments/payment-helper.php:602 +#: inc/payments/payment-helper.php:603 msgid "Payment configuration not found for this form." msgstr "No se encontró la configuración de pago para este formulario." #. translators: 1: expected currency, 2: received currency -#: inc/payments/payment-helper.php:613 +#: inc/payments/payment-helper.php:614 #, php-format msgid "Currency mismatch: expected %1$s, received %2$s." msgstr "Desajuste de moneda: se esperaba %1$s, se recibió %2$s." #. translators: 1: expected amount with currency -#: inc/payments/payment-helper.php:630 +#: inc/payments/payment-helper.php:649 #, php-format msgid "Payment amount must be exactly %1$s." msgstr "El monto del pago debe ser exactamente %1$s." #. translators: 1: minimum amount with currency -#: inc/payments/payment-helper.php:641 +#: inc/payments/payment-helper.php:660 #, php-format msgid "Payment amount must be at least %1$s." msgstr "El monto del pago debe ser al menos %1$s." -#: inc/payments/payment-helper.php:717 +#: inc/payments/payment-helper.php:737 msgid "Invalid payment verification parameters." msgstr "Parámetros de verificación de pago no válidos." -#: inc/payments/payment-helper.php:728 +#: inc/payments/payment-helper.php:748 msgid "Payment verification failed. Invalid payment intent." msgstr "La verificación del pago falló. Intención de pago no válida." -#: inc/payments/payment-helper.php:814 -#: inc/payments/payment-helper.php:952 +#: inc/payments/payment-helper.php:903 +#: inc/payments/payment-helper.php:1043 msgid "Variable amount field configuration not found." msgstr "No se encontró la configuración del campo de cantidad variable." -#: inc/payments/payment-helper.php:835 +#: inc/payments/payment-helper.php:924 msgid "No payment options are configured for this field." msgstr "No hay opciones de pago configuradas para este campo." #. translators: %s: currency code -#: inc/payments/payment-helper.php:861 +#: inc/payments/payment-helper.php:950 msgid "Invalid payment amount. Please select a valid amount from the available options." msgstr "Monto de pago no válido. Por favor, seleccione un monto válido de las opciones disponibles." #. translators: %1$s: expected amount, %2$s: payment amount -#: inc/payments/payment-helper.php:896 +#: inc/payments/payment-helper.php:986 msgid "Payment configuration not found." msgstr "Configuración de pago no encontrada." #. translators: %1$s: expected amount, %2$s: payment amount -#: inc/payments/payment-helper.php:912 -#: inc/payments/payment-helper.php:964 -#: inc/payments/payment-helper.php:1000 +#: inc/payments/payment-helper.php:1003 +#: inc/payments/payment-helper.php:1055 +#: inc/payments/payment-helper.php:1091 +#: inc/payments/payment-helper.php:1111 #, php-format msgid "Payment amount mismatch. Expected %1$s, received %2$s." msgstr "Desajuste en el monto del pago. Se esperaba %1$s, se recibió %2$s." -#: inc/payments/payment-helper.php:941 -#: inc/payments/payment-helper.php:991 +#: 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." msgstr "Se requiere el valor del campo de cantidad variable." #. translators: %1$s: minimum amount, %2$s: payment amount -#: inc/payments/payment-helper.php:1012 +#: inc/payments/payment-helper.php:1125 #, php-format msgid "Payment amount below minimum. Minimum: %1$s, received %2$s." msgstr "Importe del pago por debajo del mínimo. Mínimo: %1$s, recibido %2$s." @@ -15107,7 +15105,7 @@ msgstr "Ocurrió un error al duplicar el formulario." msgid "This will create a copy of \"%s\" with all its settings." msgstr "Esto creará una copia de \"%s\" con todas sus configuraciones." -#: inc/fields/payment-markup.php:413 +#: inc/fields/payment-markup.php:514 msgid "Pay with credit or debit card" msgstr "Paga con tarjeta de crédito o débito" @@ -15115,8 +15113,8 @@ msgstr "Paga con tarjeta de crédito o débito" msgid "This form is not yet available. Please check back after the scheduled start time." msgstr "Este formulario aún no está disponible. Por favor, vuelva a consultar después de la hora de inicio programada." -#: inc/form-restriction.php:165 -#: inc/form-restriction.php:166 +#: inc/form-restriction.php:187 +#: inc/form-restriction.php:188 #: assets/build/formEditor.js:172 msgid "This form is no longer accepting submissions. The submission period has ended." msgstr "Este formulario ya no acepta envíos. El período de envío ha terminado." @@ -15131,7 +15129,7 @@ msgstr "Pasarela de pago no encontrada." msgid "Refund processing is not supported for %s gateway." msgstr "El procesamiento de reembolsos no es compatible con la pasarela %s." -#: inc/payments/payment-helper.php:974 +#: inc/payments/payment-helper.php:1065 msgid "Number field configuration not found." msgstr "No se encontró la configuración del campo numérico." @@ -15508,11 +15506,11 @@ msgstr "El título del formulario es obligatorio." msgid "At least one form field is required." msgstr "Se requiere al menos un campo de formulario." -#: inc/abilities/forms/create-form.php:322 +#: inc/abilities/forms/create-form.php:326 msgid "Failed to generate form fields from the provided data." msgstr "Error al generar los campos del formulario a partir de los datos proporcionados." -#: inc/abilities/forms/create-form.php:372 +#: inc/abilities/forms/create-form.php:376 msgid "Failed to create the form." msgstr "Error al crear el formulario." @@ -15688,23 +15686,23 @@ msgstr "La sesión de autenticación ha expirado. Por favor, inténtelo de nuevo msgid "Invalid access key format." msgstr "Formato de clave de acceso no válido." -#: inc/ai-form-builder/ai-helper.php:182 +#: inc/ai-form-builder/ai-helper.php:175 msgid "Unable to connect to SureForms API. Please check your connection." msgstr "No se puede conectar a la API de SureForms. Por favor, verifique su conexión." -#: inc/ai-form-builder/ai-helper.php:186 +#: inc/ai-form-builder/ai-helper.php:179 msgid "Unable to verify license. Please check your license key." msgstr "No se puede verificar la licencia. Por favor, revise su clave de licencia." -#: inc/ai-form-builder/ai-helper.php:190 +#: inc/ai-form-builder/ai-helper.php:183 msgid "An error occurred while trying to verify your email. Please check your email you have used to log in or sign up on billing.sureforms.com." msgstr "Se produjo un error al intentar verificar tu correo electrónico. Por favor, revisa el correo electrónico que has utilizado para iniciar sesión o registrarte en billing.sureforms.com." -#: inc/ai-form-builder/ai-helper.php:194 +#: inc/ai-form-builder/ai-helper.php:187 msgid "Unable to verify referer. Please check your referer." msgstr "No se puede verificar el referer. Por favor, revise su referer." -#: inc/ai-form-builder/ai-helper.php:202 +#: inc/ai-form-builder/ai-helper.php:195 msgid "Domain Verification Failed on current site. Please try again on another website." msgstr "La verificación de dominio falló en el sitio actual. Por favor, inténtelo de nuevo en otro sitio web." @@ -15730,8 +15728,8 @@ msgstr "Doy mi consentimiento para que este sitio web almacene mi información p msgid "Text field" msgstr "Campo de texto" -#: inc/form-restriction.php:160 -#: inc/form-restriction.php:161 +#: inc/form-restriction.php:182 +#: inc/form-restriction.php:183 #: inc/post-types.php:1203 #: inc/post-types.php:1243 msgid "This form is not yet available. Check back after the scheduled start time." @@ -15741,8 +15739,8 @@ msgstr "Este formulario aún no está disponible. Vuelve a consultar después de #: inc/form-submit.php:400 #: inc/form-submit.php:445 #: inc/form-submit.php:968 -#: inc/payments/front-end.php:77 -#: inc/payments/front-end.php:258 +#: 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 @@ -16097,32 +16095,32 @@ msgid "Enter a valid email address." msgstr "Introduce una dirección de correo electrónico válida." #. translators: %s represents the minimum acceptable value -#: inc/translatable.php:94 +#: inc/translatable.php:97 #, php-format msgid "Minimum value is %s." msgstr "El valor mínimo es %s." #. translators: %s represents the maximum acceptable value -#: inc/translatable.php:97 +#: inc/translatable.php:100 #, php-format msgid "Maximum value is %s." msgstr "El valor máximo es %s." #. translators: %s represents the minimum number of options to select -#: inc/translatable.php:100 -#: inc/translatable.php:106 +#: inc/translatable.php:103 +#: inc/translatable.php:109 #, php-format msgid "Select at least %s options." msgstr "Seleccione al menos %s opciones." #. translators: %s represents the maximum number of options that can be selected -#: inc/translatable.php:103 -#: inc/translatable.php:109 +#: inc/translatable.php:106 +#: inc/translatable.php:112 #, php-format msgid "You can select up to %s options." msgstr "Puedes seleccionar hasta %s opciones." -#: inc/translatable.php:120 +#: inc/translatable.php:123 msgid "This form is now closed as we have reached the maximum number of entries." msgstr "Este formulario está ahora cerrado ya que hemos alcanzado el número máximo de entradas." @@ -16649,35 +16647,35 @@ msgstr "Recuperar la configuración global de SureForms. Opcionalmente filtrar p msgid "Setting categories to retrieve. Omit for all categories." msgstr "Estableciendo categorías para recuperar. Omita para todas las categorías." -#: inc/abilities/settings/update-global-settings.php:105 +#: inc/abilities/settings/update-global-settings.php:106 msgid "Update Global Settings" msgstr "Actualizar configuraciones globales" -#: inc/abilities/settings/update-global-settings.php:106 +#: inc/abilities/settings/update-global-settings.php:107 msgid "Update SureForms global settings for a specific category: general, validation-messages, email-summary, or security." msgstr "Actualiza la configuración global de SureForms para una categoría específica: general, mensajes de validación, resumen de correo electrónico o seguridad." -#: inc/abilities/settings/update-global-settings.php:139 +#: inc/abilities/settings/update-global-settings.php:140 msgid "The settings category to update." msgstr "La categoría de configuración a actualizar." -#: inc/abilities/settings/update-global-settings.php:144 +#: inc/abilities/settings/update-global-settings.php:145 msgid "Key-value pairs of settings to update." msgstr "Pares clave-valor de configuraciones para actualizar." -#: inc/abilities/settings/update-global-settings.php:180 +#: inc/abilities/settings/update-global-settings.php:181 msgid "Settings category is required." msgstr "La categoría de configuración es obligatoria." -#: inc/abilities/settings/update-global-settings.php:188 +#: inc/abilities/settings/update-global-settings.php:189 msgid "Settings data is required." msgstr "Se requieren los datos de configuración." -#: inc/abilities/settings/update-global-settings.php:199 +#: inc/abilities/settings/update-global-settings.php:200 msgid "No valid settings keys provided for this category." msgstr "No se proporcionaron claves de configuración válidas para esta categoría." -#: inc/abilities/settings/update-global-settings.php:225 +#: inc/abilities/settings/update-global-settings.php:226 msgid "Invalid settings category." msgstr "Categoría de configuración no válida." @@ -17578,6 +17576,212 @@ msgstr "Złoty polaco" msgid "Dynamic Default Value" msgstr "Valor Predeterminado Dinámico" +#: inc/admin/editor-nudge.php:191 +msgid "Hey! It looks like you're creating a form. Build a ready-to-use form in under 30 seconds with SureForms AI, with no extra setup required." +msgstr "¡Hola! Parece que estás creando un formulario. Crea un formulario listo para usar en menos de 30 segundos con SureForms AI, sin necesidad de configuración adicional." + +#: inc/admin/editor-nudge.php:228 +#: inc/admin/editor-nudge.php:237 +msgid "Invalid post." +msgstr "Publicación no válida." + +#: inc/admin/editor-nudge.php:246 +msgid "You cannot edit this post." +msgstr "No puedes editar esta publicación." + +#: inc/ai-form-builder/ai-form-builder.php:96 +msgid "The AI did not return a form. Please refine your prompt and try again." +msgstr "La IA no devolvió un formulario. Por favor, refine su solicitud e intente de nuevo." + +#: inc/ai-form-builder/ai-form-builder.php:104 +msgid "The AI response is missing a form title. Please try again." +msgstr "La respuesta de la IA no tiene un título de formulario. Por favor, inténtalo de nuevo." + +#: inc/ai-form-builder/ai-form-builder.php:115 +#: inc/ai-form-builder/field-mapping.php:69 +msgid "The AI was unable to generate form fields. Please try again." +msgstr "La IA no pudo generar los campos del formulario. Por favor, inténtelo de nuevo." + +#: inc/ai-form-builder/field-mapping.php:41 +msgid "The AI form data is missing. Please try again." +msgstr "Faltan los datos del formulario de IA. Por favor, inténtalo de nuevo." + +#: inc/ai-form-builder/field-mapping.php:51 +msgid "The AI form data is not in the expected format." +msgstr "Los datos del formulario de IA no están en el formato esperado." + +#: inc/ai-form-builder/field-mapping.php:60 +msgid "The AI response did not include a form. Please try again." +msgstr "La respuesta de la IA no incluyó un formulario. Por favor, inténtalo de nuevo." + +#: inc/ai-form-builder/field-mapping.php:90 +msgid "The AI returned a malformed form field. Please try again." +msgstr "La IA devolvió un campo de formulario malformado. Por favor, inténtalo de nuevo." + +#: inc/create-new-form.php:160 +#: inc/create-new-form.php:173 +msgid "Error creating SureForms Form." +msgstr "Error al crear el formulario de SureForms." + +#. translators: %s represents the minimum number of characters required +#: inc/field-validation.php:289 +#: inc/translatable.php:94 +#, php-format +msgid "Please enter at least %s characters." +msgstr "Por favor, introduce al menos %s caracteres." + +#: inc/fields/payment-markup.php:246 +msgid "One-Time Payment" +msgstr "Pago único" + +#: inc/fields/payment-markup.php:562 +msgid "Choose payment type" +msgstr "Elige el tipo de pago" + +#: inc/payments/front-end.php:333 +msgid "Billing interval does not match the form configuration." +msgstr "El intervalo de facturación no coincide con la configuración del formulario." + +#: inc/payments/payment-helper.php:627 +msgid "Payment type does not match the form configuration." +msgstr "El tipo de pago no coincide con la configuración del formulario." + +#: inc/payments/payment-helper.php:760 +msgid "Payment verification failed. Payment type mismatch." +msgstr "La verificación de pago falló. Incompatibilidad en el tipo de pago." + +#: assets/build/blocks.js:172 +msgid "Minimum Characters" +msgstr "Caracteres mínimos" + +#: assets/build/blocks.js:172 +msgid "Minimum characters cannot exceed Maximum characters." +msgstr "Los caracteres mínimos no pueden exceder los caracteres máximos." + +#: assets/build/blocks.js:172 +msgid "Both" +msgstr "Ambos" + +#: assets/build/blocks.js:172 +msgid "One-Time Label" +msgstr "Etiqueta de un solo uso" + +#: assets/build/blocks.js:172 +msgid "Label shown to users for the one-time payment option." +msgstr "Etiqueta mostrada a los usuarios para la opción de pago único." + +#: assets/build/blocks.js:172 +msgid "Subscription Label" +msgstr "Etiqueta de suscripción" + +#: assets/build/blocks.js:172 +msgid "Label shown to users for the subscription option." +msgstr "Etiqueta mostrada a los usuarios para la opción de suscripción." + +#: assets/build/blocks.js:172 +msgid "Default Selection" +msgstr "Selección predeterminada" + +#: assets/build/blocks.js:172 +msgid "Which option is pre-selected when the form loads." +msgstr "¿Qué opción está preseleccionada cuando se carga el formulario?" + +#: assets/build/blocks.js:172 +msgid "One-Time Amount Type" +msgstr "Tipo de Monto Único" + +#: assets/build/blocks.js:172 +msgid "Set how the one-time payment amount is determined." +msgstr "Establezca cómo se determina el monto del pago único." + +#: assets/build/blocks.js:172 +msgid "One-Time Fixed Amount" +msgstr "Monto fijo único" + +#: assets/build/blocks.js:172 +msgid "Amount charged for a one-time payment." +msgstr "Cantidad cobrada por un pago único." + +#: assets/build/blocks.js:172 +msgid "One-Time Amount Field" +msgstr "Campo de Monto Único" + +#: assets/build/blocks.js:172 +msgid "Pick a form field whose value determines the one-time payment amount." +msgstr "Elija un campo de formulario cuyo valor determine el monto del pago único." + +#: assets/build/blocks.js:172 +msgid "One-Time Minimum Amount" +msgstr "Monto mínimo único" + +#: assets/build/blocks.js:172 +msgid "Minimum amount users can enter for one-time payment (0 for no minimum)." +msgstr "Monto mínimo que los usuarios pueden ingresar para un pago único (0 para sin mínimo)." + +#: assets/build/blocks.js:172 +msgid "Subscription Amount Type" +msgstr "Tipo de Monto de Suscripción" + +#: assets/build/blocks.js:172 +msgid "Set how the subscription amount is determined." +msgstr "Establezca cómo se determina el monto de la suscripción." + +#: assets/build/blocks.js:172 +msgid "Subscription Fixed Amount" +msgstr "Monto fijo de suscripción" + +#: assets/build/blocks.js:172 +msgid "Recurring amount charged per billing interval." +msgstr "Monto recurrente cobrado por intervalo de facturación." + +#: assets/build/blocks.js:172 +msgid "Subscription Amount Field" +msgstr "Campo de Monto de Suscripción" + +#: assets/build/blocks.js:172 +msgid "Pick a form field whose value determines the subscription amount." +msgstr "Elija un campo de formulario cuyo valor determine el monto de la suscripción." + +#: assets/build/blocks.js:172 +msgid "Subscription Minimum Amount" +msgstr "Monto Mínimo de Suscripción" + +#: assets/build/blocks.js:172 +msgid "Minimum amount users can enter for subscription (0 for no minimum)." +msgstr "Cantidad mínima que los usuarios pueden ingresar para la suscripción (0 para sin mínimo)." + +#: 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 "Elige un campo de tu formulario como un número, un desplegable, una opción múltiple o un campo oculto cuyo valor deba determinar el monto del pago." + +#: assets/build/templatePicker.js:172 +msgid "You do not have permission to create forms." +msgstr "No tienes permiso para crear formularios." + +#: assets/build/templatePicker.js:172 +msgid "The form could not be saved. Please try again." +msgstr "El formulario no se pudo guardar. Por favor, inténtelo de nuevo." + +#: assets/build/templatePicker.js:172 +msgid "Unable to reach the SureForms AI service. Please check your connection and try again." +msgstr "No se puede acceder al servicio de SureForms AI. Por favor, verifique su conexión e inténtelo de nuevo." + +#: assets/build/templatePicker.js:172 +msgid "The AI service did not return a response. Please try again." +msgstr "El servicio de IA no devolvió una respuesta. Por favor, inténtelo de nuevo." + +#: assets/build/templatePicker.js:172 +msgid "Form generation failed. Please try again." +msgstr "La generación del formulario falló. Por favor, inténtelo de nuevo." + +#: assets/build/templatePicker.js:172 +msgid "The AI response was empty. Please refine your prompt and try again." +msgstr "La respuesta de la IA estaba vacía. Por favor, refine su solicitud y vuelva a intentarlo." + +#: assets/build/templatePicker.js:172 +msgid "Unable to build form fields from the AI response." +msgstr "No se pueden construir los campos del formulario a partir de la respuesta de la IA." + #: inc/post-types.php:205 msgctxt "post type general name" msgid "Forms" @@ -18036,7 +18240,7 @@ msgstr "día" #: inc/payments/payment-history-shortcode.php:844 msgctxt "billing interval" msgid "wk" -msgstr "" +msgstr "wk" #: inc/payments/payment-history-shortcode.php:845 msgctxt "billing interval" diff --git a/languages/sureforms-fr_FR-120a6dad015d3891c70f578c2251576b.json b/languages/sureforms-fr_FR-120a6dad015d3891c70f578c2251576b.json index 4d974bae5..8ad340bdb 100644 --- a/languages/sureforms-fr_FR-120a6dad015d3891c70f578c2251576b.json +++ b/languages/sureforms-fr_FR-120a6dad015d3891c70f578c2251576b.json @@ -1 +1 @@ -{"translation-revision-date":"2024-12-13T13:12:49+00:00","generator":"WP-CLI\/2.12.0","source":"assets\/build\/templatePicker.js","domain":"messages","locale_data":{"messages":{"":{"domain":"messages","lang":"en","plural-forms":"nplurals=2; plural=(n != 1);"},"Dashboard":["Tableau de bord"],"Connect Now":["Connectez-vous maintenant"],"Authentication Failed":["\u00c9chec de l'authentification"],"Contact Support":["Contacter le support"],"Click Here to Retry":["Cliquez ici pour r\u00e9essayer"],"Exit to Dashboard":["Quitter vers le tableau de bord"],"AI Form Builder":["G\u00e9n\u00e9rateur de formulaires IA"],"Speech recognition is not supported in your current browser. Please use Google Chrome \/ Safari.":["La reconnaissance vocale n'est pas prise en charge dans votre navigateur actuel. Veuillez utiliser Google Chrome \/ Safari."],"Please allow microphone access to use voice input.":["Veuillez autoriser l'acc\u00e8s au microphone pour utiliser la saisie vocale."],"Voice Input":["Entr\u00e9e vocale"],"Try Again":["R\u00e9essayez"],"Please try again after %s.":["Veuillez r\u00e9essayer apr\u00e8s %s."],"You have reached the maximum number of form generations in your Free Plan.":["Vous avez atteint le nombre maximum de g\u00e9n\u00e9rations de formulaires dans votre Plan Gratuit."],"Unlock Conversational Forms":["D\u00e9verrouiller les formulaires conversationnels"],"Simple":["Simple"],"Upgrade Now":["Mettez \u00e0 niveau maintenant"],"Generate with AI":["G\u00e9n\u00e9rer avec l'IA"],"Please check your username and password for the account, and try to reconnect again. Need help?":["Veuillez v\u00e9rifier votre nom d'utilisateur et votre mot de passe pour le compte, et essayez de vous reconnecter. Besoin d'aide ?"],"Describe the form you want to create":["D\u00e9crivez le formulaire que vous souhaitez cr\u00e9er"],"We are building your form\u2026":["Nous construisons votre formulaire\u2026"],"Payment":["Paiement"],"and ":["et"],"more\u2026":["plus\u2026"],"Calculations":["Calculs"],"Unlock Calculator Forms":["D\u00e9verrouiller les formulaires de calculatrice"],"Build Smart Forms That Calculate Instantly":["Cr\u00e9ez des formulaires intelligents qui calculent instantan\u00e9ment"],"Empower your forms with advanced calculations. From loan calculators to BMI checkers - create interactive forms that give real-time results.":["Donnez plus de puissance \u00e0 vos formulaires avec des calculs avanc\u00e9s. Des calculateurs de pr\u00eat aux v\u00e9rificateurs d'IMC - cr\u00e9ez des formulaires interactifs qui fournissent des r\u00e9sultats en temps r\u00e9el."],"Add complex formulas with ease":["Ajoutez des formules complexes en toute simplicit\u00e9"],"Provide instant answers to users":["Fournir des r\u00e9ponses instantan\u00e9es aux utilisateurs"],"Perfect for finance, health, and pricing forms":["Parfait pour les formulaires de finance, de sant\u00e9 et de tarification"],"Conversational":["Conversationnel"],"Turn Simple Forms Into Conversations":["Transformez les formulaires simples en conversations"],"Transform boring forms into friendly, chat-like experiences. Ask one question at a time, just like a real conversation, and see higher engagement.":["Transformez les formulaires ennuyeux en exp\u00e9riences conviviales, semblables \u00e0 une conversation. Posez une question \u00e0 la fois, comme dans une vraie conversation, et constatez un engagement accru."],"One question at a time, in chat flow":["Une question \u00e0 la fois, dans le flux de discussion"],"More engaging than traditional forms":["Plus engageant que les formes traditionnelles"],"Boosts completion rates with a friendly interface":["Augmente les taux de compl\u00e9tion avec une interface conviviale"],"Select this if you need calculations in your form. For example: Loan interest calculator.":["S\u00e9lectionnez ceci si vous avez besoin de calculs dans votre formulaire. Par exemple : Calculateur d'int\u00e9r\u00eats de pr\u00eat."],"Select this if you want your form to display one question at a time, like a chat.":["S\u00e9lectionnez ceci si vous souhaitez que votre formulaire affiche une question \u00e0 la fois, comme une conversation."],"Select this if you want to collect payments through your form.":["S\u00e9lectionnez ceci si vous souhaitez collecter des paiements via votre formulaire."],"%d AI Generations Left. SureForms Premium allows:":["Il reste %d g\u00e9n\u00e9rations d'IA. SureForms Premium permet :"],"%d AI Generations Left, Connect to SureForms AI to Get 10 More":["%d g\u00e9n\u00e9rations d'IA restantes, connectez-vous \u00e0 SureForms AI pour en obtenir 10 de plus"],"%d AI Generations Left. Upgrade to SureForms Premium":["Il reste %d g\u00e9n\u00e9rations d'IA. Passez \u00e0 SureForms Premium"],"Contact form to collect name, email, and message from visitors":["Formulaire de contact pour recueillir le nom, l'email et le message des visiteurs"],"Job application form for \"Marketing Manager\" with resume upload":["Formulaire de candidature pour le poste de \"Responsable Marketing\" avec t\u00e9l\u00e9chargement de CV"],"Feedback form to ask customers: \"How would you rate our product and what should we improve?\"":["Formulaire de retour pour demander aux clients : \"Comment \u00e9valueriez-vous notre produit et que devrions-nous am\u00e9liorer ?\""],"Event registration form for \"Photography Workshop\" with date and seat selection":["Formulaire d'inscription \u00e0 l'\u00e9v\u00e9nement pour \"Atelier de photographie\" avec s\u00e9lection de date et de si\u00e8ge"],"Newsletter signup form with name and email to join mailing list":["Formulaire d'inscription \u00e0 la newsletter avec nom et email pour rejoindre la liste de diffusion"],"Order form for \"Custom T-Shirt\" with size, color, and quantity options":["Formulaire de commande pour \"T-shirt personnalis\u00e9\" avec options de taille, couleur et quantit\u00e9"],"Survey form: \"How satisfied are you with our service? (1\u20135 stars)\"":["Formulaire d'enqu\u00eate : \"Dans quelle mesure \u00eates-vous satisfait de notre service ? (1\u20135 \u00e9toiles)\""],"Appointment booking form for \"Consultation Call\" with preferred time":["Formulaire de r\u00e9servation de rendez-vous pour \"Appel de consultation\" avec heure pr\u00e9f\u00e9r\u00e9e"],"Describe the form that you want":["D\u00e9crivez la forme que vous souhaitez"],"Generate":["G\u00e9n\u00e9rer"],"Create Unlimited Forms with AI":["Cr\u00e9ez des formulaires illimit\u00e9s avec l'IA"],"Add Advanced Field Types":["Ajouter des types de champs avanc\u00e9s"],"Create Calculators, Surveys, etc.":["Cr\u00e9ez des calculatrices, des sondages, etc."],"Form Generation Limit Reached":["Limite de g\u00e9n\u00e9ration de formulaire atteinte"],"You have reached the maximum number of form generations in your Free Plan. SureForms Premium allows:":["Vous avez atteint le nombre maximum de g\u00e9n\u00e9rations de formulaires dans votre plan gratuit. SureForms Premium permet :"],"%s AI Generations Left.":["Il reste %s g\u00e9n\u00e9rations d'IA."],"Unlock Unlimited Generations":["D\u00e9verrouillez des G\u00e9n\u00e9rations Illimit\u00e9es"],"Connect to SureForms AI":["Connectez-vous \u00e0 SureForms AI"],"You Have Hit Your Free Limit.":["Vous avez atteint votre limite gratuite."],"Connect to SureForms AI to Get 10 More.":["Connectez-vous \u00e0 SureForms AI pour obtenir 10 de plus."],"Or create it yourself":["Ou cr\u00e9ez-le vous-m\u00eame"],"Unable to create form":["Impossible de cr\u00e9er le formulaire"],"Something went wrong. Please try again.":["Un probl\u00e8me est survenu. Veuillez r\u00e9essayer."],"Describe what kind of form you want":["D\u00e9crivez le type de formulaire que vous souhaitez"],"Click to generate the form":["Cliquez pour g\u00e9n\u00e9rer le formulaire"],"Connecting to AI service":["Connexion au service d'IA"],"Generating fields":["G\u00e9n\u00e9ration des champs"],"Finalizing your form":["Finalisation de votre formulaire"],"Opening form editor":["Ouverture de l'\u00e9diteur de formulaire"],"Design Multistep Forms":["Concevoir des formulaires \u00e0 plusieurs \u00e9tapes"],"Send Form Entries to Your CRM or Any App":["Envoyez les entr\u00e9es de formulaire \u00e0 votre CRM ou \u00e0 n'importe quelle application"],"You've reached your daily generation limit.":["Vous avez atteint votre limite quotidienne de g\u00e9n\u00e9ration."],"You've reached your daily limit for AI form generations.":["Vous avez atteint votre limite quotidienne pour les g\u00e9n\u00e9rations de formulaires d'IA."],"Quiz":["Quiz"],"Unlock Quiz Forms":["D\u00e9verrouiller les formulaires de quiz"],"Create Engaging Quizzes That Score Automatically":["Cr\u00e9ez des quiz engageants qui se notent automatiquement"],"Build interactive quizzes with scored questions and graded results. Perfect for assessments, trivia, and educational content.":["Cr\u00e9ez des quiz interactifs avec des questions not\u00e9es et des r\u00e9sultats \u00e9valu\u00e9s. Parfait pour les \u00e9valuations, les jeux de culture g\u00e9n\u00e9rale et le contenu \u00e9ducatif."],"Auto-score responses instantly":["\u00c9valuer automatiquement les r\u00e9ponses instantan\u00e9ment"],"Display graded results to users":["Afficher les r\u00e9sultats not\u00e9s aux utilisateurs"],"Perfect for education, training, and fun trivia":["Parfait pour l'\u00e9ducation, la formation et les quiz amusants"],"Select this to create a quiz with scored questions and graded results.":["S\u00e9lectionnez ceci pour cr\u00e9er un quiz avec des questions not\u00e9es et des r\u00e9sultats \u00e9valu\u00e9s."],"Select this to create a survey to collect responses and opinions.":["S\u00e9lectionnez ceci pour cr\u00e9er un sondage afin de recueillir des r\u00e9ponses et des opinions."],"Survey":["Enqu\u00eate"],"Unlock Survey Forms":["D\u00e9verrouiller les formulaires d'enqu\u00eate"],"Collect Insights with Powerful Surveys":["Recueillez des informations avec des enqu\u00eates puissantes"],"Create surveys to collect responses and opinions. Visualize results with charts and share aggregated insights with your audience.":["Cr\u00e9ez des enqu\u00eates pour recueillir des r\u00e9ponses et des opinions. Visualisez les r\u00e9sultats avec des graphiques et partagez des insights agr\u00e9g\u00e9s avec votre audience."],"Aggregate and visualize responses":["Agr\u00e9ger et visualiser les r\u00e9ponses"],"Show live results to respondents":["Afficher les r\u00e9sultats en direct aux r\u00e9pondants"],"Perfect for feedback, polls, and research":["Parfait pour les retours, les sondages et la recherche"]}}} \ No newline at end of file +{"translation-revision-date":"2024-12-13T13:12:49+00:00","generator":"WP-CLI\/2.12.0","source":"assets\/build\/templatePicker.js","domain":"messages","locale_data":{"messages":{"":{"domain":"messages","lang":"en","plural-forms":"nplurals=2; plural=(n != 1);"},"Dashboard":["Tableau de bord"],"Connect Now":["Connectez-vous maintenant"],"Authentication Failed":["\u00c9chec de l'authentification"],"Contact Support":["Contacter le support"],"Click Here to Retry":["Cliquez ici pour r\u00e9essayer"],"Exit to Dashboard":["Quitter vers le tableau de bord"],"AI Form Builder":["G\u00e9n\u00e9rateur de formulaires IA"],"Speech recognition is not supported in your current browser. Please use Google Chrome \/ Safari.":["La reconnaissance vocale n'est pas prise en charge dans votre navigateur actuel. Veuillez utiliser Google Chrome \/ Safari."],"Please allow microphone access to use voice input.":["Veuillez autoriser l'acc\u00e8s au microphone pour utiliser la saisie vocale."],"Voice Input":["Entr\u00e9e vocale"],"Try Again":["R\u00e9essayez"],"Please try again after %s.":["Veuillez r\u00e9essayer apr\u00e8s %s."],"You have reached the maximum number of form generations in your Free Plan.":["Vous avez atteint le nombre maximum de g\u00e9n\u00e9rations de formulaires dans votre Plan Gratuit."],"Unlock Conversational Forms":["D\u00e9verrouiller les formulaires conversationnels"],"Simple":["Simple"],"Upgrade Now":["Mettez \u00e0 niveau maintenant"],"Generate with AI":["G\u00e9n\u00e9rer avec l'IA"],"Please check your username and password for the account, and try to reconnect again. Need help?":["Veuillez v\u00e9rifier votre nom d'utilisateur et votre mot de passe pour le compte, et essayez de vous reconnecter. Besoin d'aide ?"],"Describe the form you want to create":["D\u00e9crivez le formulaire que vous souhaitez cr\u00e9er"],"We are building your form\u2026":["Nous construisons votre formulaire\u2026"],"Payment":["Paiement"],"and ":["et"],"more\u2026":["plus\u2026"],"Calculations":["Calculs"],"Unlock Calculator Forms":["D\u00e9verrouiller les formulaires de calculatrice"],"Build Smart Forms That Calculate Instantly":["Cr\u00e9ez des formulaires intelligents qui calculent instantan\u00e9ment"],"Empower your forms with advanced calculations. From loan calculators to BMI checkers - create interactive forms that give real-time results.":["Donnez plus de puissance \u00e0 vos formulaires avec des calculs avanc\u00e9s. Des calculateurs de pr\u00eat aux v\u00e9rificateurs d'IMC - cr\u00e9ez des formulaires interactifs qui fournissent des r\u00e9sultats en temps r\u00e9el."],"Add complex formulas with ease":["Ajoutez des formules complexes en toute simplicit\u00e9"],"Provide instant answers to users":["Fournir des r\u00e9ponses instantan\u00e9es aux utilisateurs"],"Perfect for finance, health, and pricing forms":["Parfait pour les formulaires de finance, de sant\u00e9 et de tarification"],"Conversational":["Conversationnel"],"Turn Simple Forms Into Conversations":["Transformez les formulaires simples en conversations"],"Transform boring forms into friendly, chat-like experiences. Ask one question at a time, just like a real conversation, and see higher engagement.":["Transformez les formulaires ennuyeux en exp\u00e9riences conviviales, semblables \u00e0 une conversation. Posez une question \u00e0 la fois, comme dans une vraie conversation, et constatez un engagement accru."],"One question at a time, in chat flow":["Une question \u00e0 la fois, dans le flux de discussion"],"More engaging than traditional forms":["Plus engageant que les formes traditionnelles"],"Boosts completion rates with a friendly interface":["Augmente les taux de compl\u00e9tion avec une interface conviviale"],"Select this if you need calculations in your form. For example: Loan interest calculator.":["S\u00e9lectionnez ceci si vous avez besoin de calculs dans votre formulaire. Par exemple : Calculateur d'int\u00e9r\u00eats de pr\u00eat."],"Select this if you want your form to display one question at a time, like a chat.":["S\u00e9lectionnez ceci si vous souhaitez que votre formulaire affiche une question \u00e0 la fois, comme une conversation."],"Select this if you want to collect payments through your form.":["S\u00e9lectionnez ceci si vous souhaitez collecter des paiements via votre formulaire."],"%d AI Generations Left. SureForms Premium allows:":["Il reste %d g\u00e9n\u00e9rations d'IA. SureForms Premium permet :"],"%d AI Generations Left, Connect to SureForms AI to Get 10 More":["%d g\u00e9n\u00e9rations d'IA restantes, connectez-vous \u00e0 SureForms AI pour en obtenir 10 de plus"],"%d AI Generations Left. Upgrade to SureForms Premium":["Il reste %d g\u00e9n\u00e9rations d'IA. Passez \u00e0 SureForms Premium"],"Contact form to collect name, email, and message from visitors":["Formulaire de contact pour recueillir le nom, l'email et le message des visiteurs"],"Job application form for \"Marketing Manager\" with resume upload":["Formulaire de candidature pour le poste de \"Responsable Marketing\" avec t\u00e9l\u00e9chargement de CV"],"Feedback form to ask customers: \"How would you rate our product and what should we improve?\"":["Formulaire de retour pour demander aux clients : \"Comment \u00e9valueriez-vous notre produit et que devrions-nous am\u00e9liorer ?\""],"Event registration form for \"Photography Workshop\" with date and seat selection":["Formulaire d'inscription \u00e0 l'\u00e9v\u00e9nement pour \"Atelier de photographie\" avec s\u00e9lection de date et de si\u00e8ge"],"Newsletter signup form with name and email to join mailing list":["Formulaire d'inscription \u00e0 la newsletter avec nom et email pour rejoindre la liste de diffusion"],"Order form for \"Custom T-Shirt\" with size, color, and quantity options":["Formulaire de commande pour \"T-shirt personnalis\u00e9\" avec options de taille, couleur et quantit\u00e9"],"Survey form: \"How satisfied are you with our service? (1\u20135 stars)\"":["Formulaire d'enqu\u00eate : \"Dans quelle mesure \u00eates-vous satisfait de notre service ? (1\u20135 \u00e9toiles)\""],"Appointment booking form for \"Consultation Call\" with preferred time":["Formulaire de r\u00e9servation de rendez-vous pour \"Appel de consultation\" avec heure pr\u00e9f\u00e9r\u00e9e"],"Describe the form that you want":["D\u00e9crivez la forme que vous souhaitez"],"Generate":["G\u00e9n\u00e9rer"],"Create Unlimited Forms with AI":["Cr\u00e9ez des formulaires illimit\u00e9s avec l'IA"],"Add Advanced Field Types":["Ajouter des types de champs avanc\u00e9s"],"Create Calculators, Surveys, etc.":["Cr\u00e9ez des calculatrices, des sondages, etc."],"Form Generation Limit Reached":["Limite de g\u00e9n\u00e9ration de formulaire atteinte"],"You have reached the maximum number of form generations in your Free Plan. SureForms Premium allows:":["Vous avez atteint le nombre maximum de g\u00e9n\u00e9rations de formulaires dans votre plan gratuit. SureForms Premium permet :"],"%s AI Generations Left.":["Il reste %s g\u00e9n\u00e9rations d'IA."],"Unlock Unlimited Generations":["D\u00e9verrouillez des G\u00e9n\u00e9rations Illimit\u00e9es"],"Connect to SureForms AI":["Connectez-vous \u00e0 SureForms AI"],"You Have Hit Your Free Limit.":["Vous avez atteint votre limite gratuite."],"Connect to SureForms AI to Get 10 More.":["Connectez-vous \u00e0 SureForms AI pour obtenir 10 de plus."],"Or create it yourself":["Ou cr\u00e9ez-le vous-m\u00eame"],"Unable to create form":["Impossible de cr\u00e9er le formulaire"],"Something went wrong. Please try again.":["Un probl\u00e8me est survenu. Veuillez r\u00e9essayer."],"Describe what kind of form you want":["D\u00e9crivez le type de formulaire que vous souhaitez"],"Click to generate the form":["Cliquez pour g\u00e9n\u00e9rer le formulaire"],"Connecting to AI service":["Connexion au service d'IA"],"Generating fields":["G\u00e9n\u00e9ration des champs"],"Finalizing your form":["Finalisation de votre formulaire"],"Opening form editor":["Ouverture de l'\u00e9diteur de formulaire"],"Design Multistep Forms":["Concevoir des formulaires \u00e0 plusieurs \u00e9tapes"],"Send Form Entries to Your CRM or Any App":["Envoyez les entr\u00e9es de formulaire \u00e0 votre CRM ou \u00e0 n'importe quelle application"],"You've reached your daily generation limit.":["Vous avez atteint votre limite quotidienne de g\u00e9n\u00e9ration."],"You've reached your daily limit for AI form generations.":["Vous avez atteint votre limite quotidienne pour les g\u00e9n\u00e9rations de formulaires d'IA."],"Quiz":["Quiz"],"Unlock Quiz Forms":["D\u00e9verrouiller les formulaires de quiz"],"Create Engaging Quizzes That Score Automatically":["Cr\u00e9ez des quiz engageants qui se notent automatiquement"],"Build interactive quizzes with scored questions and graded results. Perfect for assessments, trivia, and educational content.":["Cr\u00e9ez des quiz interactifs avec des questions not\u00e9es et des r\u00e9sultats \u00e9valu\u00e9s. Parfait pour les \u00e9valuations, les jeux de culture g\u00e9n\u00e9rale et le contenu \u00e9ducatif."],"Auto-score responses instantly":["\u00c9valuer automatiquement les r\u00e9ponses instantan\u00e9ment"],"Display graded results to users":["Afficher les r\u00e9sultats not\u00e9s aux utilisateurs"],"Perfect for education, training, and fun trivia":["Parfait pour l'\u00e9ducation, la formation et les quiz amusants"],"Select this to create a quiz with scored questions and graded results.":["S\u00e9lectionnez ceci pour cr\u00e9er un quiz avec des questions not\u00e9es et des r\u00e9sultats \u00e9valu\u00e9s."],"Select this to create a survey to collect responses and opinions.":["S\u00e9lectionnez ceci pour cr\u00e9er un sondage afin de recueillir des r\u00e9ponses et des opinions."],"Survey":["Enqu\u00eate"],"Unlock Survey Forms":["D\u00e9verrouiller les formulaires d'enqu\u00eate"],"Collect Insights with Powerful Surveys":["Recueillez des informations avec des enqu\u00eates puissantes"],"Create surveys to collect responses and opinions. Visualize results with charts and share aggregated insights with your audience.":["Cr\u00e9ez des enqu\u00eates pour recueillir des r\u00e9ponses et des opinions. Visualisez les r\u00e9sultats avec des graphiques et partagez des insights agr\u00e9g\u00e9s avec votre audience."],"Aggregate and visualize responses":["Agr\u00e9ger et visualiser les r\u00e9ponses"],"Show live results to respondents":["Afficher les r\u00e9sultats en direct aux r\u00e9pondants"],"Perfect for feedback, polls, and research":["Parfait pour les retours, les sondages et la recherche"],"You do not have permission to create forms.":["Vous n'avez pas la permission de cr\u00e9er des formulaires."],"The form could not be saved. Please try again.":["Le formulaire n'a pas pu \u00eatre enregistr\u00e9. Veuillez r\u00e9essayer."],"Unable to reach the SureForms AI service. Please check your connection and try again.":["Impossible d'atteindre le service SureForms AI. Veuillez v\u00e9rifier votre connexion et r\u00e9essayer."],"The AI service did not return a response. Please try again.":["Le service d'IA n'a pas renvoy\u00e9 de r\u00e9ponse. Veuillez r\u00e9essayer."],"Form generation failed. Please try again.":["La g\u00e9n\u00e9ration du formulaire a \u00e9chou\u00e9. Veuillez r\u00e9essayer."],"The AI response was empty. Please refine your prompt and try again.":["La r\u00e9ponse de l'IA \u00e9tait vide. Veuillez affiner votre invite et r\u00e9essayer."],"Unable to build form fields from the AI response.":["Impossible de cr\u00e9er les champs de formulaire \u00e0 partir de la r\u00e9ponse de l'IA."]}}} \ No newline at end of file diff --git a/languages/sureforms-fr_FR-4b62e3f004dea2c587b5a3069263d994.json b/languages/sureforms-fr_FR-4b62e3f004dea2c587b5a3069263d994.json index 5d8afb8cf..5dbf86da8 100644 --- a/languages/sureforms-fr_FR-4b62e3f004dea2c587b5a3069263d994.json +++ b/languages/sureforms-fr_FR-4b62e3f004dea2c587b5a3069263d994.json @@ -1 +1 @@ -{"translation-revision-date":"2024-12-13T13:12:49+00:00","generator":"WP-CLI\/2.12.0","source":"assets\/build\/blocks.js","domain":"messages","locale_data":{"messages":{"":{"domain":"messages","lang":"en","plural-forms":"nplurals=2; plural=(n != 1);"},"Settings":["Param\u00e8tres"],"Search":["Recherche"],"Fields":["Champs"],"Image":["Image"],"Submit":["Soumettre"],"Required":["Requis"],"Form Title":["Titre du formulaire"],"Show":["Afficher"],"Hide":["Cacher"],"Edit Form":["Modifier le formulaire"],"Icon":["Ic\u00f4ne"],"Desktop":["Bureau"],"Medium":["Moyen"],"Mobile":["Mobile"],"Repeat":["R\u00e9p\u00e9ter"],"Scroll":["Faire d\u00e9filer"],"Tablet":["Tablette"],"Basic":["De base"],"(no title)":["(pas de titre)"],"Select a Form":["S\u00e9lectionnez un formulaire"],"No forms found\u2026":["Aucun formulaire trouv\u00e9\u2026"],"Choose":["Choisissez"],"Create New":["Cr\u00e9er Nouveau"],"Change Form":["Changer de formulaire"],"This form has been deleted or is unavailable.":["Ce formulaire a \u00e9t\u00e9 supprim\u00e9 ou est indisponible."],"Form Settings":["Param\u00e8tres du formulaire"],"Show Form Title on this Page":["Afficher le titre du formulaire sur cette page"],"Note: For editing SureForms, please refer to the SureForms Editor - ":["Remarque : Pour modifier les SureForms, veuillez vous r\u00e9f\u00e9rer \u00e0 l'\u00e9diteur SureForms -"],"Field preview":["Aper\u00e7u du champ"],"General":["G\u00e9n\u00e9ral"],"Style":["Style"],"Advanced":["Avanc\u00e9"],"No tags available":["Aucune \u00e9tiquette disponible"],"Device":["Appareil"],"Select Shortcodes":["S\u00e9lectionner les codes courts"],"Page Break Label":["\u00c9tiquette de saut de page"],"Next":["Suivant"],"Back":["Retour"],"Reset":["R\u00e9initialiser"],"Generic tags":["Balises g\u00e9n\u00e9riques"],"Pixel":["Pixel"],"Em":["Em"],"Select Units":["S\u00e9lectionner les unit\u00e9s"],"%s units":["%s unit\u00e9s"],"Margin":["Marge"],"Attributes":["Attributs"],"Input Pattern":["Mod\u00e8le d'entr\u00e9e"],"None":["Aucun"],"(###) ###-####":["(###) ###-####"],"(##) ####-####":["(##) ####-####"],"27\/08\/2024":["27\/08\/2024"],"23:59:59":["23:59:59"],"27\/08\/2024 23:59:59":["27\/08\/2024 23:59:59"],"Custom":["Personnalis\u00e9"],"Custom Mask":["Masque personnalis\u00e9"],"Please check the documentation to manage custom input pattern ":["Veuillez consulter la documentation pour g\u00e9rer le mod\u00e8le d'entr\u00e9e personnalis\u00e9"],"here":["ici"],"Default Value":["Valeur par d\u00e9faut"],"Error Message":["Message d'erreur"],"Help Text":["Texte d'aide"],"Number Format":["Format de nombre"],"US Style (Eg: 9,999.99)":["Style am\u00e9ricain (Ex : 9 999,99)"],"EU Style (Eg: 9.999,99)":["Style UE (Ex : 9.999,99)"],"Minimum Value":["Valeur minimale"],"Maximum Value":["Valeur maximale"],"Please check the Minimum and Maximum value":["Veuillez v\u00e9rifier la valeur minimale et maximale"],"Enable Email Confirmation":["Activer la confirmation par e-mail"],"Checked by Default":["Coch\u00e9 par d\u00e9faut"],"Error message":["Message d'erreur"],"Checked by default":["Coch\u00e9 par d\u00e9faut"],"Please add a option props to MultiButtonsControl":["Veuillez ajouter une option props \u00e0 MultiButtonsControl"],"Icon Library":["Biblioth\u00e8que d'ic\u00f4nes"],"Close":["Fermer"],"All Icons":["Toutes les ic\u00f4nes"],"Other":["Autre"],"No Icons Found":["Aucune ic\u00f4ne trouv\u00e9e"],"Insert Icon":["Ins\u00e9rer une ic\u00f4ne"],"Change Icon":["Changer l'ic\u00f4ne"],"Choose Icon":["Choisir une ic\u00f4ne"],"Confirm":["Confirmer"],"Cancel":["Annuler"],"Processing\u2026":["Traitement\u2026"],"Select Video":["S\u00e9lectionner la vid\u00e9o"],"Change Video":["Changer la vid\u00e9o"],"Select Lottie Animation":["S\u00e9lectionner l'animation Lottie"],"Change Lottie Animation":["Changer l'animation Lottie"],"Upload SVG":["T\u00e9l\u00e9charger SVG"],"Change SVG":["Modifier SVG"],"Select Image":["S\u00e9lectionner l'image"],"Change Image":["Changer l'image"],"Upload SVG?":["T\u00e9l\u00e9charger le SVG ?"],"Upload SVG can be potentially risky. Are you sure?":["T\u00e9l\u00e9charger un SVG peut \u00eatre potentiellement risqu\u00e9. \u00cates-vous s\u00fbr ?"],"Upload Anyway":["T\u00e9l\u00e9charger quand m\u00eame"],"Bulk Add":["Ajout en masse"],"Bulk Add Options":["Ajouter des options en masse"],"Enter each option on a new line.":["Entrez chaque option sur une nouvelle ligne."],"Insert Options":["Options d'insertion"],"Full Width":["Pleine largeur"],"Option Type":["Type d'option"],"Edit Options":["Modifier les options"],"Add New Option":["Ajouter une nouvelle option"],"ADD":["AJOUTER"],"Enable Auto Country Detection":["Activer la d\u00e9tection automatique du pays"],"%s Width":["Largeur %s"],"Upgrade":["Mise \u00e0 niveau"],"Clear":["Clair"],"Select Color":["S\u00e9lectionner la couleur"],"Primary Color":["Couleur primaire"],"Text Color":["Couleur du texte"],"Field Spacing":["Espacement des champs"],"Small":["Petit"],"Large":["Grand"],"Left":["Gauche"],"Center":["Centre"],"Right":["D'accord"],"Color":["Couleur"],"Background Color":["Couleur de fond"],"Auto":["Auto"],"Default":["Par d\u00e9faut"],"Normal":["Normal"],"%":["%"],"Top":["Haut"],"Bottom":["Bas"],"Width":["Largeur"],"Size":["Taille"],"EM":["EM"],"Padding":["Rembourrage"],"Color 1":["Couleur 1"],"Color 2":["Couleur 2"],"Type":["Type"],"Linear":["Lin\u00e9aire"],"Radial":["Radial"],"Location 1":["Emplacement 1"],"Location 2":["Emplacement 2"],"Angle":["Angle"],"Classic":["Classique"],"Gradient":["Gradient"],"Horizontal":["Horizontal"],"Vertical":["Vertical"],"Background":["Contexte"],"Cover":["Couvrir"],"Contain":["Contenir"],"Layout":["Mise en page"],"Overlay":["Superposition"],"No Repeat":["Pas de r\u00e9p\u00e9tition"],"Overlay Opacity":["Opacit\u00e9 de superposition"],"Conditional Logic":["Logique conditionnelle"],"Upgrade to the SureForms Starter Plan to create dynamic forms that adapt based on user input, offering a personalised and efficient form experience.":["Passez au plan de d\u00e9marrage SureForms pour cr\u00e9er des formulaires dynamiques qui s'adaptent en fonction des saisies de l'utilisateur, offrant une exp\u00e9rience de formulaire personnalis\u00e9e et efficace."],"Enable Conditional Logic":["Activer la logique conditionnelle"],"this field if":["ce champ si"],"Configure Conditions":["Configurer les conditions"],"Premium":["Premium"],"Overlay Type":["Type de superposition"],"Image Overlay Color":["Couleur de superposition d'image"],"Image Position":["Position de l'image"],"Attachment":["Pi\u00e8ce jointe"],"Fixed":["Fix\u00e9"],"Blend Mode":["Mode de fusion"],"Multiply":["Multiplier"],"Screen":["\u00c9cran"],"Darken":["Assombrir"],"Lighten":["All\u00e9ger"],"Color Dodge":["Superposition de couleurs"],"Saturation":["Saturation"],"Repeat-x":["R\u00e9p\u00e9ter-x"],"Repeat-y":["R\u00e9p\u00e8te-y"],"PX":["PX"],"Button":["Bouton"],"Prefix Label":["\u00c9tiquette de pr\u00e9fixe"],"Suffix Label":["\u00c9tiquette de suffixe"],"Border Radius":["Rayon de bordure"],"Form Theme":["Th\u00e8me du formulaire"],"Select Gradient":["S\u00e9lectionner le d\u00e9grad\u00e9"],"Unlock Conditional Logic Editor":["D\u00e9verrouiller l'\u00e9diteur de logique conditionnelle"],"Rich Text Editor":["\u00c9diteur de texte enrichi"],"Read Only":["Lecture seule"],"Select Country":["S\u00e9lectionner le pays"],"Default Country":["Pays par d\u00e9faut"],"Subscription":["Abonnement"],"One Time":["Une fois"],"Unique Entry":["Entr\u00e9e unique"],"Maximum Characters":["Caract\u00e8res maximum"],"Textarea Height":["Hauteur de la zone de texte"],"Minimum Selections":["S\u00e9lections minimales"],"Maximum Selections":["S\u00e9lections maximales"],"Add Numeric Values to Options":["Ajouter des valeurs num\u00e9riques aux options"],"Single Choice Only":["Choix unique seulement"],"Enable Dropdown Search":["Activer la recherche d\u00e9roulante"],"Allow Multiple":["Autoriser plusieurs"],"%1$s fields are required. Please configure these fields in the block settings.":["Les champs %1$s sont obligatoires. Veuillez configurer ces champs dans les param\u00e8tres du bloc."],"%1$s field is required. Please configure this field in the block settings.":["Le champ %1$s est requis. Veuillez configurer ce champ dans les param\u00e8tres du bloc."],"You need to configure a payment account to collect payments from this form. Please configure your payment provider to proceed.":["Vous devez configurer un compte de paiement pour collecter les paiements \u00e0 partir de ce formulaire. Veuillez configurer votre fournisseur de paiement pour continuer."],"Configure Payment Account":["Configurer le compte de paiement"],"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.":["Ceci est un espace r\u00e9serv\u00e9 pour le bloc de paiement. Les champs de paiement r\u00e9els pour votre ou vos fournisseurs de paiement configur\u00e9s n'appara\u00eetront que lorsque vous pr\u00e9visualiserez ou publierez le formulaire."],"2 Payments":["2 Paiements"],"3 Payments":["3 Paiements"],"4 Payments":["4 Paiements"],"5 Payments":["5 Paiements"],"Never":["Jamais"],"Stop Subscription After":["Arr\u00eater l'abonnement apr\u00e8s"],"Choose when to automatically stop the subscription":["Choisissez quand arr\u00eater automatiquement l'abonnement"],"Number of Payments":["Nombre de paiements"],"Enter a number between 1 to 100":["Entrez un nombre entre 1 et 100"],"Form Field":["Champ de formulaire"],"Payment Type":["Type de paiement"],"Subscription Plan Name":["Nom du plan d'abonnement"],"Billing Interval":["Intervalle de facturation"],"Daily":["Quotidien"],"Weekly":["Hebdomadaire"],"Monthly":["Mensuel"],"Quarterly":["Trimestriel"],"Yearly":["Annuel"],"Amount Type":["Type de montant"],"Fixed Amount":["Montant fixe"],"Dynamic Amount":["Montant Dynamique"],"Choose whether to charge a fixed amount or charge the amount based on user input in other form fields.":["Choisissez de facturer un montant fixe ou de facturer le montant en fonction des saisies de l'utilisateur dans d'autres champs de formulaire."],"Set the exact amount you want to charge. Users won\u2019t be able to change it":["D\u00e9finissez le montant exact que vous souhaitez facturer. Les utilisateurs ne pourront pas le modifier"],"Choose Amount Field":["Choisissez le champ Montant"],"Select a field\u2026":["S\u00e9lectionnez un champ\u2026"],"Pick a field from your form like a number, dropdown, or multichoice whose value should decide the payment amount.":["Choisissez un champ de votre formulaire, tel qu'un nombre, une liste d\u00e9roulante ou un choix multiple, dont la valeur doit d\u00e9terminer le montant du paiement."],"Minimum Amount":["Montant minimum"],"Set the minimum amount users can enter (0 for no minimum)":["D\u00e9finissez le montant minimum que les utilisateurs peuvent entrer (0 pour aucun minimum)"],"Customer Name Field (Required)":["Champ Nom du client (Obligatoire)"],"Customer Name Field (Optional)":["Champ Nom du Client (Facultatif)"],"Select the input field that contains the customer name (Required for subscriptions)":["S\u00e9lectionnez le champ de saisie qui contient le nom du client (Requis pour les abonnements)"],"Select the input field that contains the customer name":["S\u00e9lectionnez le champ de saisie qui contient le nom du client"],"Customer Email Field (Required)":["Champ d'email du client (Obligatoire)"],"Select the email field that contains the customer email":["S\u00e9lectionnez le champ de courriel qui contient l'email du client"],"Payment":["Paiement"],"%s - Order ID":["%s - ID de commande"],"%s - Amount":["%s - Montant"],"%s - Customer Email":["%s - Email du client"],"%s - Customer Name":["%s - Nom du client"],"%s - Status":["%s - Statut"],"Button Alignment":["Alignement du bouton"],"Placeholder":["Espace r\u00e9serv\u00e9"],"Preselect this option":["Pr\u00e9s\u00e9lectionnez cette option"],"Restrict Country Codes":["Restreindre les codes pays"],"Restriction Type":["Type de restriction"],"Allow":["Autoriser"],"Block":["Bloquer"],"Select Allowed Countries":["S\u00e9lectionner les pays autoris\u00e9s"],"Choose countries\u2026":["Choisissez des pays\u2026"],"Choose which country codes users can select in the phone number field. Leave empty to allow all country codes.":["Choisissez les indicatifs de pays que les utilisateurs peuvent s\u00e9lectionner dans le champ du num\u00e9ro de t\u00e9l\u00e9phone. Laissez vide pour autoriser tous les indicatifs de pays."],"Select Blocked Countries":["S\u00e9lectionner les pays bloqu\u00e9s"],"These countries will be hidden from the dropdown.":["Ces pays seront masqu\u00e9s dans le menu d\u00e9roulant."],"Bulk Edit":["Modification en masse"],"Select Layout":["S\u00e9lectionner la disposition"],"Number of Columns":["Nombre de colonnes"],"Validation Message for Duplicate":["Message de validation pour doublon"],"Click here to insert a form":["Cliquez ici pour ins\u00e9rer un formulaire"],"Inherit Form's Original Style":["H\u00e9riter du style original du formulaire"],"Text on Primary":["Texte sur Principal"],"%s - Description":["%s - Description"],"Upgrade to Unlock":["Mettez \u00e0 niveau pour d\u00e9bloquer"],"Custom (Premium)":["Personnalis\u00e9 (Premium)"],"Select a theme style for this form embed.":["S\u00e9lectionnez un style de th\u00e8me pour cette int\u00e9gration de formulaire."],"Colors":["Couleurs"],"Advanced Styling":["Style avanc\u00e9"],"Unlock Custom Styling":["D\u00e9verrouiller le style personnalis\u00e9"],"Switch to Custom Mode to take full control of your form's design and spacing.":["Passez en mode personnalis\u00e9 pour prendre le contr\u00f4le total de la conception et de l'espacement de votre formulaire."],"Full color control (buttons, fields, text)":["Contr\u00f4le complet des couleurs (boutons, champs, texte)"],"Row and column gap control":["Contr\u00f4le de l'espacement des lignes et des colonnes"],"Field spacing and layout precision":["Pr\u00e9cision de l'espacement et de la disposition des champs"],"Complete button styling":["Style complet du bouton"],"Payment Description":["Description du paiement"],"Shown on payment receipts and in your payment dashboard (Stripe and PayPal). Leave blank to use the default.":["Affich\u00e9 sur les re\u00e7us de paiement et dans votre tableau de bord de paiement (Stripe et PayPal). Laissez vide pour utiliser la valeur par d\u00e9faut."],"Slug":["Limace"],"Auto-generated on save":["G\u00e9n\u00e9r\u00e9 automatiquement lors de l'enregistrement"],"This slug is already used by another field. It will revert to the previous value.":["Ce slug est d\u00e9j\u00e0 utilis\u00e9 par un autre champ. Il reviendra \u00e0 la valeur pr\u00e9c\u00e9dente."],"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.":["Changer le slug peut perturber les soumissions de formulaires, la logique conditionnelle, les int\u00e9grations ou toute autre fonctionnalit\u00e9 se r\u00e9f\u00e9rant actuellement \u00e0 ce slug. Vous devrez mettre \u00e0 jour manuellement toutes ces r\u00e9f\u00e9rences."],"Field Slug":["Slug de champ"],"Location Services":["Services de localisation"],"Unlock Address Autocomplete":["D\u00e9verrouiller la saisie semi-automatique de l'adresse"],"Upgrade to enable Google Address Autocomplete with interactive map preview, making address entry faster and more accurate for your users.":["Mettez \u00e0 niveau pour activer la saisie semi-automatique des adresses Google avec aper\u00e7u interactif de la carte, rendant la saisie des adresses plus rapide et plus pr\u00e9cise pour vos utilisateurs."],"Enable Google Autocomplete":["Activer la saisie semi-automatique de Google"],"Show Interactive Map":["Afficher la carte interactive"],"Payments Per Page":["Paiements par page"],"Show Subscriptions Section":["Afficher la section des abonnements"],"Show a dedicated subscriptions section above payment history.":["Afficher une section d\u00e9di\u00e9e aux abonnements au-dessus de l'historique des paiements."],"Payment Dashboard":["Tableau de bord des paiements"],"View your payments and manage subscriptions in a single dashboard.":["Consultez vos paiements et g\u00e9rez vos abonnements dans un tableau de bord unique."],"Dynamic Default Value":["Valeur par d\u00e9faut dynamique"]}}} \ No newline at end of file +{"translation-revision-date":"2024-12-13T13:12:49+00:00","generator":"WP-CLI\/2.12.0","source":"assets\/build\/blocks.js","domain":"messages","locale_data":{"messages":{"":{"domain":"messages","lang":"en","plural-forms":"nplurals=2; plural=(n != 1);"},"Settings":["Param\u00e8tres"],"Search":["Recherche"],"Fields":["Champs"],"Image":["Image"],"Submit":["Soumettre"],"Required":["Requis"],"Form Title":["Titre du formulaire"],"Show":["Afficher"],"Hide":["Cacher"],"Edit Form":["Modifier le formulaire"],"Icon":["Ic\u00f4ne"],"Desktop":["Bureau"],"Medium":["Moyen"],"Mobile":["Mobile"],"Repeat":["R\u00e9p\u00e9ter"],"Scroll":["Faire d\u00e9filer"],"Tablet":["Tablette"],"Basic":["De base"],"(no title)":["(pas de titre)"],"Select a Form":["S\u00e9lectionnez un formulaire"],"No forms found\u2026":["Aucun formulaire trouv\u00e9\u2026"],"Choose":["Choisissez"],"Create New":["Cr\u00e9er Nouveau"],"Change Form":["Changer de formulaire"],"This form has been deleted or is unavailable.":["Ce formulaire a \u00e9t\u00e9 supprim\u00e9 ou est indisponible."],"Form Settings":["Param\u00e8tres du formulaire"],"Show Form Title on this Page":["Afficher le titre du formulaire sur cette page"],"Note: For editing SureForms, please refer to the SureForms Editor - ":["Remarque : Pour modifier les SureForms, veuillez vous r\u00e9f\u00e9rer \u00e0 l'\u00e9diteur SureForms -"],"Field preview":["Aper\u00e7u du champ"],"General":["G\u00e9n\u00e9ral"],"Style":["Style"],"Advanced":["Avanc\u00e9"],"No tags available":["Aucune \u00e9tiquette disponible"],"Device":["Appareil"],"Select Shortcodes":["S\u00e9lectionner les codes courts"],"Page Break Label":["\u00c9tiquette de saut de page"],"Next":["Suivant"],"Back":["Retour"],"Reset":["R\u00e9initialiser"],"Generic tags":["Balises g\u00e9n\u00e9riques"],"Pixel":["Pixel"],"Em":["Em"],"Select Units":["S\u00e9lectionner les unit\u00e9s"],"%s units":["%s unit\u00e9s"],"Margin":["Marge"],"Attributes":["Attributs"],"Input Pattern":["Mod\u00e8le d'entr\u00e9e"],"None":["Aucun"],"(###) ###-####":["(###) ###-####"],"(##) ####-####":["(##) ####-####"],"27\/08\/2024":["27\/08\/2024"],"23:59:59":["23:59:59"],"27\/08\/2024 23:59:59":["27\/08\/2024 23:59:59"],"Custom":["Personnalis\u00e9"],"Custom Mask":["Masque personnalis\u00e9"],"Please check the documentation to manage custom input pattern ":["Veuillez consulter la documentation pour g\u00e9rer le mod\u00e8le d'entr\u00e9e personnalis\u00e9"],"here":["ici"],"Default Value":["Valeur par d\u00e9faut"],"Error Message":["Message d'erreur"],"Help Text":["Texte d'aide"],"Number Format":["Format de nombre"],"US Style (Eg: 9,999.99)":["Style am\u00e9ricain (Ex : 9 999,99)"],"EU Style (Eg: 9.999,99)":["Style UE (Ex : 9.999,99)"],"Minimum Value":["Valeur minimale"],"Maximum Value":["Valeur maximale"],"Please check the Minimum and Maximum value":["Veuillez v\u00e9rifier la valeur minimale et maximale"],"Enable Email Confirmation":["Activer la confirmation par e-mail"],"Checked by Default":["Coch\u00e9 par d\u00e9faut"],"Error message":["Message d'erreur"],"Checked by default":["Coch\u00e9 par d\u00e9faut"],"Please add a option props to MultiButtonsControl":["Veuillez ajouter une option props \u00e0 MultiButtonsControl"],"Icon Library":["Biblioth\u00e8que d'ic\u00f4nes"],"Close":["Fermer"],"All Icons":["Toutes les ic\u00f4nes"],"Other":["Autre"],"No Icons Found":["Aucune ic\u00f4ne trouv\u00e9e"],"Insert Icon":["Ins\u00e9rer une ic\u00f4ne"],"Change Icon":["Changer l'ic\u00f4ne"],"Choose Icon":["Choisir une ic\u00f4ne"],"Confirm":["Confirmer"],"Cancel":["Annuler"],"Processing\u2026":["Traitement\u2026"],"Select Video":["S\u00e9lectionner la vid\u00e9o"],"Change Video":["Changer la vid\u00e9o"],"Select Lottie Animation":["S\u00e9lectionner l'animation Lottie"],"Change Lottie Animation":["Changer l'animation Lottie"],"Upload SVG":["T\u00e9l\u00e9charger SVG"],"Change SVG":["Modifier SVG"],"Select Image":["S\u00e9lectionner l'image"],"Change Image":["Changer l'image"],"Upload SVG?":["T\u00e9l\u00e9charger le SVG ?"],"Upload SVG can be potentially risky. Are you sure?":["T\u00e9l\u00e9charger un SVG peut \u00eatre potentiellement risqu\u00e9. \u00cates-vous s\u00fbr ?"],"Upload Anyway":["T\u00e9l\u00e9charger quand m\u00eame"],"Bulk Add":["Ajout en masse"],"Bulk Add Options":["Ajouter des options en masse"],"Enter each option on a new line.":["Entrez chaque option sur une nouvelle ligne."],"Insert Options":["Options d'insertion"],"Full Width":["Pleine largeur"],"Option Type":["Type d'option"],"Edit Options":["Modifier les options"],"Add New Option":["Ajouter une nouvelle option"],"ADD":["AJOUTER"],"Enable Auto Country Detection":["Activer la d\u00e9tection automatique du pays"],"%s Width":["Largeur %s"],"Upgrade":["Mise \u00e0 niveau"],"Clear":["Clair"],"Select Color":["S\u00e9lectionner la couleur"],"Primary Color":["Couleur primaire"],"Text Color":["Couleur du texte"],"Field Spacing":["Espacement des champs"],"Small":["Petit"],"Large":["Grand"],"Left":["Gauche"],"Center":["Centre"],"Right":["D'accord"],"Color":["Couleur"],"Background Color":["Couleur de fond"],"Auto":["Auto"],"Default":["Par d\u00e9faut"],"Normal":["Normal"],"%":["%"],"Top":["Haut"],"Bottom":["Bas"],"Width":["Largeur"],"Size":["Taille"],"EM":["EM"],"Padding":["Rembourrage"],"Color 1":["Couleur 1"],"Color 2":["Couleur 2"],"Type":["Type"],"Linear":["Lin\u00e9aire"],"Radial":["Radial"],"Location 1":["Emplacement 1"],"Location 2":["Emplacement 2"],"Angle":["Angle"],"Classic":["Classique"],"Gradient":["Gradient"],"Horizontal":["Horizontal"],"Vertical":["Vertical"],"Background":["Contexte"],"Cover":["Couvrir"],"Contain":["Contenir"],"Layout":["Mise en page"],"Overlay":["Superposition"],"No Repeat":["Pas de r\u00e9p\u00e9tition"],"Overlay Opacity":["Opacit\u00e9 de superposition"],"Conditional Logic":["Logique conditionnelle"],"Upgrade to the SureForms Starter Plan to create dynamic forms that adapt based on user input, offering a personalised and efficient form experience.":["Passez au plan de d\u00e9marrage SureForms pour cr\u00e9er des formulaires dynamiques qui s'adaptent en fonction des saisies de l'utilisateur, offrant une exp\u00e9rience de formulaire personnalis\u00e9e et efficace."],"Enable Conditional Logic":["Activer la logique conditionnelle"],"this field if":["ce champ si"],"Configure Conditions":["Configurer les conditions"],"Premium":["Premium"],"Overlay Type":["Type de superposition"],"Image Overlay Color":["Couleur de superposition d'image"],"Image Position":["Position de l'image"],"Attachment":["Pi\u00e8ce jointe"],"Fixed":["Fix\u00e9"],"Blend Mode":["Mode de fusion"],"Multiply":["Multiplier"],"Screen":["\u00c9cran"],"Darken":["Assombrir"],"Lighten":["All\u00e9ger"],"Color Dodge":["Superposition de couleurs"],"Saturation":["Saturation"],"Repeat-x":["R\u00e9p\u00e9ter-x"],"Repeat-y":["R\u00e9p\u00e8te-y"],"PX":["PX"],"Button":["Bouton"],"Prefix Label":["\u00c9tiquette de pr\u00e9fixe"],"Suffix Label":["\u00c9tiquette de suffixe"],"Border Radius":["Rayon de bordure"],"Form Theme":["Th\u00e8me du formulaire"],"Select Gradient":["S\u00e9lectionner le d\u00e9grad\u00e9"],"Unlock Conditional Logic Editor":["D\u00e9verrouiller l'\u00e9diteur de logique conditionnelle"],"Rich Text Editor":["\u00c9diteur de texte enrichi"],"Read Only":["Lecture seule"],"Select Country":["S\u00e9lectionner le pays"],"Default Country":["Pays par d\u00e9faut"],"Subscription":["Abonnement"],"One Time":["Une fois"],"Unique Entry":["Entr\u00e9e unique"],"Maximum Characters":["Caract\u00e8res maximum"],"Textarea Height":["Hauteur de la zone de texte"],"Minimum Selections":["S\u00e9lections minimales"],"Maximum Selections":["S\u00e9lections maximales"],"Add Numeric Values to Options":["Ajouter des valeurs num\u00e9riques aux options"],"Single Choice Only":["Choix unique seulement"],"Enable Dropdown Search":["Activer la recherche d\u00e9roulante"],"Allow Multiple":["Autoriser plusieurs"],"%1$s fields are required. Please configure these fields in the block settings.":["Les champs %1$s sont obligatoires. Veuillez configurer ces champs dans les param\u00e8tres du bloc."],"%1$s field is required. Please configure this field in the block settings.":["Le champ %1$s est requis. Veuillez configurer ce champ dans les param\u00e8tres du bloc."],"You need to configure a payment account to collect payments from this form. Please configure your payment provider to proceed.":["Vous devez configurer un compte de paiement pour collecter les paiements \u00e0 partir de ce formulaire. Veuillez configurer votre fournisseur de paiement pour continuer."],"Configure Payment Account":["Configurer le compte de paiement"],"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.":["Ceci est un espace r\u00e9serv\u00e9 pour le bloc de paiement. Les champs de paiement r\u00e9els pour votre ou vos fournisseurs de paiement configur\u00e9s n'appara\u00eetront que lorsque vous pr\u00e9visualiserez ou publierez le formulaire."],"2 Payments":["2 Paiements"],"3 Payments":["3 Paiements"],"4 Payments":["4 Paiements"],"5 Payments":["5 Paiements"],"Never":["Jamais"],"Stop Subscription After":["Arr\u00eater l'abonnement apr\u00e8s"],"Choose when to automatically stop the subscription":["Choisissez quand arr\u00eater automatiquement l'abonnement"],"Number of Payments":["Nombre de paiements"],"Enter a number between 1 to 100":["Entrez un nombre entre 1 et 100"],"Form Field":["Champ de formulaire"],"Payment Type":["Type de paiement"],"Subscription Plan Name":["Nom du plan d'abonnement"],"Billing Interval":["Intervalle de facturation"],"Daily":["Quotidien"],"Weekly":["Hebdomadaire"],"Monthly":["Mensuel"],"Quarterly":["Trimestriel"],"Yearly":["Annuel"],"Amount Type":["Type de montant"],"Fixed Amount":["Montant fixe"],"Dynamic Amount":["Montant Dynamique"],"Choose whether to charge a fixed amount or charge the amount based on user input in other form fields.":["Choisissez de facturer un montant fixe ou de facturer le montant en fonction des saisies de l'utilisateur dans d'autres champs de formulaire."],"Set the exact amount you want to charge. Users won\u2019t be able to change it":["D\u00e9finissez le montant exact que vous souhaitez facturer. Les utilisateurs ne pourront pas le modifier"],"Choose Amount Field":["Choisissez le champ Montant"],"Select a field\u2026":["S\u00e9lectionnez un champ\u2026"],"Minimum Amount":["Montant minimum"],"Set the minimum amount users can enter (0 for no minimum)":["D\u00e9finissez le montant minimum que les utilisateurs peuvent entrer (0 pour aucun minimum)"],"Customer Name Field (Required)":["Champ Nom du client (Obligatoire)"],"Customer Name Field (Optional)":["Champ Nom du Client (Facultatif)"],"Select the input field that contains the customer name (Required for subscriptions)":["S\u00e9lectionnez le champ de saisie qui contient le nom du client (Requis pour les abonnements)"],"Select the input field that contains the customer name":["S\u00e9lectionnez le champ de saisie qui contient le nom du client"],"Customer Email Field (Required)":["Champ d'email du client (Obligatoire)"],"Select the email field that contains the customer email":["S\u00e9lectionnez le champ de courriel qui contient l'email du client"],"Payment":["Paiement"],"%s - Order ID":["%s - ID de commande"],"%s - Amount":["%s - Montant"],"%s - Customer Email":["%s - Email du client"],"%s - Customer Name":["%s - Nom du client"],"%s - Status":["%s - Statut"],"Button Alignment":["Alignement du bouton"],"Placeholder":["Espace r\u00e9serv\u00e9"],"Preselect this option":["Pr\u00e9s\u00e9lectionnez cette option"],"Restrict Country Codes":["Restreindre les codes pays"],"Restriction Type":["Type de restriction"],"Allow":["Autoriser"],"Block":["Bloquer"],"Select Allowed Countries":["S\u00e9lectionner les pays autoris\u00e9s"],"Choose countries\u2026":["Choisissez des pays\u2026"],"Choose which country codes users can select in the phone number field. Leave empty to allow all country codes.":["Choisissez les indicatifs de pays que les utilisateurs peuvent s\u00e9lectionner dans le champ du num\u00e9ro de t\u00e9l\u00e9phone. Laissez vide pour autoriser tous les indicatifs de pays."],"Select Blocked Countries":["S\u00e9lectionner les pays bloqu\u00e9s"],"These countries will be hidden from the dropdown.":["Ces pays seront masqu\u00e9s dans le menu d\u00e9roulant."],"Bulk Edit":["Modification en masse"],"Select Layout":["S\u00e9lectionner la disposition"],"Number of Columns":["Nombre de colonnes"],"Validation Message for Duplicate":["Message de validation pour doublon"],"Click here to insert a form":["Cliquez ici pour ins\u00e9rer un formulaire"],"Inherit Form's Original Style":["H\u00e9riter du style original du formulaire"],"Text on Primary":["Texte sur Principal"],"%s - Description":["%s - Description"],"Upgrade to Unlock":["Mettez \u00e0 niveau pour d\u00e9bloquer"],"Custom (Premium)":["Personnalis\u00e9 (Premium)"],"Select a theme style for this form embed.":["S\u00e9lectionnez un style de th\u00e8me pour cette int\u00e9gration de formulaire."],"Colors":["Couleurs"],"Advanced Styling":["Style avanc\u00e9"],"Unlock Custom Styling":["D\u00e9verrouiller le style personnalis\u00e9"],"Switch to Custom Mode to take full control of your form's design and spacing.":["Passez en mode personnalis\u00e9 pour prendre le contr\u00f4le total de la conception et de l'espacement de votre formulaire."],"Full color control (buttons, fields, text)":["Contr\u00f4le complet des couleurs (boutons, champs, texte)"],"Row and column gap control":["Contr\u00f4le de l'espacement des lignes et des colonnes"],"Field spacing and layout precision":["Pr\u00e9cision de l'espacement et de la disposition des champs"],"Complete button styling":["Style complet du bouton"],"Payment Description":["Description du paiement"],"Shown on payment receipts and in your payment dashboard (Stripe and PayPal). Leave blank to use the default.":["Affich\u00e9 sur les re\u00e7us de paiement et dans votre tableau de bord de paiement (Stripe et PayPal). Laissez vide pour utiliser la valeur par d\u00e9faut."],"Slug":["Limace"],"Auto-generated on save":["G\u00e9n\u00e9r\u00e9 automatiquement lors de l'enregistrement"],"This slug is already used by another field. It will revert to the previous value.":["Ce slug est d\u00e9j\u00e0 utilis\u00e9 par un autre champ. Il reviendra \u00e0 la valeur pr\u00e9c\u00e9dente."],"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.":["Changer le slug peut perturber les soumissions de formulaires, la logique conditionnelle, les int\u00e9grations ou toute autre fonctionnalit\u00e9 se r\u00e9f\u00e9rant actuellement \u00e0 ce slug. Vous devrez mettre \u00e0 jour manuellement toutes ces r\u00e9f\u00e9rences."],"Field Slug":["Slug de champ"],"Location Services":["Services de localisation"],"Unlock Address Autocomplete":["D\u00e9verrouiller la saisie semi-automatique de l'adresse"],"Upgrade to enable Google Address Autocomplete with interactive map preview, making address entry faster and more accurate for your users.":["Mettez \u00e0 niveau pour activer la saisie semi-automatique des adresses Google avec aper\u00e7u interactif de la carte, rendant la saisie des adresses plus rapide et plus pr\u00e9cise pour vos utilisateurs."],"Enable Google Autocomplete":["Activer la saisie semi-automatique de Google"],"Show Interactive Map":["Afficher la carte interactive"],"Payments Per Page":["Paiements par page"],"Show Subscriptions Section":["Afficher la section des abonnements"],"Show a dedicated subscriptions section above payment history.":["Afficher une section d\u00e9di\u00e9e aux abonnements au-dessus de l'historique des paiements."],"Payment Dashboard":["Tableau de bord des paiements"],"View your payments and manage subscriptions in a single dashboard.":["Consultez vos paiements et g\u00e9rez vos abonnements dans un tableau de bord unique."],"Dynamic Default Value":["Valeur par d\u00e9faut dynamique"],"Minimum Characters":["Caract\u00e8res minimum"],"Minimum characters cannot exceed Maximum characters.":["Les caract\u00e8res minimum ne peuvent pas d\u00e9passer les caract\u00e8res maximum."],"Both":["Les deux"],"One-Time Label":["\u00c9tiquette unique"],"Label shown to users for the one-time payment option.":["Libell\u00e9 affich\u00e9 aux utilisateurs pour l'option de paiement unique."],"Subscription Label":["Libell\u00e9 d'abonnement"],"Label shown to users for the subscription option.":["Libell\u00e9 affich\u00e9 aux utilisateurs pour l'option d'abonnement."],"Default Selection":["S\u00e9lection par d\u00e9faut"],"Which option is pre-selected when the form loads.":["Quelle option est pr\u00e9s\u00e9lectionn\u00e9e lorsque le formulaire se charge."],"One-Time Amount Type":["Type de montant unique"],"Set how the one-time payment amount is determined.":["D\u00e9finissez comment le montant du paiement unique est d\u00e9termin\u00e9."],"One-Time Fixed Amount":["Montant fixe unique"],"Amount charged for a one-time payment.":["Montant factur\u00e9 pour un paiement unique."],"One-Time Amount Field":["Champ de montant unique"],"Pick a form field whose value determines the one-time payment amount.":["S\u00e9lectionnez un champ de formulaire dont la valeur d\u00e9termine le montant du paiement unique."],"One-Time Minimum Amount":["Montant minimum unique"],"Minimum amount users can enter for one-time payment (0 for no minimum).":["Montant minimum que les utilisateurs peuvent entrer pour un paiement unique (0 pour aucun minimum)."],"Subscription Amount Type":["Type de montant d'abonnement"],"Set how the subscription amount is determined.":["D\u00e9finissez comment le montant de l'abonnement est d\u00e9termin\u00e9."],"Subscription Fixed Amount":["Montant fixe de l'abonnement"],"Recurring amount charged per billing interval.":["Montant r\u00e9current factur\u00e9 par intervalle de facturation."],"Subscription Amount Field":["Champ Montant de l'abonnement"],"Pick a form field whose value determines the subscription amount.":["Choisissez un champ de formulaire dont la valeur d\u00e9termine le montant de l'abonnement."],"Subscription Minimum Amount":["Montant minimum de l'abonnement"],"Minimum amount users can enter for subscription (0 for no minimum).":["Montant minimum que les utilisateurs peuvent entrer pour l'abonnement (0 pour aucun minimum)."],"Pick a field from your form like a number, dropdown, multichoice, or hidden whose value should decide the payment amount.":["Choisissez un champ de votre formulaire comme un nombre, une liste d\u00e9roulante, un choix multiple ou un champ cach\u00e9 dont la valeur doit d\u00e9terminer le montant du paiement."]}}} \ No newline at end of file diff --git a/languages/sureforms-fr_FR.mo b/languages/sureforms-fr_FR.mo index 881a47700..b575a65ca 100644 Binary files a/languages/sureforms-fr_FR.mo and b/languages/sureforms-fr_FR.mo differ diff --git a/languages/sureforms-fr_FR.po b/languages/sureforms-fr_FR.po index 5c00795a5..c66754b88 100644 --- a/languages/sureforms-fr_FR.po +++ b/languages/sureforms-fr_FR.po @@ -106,13 +106,13 @@ msgstr "Modifier %1$s" #: inc/ai-form-builder/ai-auth.php:93 #: inc/ai-form-builder/ai-auth.php:167 #: inc/background-process.php:112 -#: inc/create-new-form.php:101 +#: inc/create-new-form.php:102 #: inc/duplicate-form.php:176 #: inc/export.php:118 #: inc/export.php:176 #: inc/forms-data.php:88 #: inc/global-settings/global-settings.php:86 -#: inc/global-settings/global-settings.php:403 +#: inc/global-settings/global-settings.php:404 #: inc/rest-api.php:177 msgid "Nonce verification failed." msgstr "La vérification du nonce a échoué." @@ -377,7 +377,7 @@ msgid "Selected radio option" msgstr "Option radio sélectionnée" #: inc/admin-ajax.php:341 -#: inc/create-new-form.php:63 +#: inc/create-new-form.php:64 #: assets/build/blocks.js:172 #: assets/build/formEditor.js:172 msgid "Submit" @@ -416,53 +416,53 @@ msgid "The message array was not supplied" msgstr "Le tableau de messages n'a pas été fourni" #: inc/ai-form-builder/ai-form-builder.php:68 -#: inc/ai-form-builder/ai-form-builder.php:78 -#: inc/ai-form-builder/ai-helper.php:73 +#: inc/ai-form-builder/ai-form-builder.php:87 +#: inc/ai-form-builder/ai-helper.php:294 msgid "The SureForms AI Middleware encountered an error." msgstr "Le middleware SureForms AI a rencontré une erreur." -#: inc/ai-form-builder/ai-helper.php:95 +#: inc/ai-form-builder/ai-helper.php:91 msgid "Unable to get usage response." msgstr "Impossible d'obtenir la réponse d'utilisation." -#: inc/ai-form-builder/ai-helper.php:148 +#: inc/ai-form-builder/ai-helper.php:145 msgid "The SureForms API server encountered an error." msgstr "Le serveur API de SureForms a rencontré une erreur." -#: inc/ai-form-builder/ai-helper.php:174 -#: inc/ai-form-builder/ai-helper.php:206 +#: inc/ai-form-builder/ai-helper.php:167 +#: inc/ai-form-builder/ai-helper.php:199 msgid "An unknown error occurred." msgstr "Une erreur inconnue s'est produite." -#: inc/ai-form-builder/ai-helper.php:181 +#: inc/ai-form-builder/ai-helper.php:174 msgid "HTTP Request Failed" msgstr "Échec de la requête HTTP" -#: inc/ai-form-builder/ai-helper.php:185 +#: inc/ai-form-builder/ai-helper.php:178 msgid "License Verification Failed" msgstr "Échec de la vérification de la licence" -#: inc/ai-form-builder/ai-helper.php:189 +#: inc/ai-form-builder/ai-helper.php:182 msgid "User Verification Failed" msgstr "Échec de la vérification de l'utilisateur" -#: inc/ai-form-builder/ai-helper.php:193 +#: inc/ai-form-builder/ai-helper.php:186 msgid "Referer Mismatch" msgstr "Incohérence du référent" -#: inc/ai-form-builder/ai-helper.php:197 +#: inc/ai-form-builder/ai-helper.php:190 msgid "Invalid Website URL" msgstr "URL de site Web invalide" -#: inc/ai-form-builder/ai-helper.php:198 +#: inc/ai-form-builder/ai-helper.php:191 msgid "AI Form Builder does not work on localhost. Please try on a live website." msgstr "Le générateur de formulaires AI ne fonctionne pas sur localhost. Veuillez essayer sur un site web en ligne." -#: inc/ai-form-builder/ai-helper.php:201 +#: inc/ai-form-builder/ai-helper.php:194 msgid "Domain Verification Failed" msgstr "Échec de la vérification du domaine" -#: inc/ai-form-builder/ai-helper.php:205 +#: inc/ai-form-builder/ai-helper.php:198 msgid "Unknown Error" msgstr "Erreur inconnue" @@ -470,22 +470,18 @@ msgstr "Erreur inconnue" msgid "Submission id missing." msgstr "ID de soumission manquant." -#: inc/create-new-form.php:113 +#: inc/create-new-form.php:114 msgid "Invalid JSON format." msgstr "Format JSON invalide." -#: inc/create-new-form.php:125 +#: inc/create-new-form.php:126 msgid "Missing required properties in form info." msgstr "Propriétés requises manquantes dans les informations du formulaire." -#: inc/create-new-form.php:161 +#: inc/create-new-form.php:187 msgid "SureForms Form created successfully." msgstr "Formulaire SureForms créé avec succès." -#: inc/create-new-form.php:168 -msgid "Error creating SureForms Form, " -msgstr "Erreur lors de la création du formulaire SureForms," - #: inc/email/email-template.php:46 msgid "New form submission" msgstr "Nouvelle soumission de formulaire" @@ -547,7 +543,7 @@ msgstr "Nombre" msgid "Phone" msgstr "Téléphone" -#: inc/fields/textarea-markup.php:95 +#: inc/fields/textarea-markup.php:111 msgid "Textarea" msgstr "Zone de texte" @@ -590,8 +586,8 @@ msgstr "Aucun formulaire trouvé." #: inc/abilities/settings/get-global-settings.php:192 #: inc/global-settings/email-summary.php:571 -#: inc/global-settings/global-settings.php:250 -#: inc/global-settings/global-settings.php:456 +#: inc/global-settings/global-settings.php:251 +#: inc/global-settings/global-settings.php:457 #: assets/build/settings.js:172 msgid "Monday" msgstr "Lundi" @@ -6994,7 +6990,7 @@ msgstr "Vue de la rue" msgid "Strikethrough" msgstr "Barré" -#: inc/fields/payment-markup.php:412 +#: inc/fields/payment-markup.php:513 #: modules/gutenberg/icons/icons-v6-3.php:1812 #: assets/build/payments.js:172 msgid "Stripe" @@ -11593,6 +11589,7 @@ msgstr "Créez votre premier formulaire" msgid "Invalid nonce action or name." msgstr "Action ou nom de nonce invalide." +#: inc/admin/editor-nudge.php:216 #: inc/helper.php:2029 #: inc/helper.php:2037 msgid "Invalid security token." @@ -11776,7 +11773,7 @@ msgstr "Explorez SureDash" msgid "Something went wrong. We have logged the error for further investigation" msgstr "Un problème est survenu. Nous avons enregistré l'erreur pour une enquête plus approfondie." -#: inc/field-validation.php:273 +#: inc/field-validation.php:276 msgid "Field is not valid." msgstr "Le champ n'est pas valide." @@ -11934,82 +11931,82 @@ msgstr "Aucune donnée de formulaire fournie pour l'importation." msgid "Invalid form data structure provided." msgstr "Structure de données de formulaire invalide fournie." -#: inc/fields/payment-markup.php:249 +#: inc/fields/payment-markup.php:346 #: inc/payments/payment-helper.php:543 msgid "Subscription Plan" msgstr "Plan d'abonnement" #. translators: 1: Amount with currency, 2: Interval (day/week/month/quarter/year) -#: inc/fields/payment-markup.php:288 +#: inc/fields/payment-markup.php:672 #, php-format msgid "%1$s per %2$s (until cancelled)" msgstr "%1$s par %2$s (jusqu'à annulation)" #. translators: 1: Amount with currency, 2: Interval (day/week/month/quarter/year), 3: Number of billing cycles -#: inc/fields/payment-markup.php:297 +#: inc/fields/payment-markup.php:681 #, php-format msgid "%1$s per %2$s (%3$s payments)" msgstr "%1$s par %2$s (%3$s paiements)" #. translators: 1: Amount with currency, 2: Interval (day/week/month/quarter/year) -#: inc/fields/payment-markup.php:307 +#: inc/fields/payment-markup.php:691 #, php-format msgid "%1$s per %2$s" msgstr "%1$s par %2$s" #. translators: 1: Amount with currency placeholder, 2: Interval (day/week/month/quarter/year) -#: inc/fields/payment-markup.php:334 +#: inc/fields/payment-markup.php:714 #, php-format msgid "{amount} per %s (until cancelled)" msgstr "{amount} par %s (jusqu'à annulation)" #. translators: 1: Amount with currency placeholder, 2: Interval (day/week/month/quarter/year), 3: Number of billing cycles -#: inc/fields/payment-markup.php:337 +#: inc/fields/payment-markup.php:717 #, php-format msgid "{amount} per %1$s (%2$s payments)" msgstr "{amount} par %1$s (%2$s paiements)" #. translators: 1: Amount with currency placeholder, 2: Interval (day/week/month/quarter/year) -#: inc/fields/payment-markup.php:340 +#: inc/fields/payment-markup.php:720 #, php-format msgid "{amount} per %s" msgstr "{amount} par %s" #. translators: %s: Minimum amount with currency -#: inc/fields/payment-markup.php:353 +#: inc/fields/payment-markup.php:740 #, php-format msgid "Minimum amount: %s" msgstr "Montant minimum : %s" -#: inc/fields/payment-markup.php:385 +#: inc/fields/payment-markup.php:486 msgid "Processing payment..." msgstr "Traitement du paiement..." -#: inc/fields/payment-markup.php:579 +#: inc/fields/payment-markup.php:906 msgid "day" msgstr "jour" -#: inc/fields/payment-markup.php:580 +#: inc/fields/payment-markup.php:907 msgid "week" msgstr "semaine" -#: inc/fields/payment-markup.php:581 +#: inc/fields/payment-markup.php:908 msgid "month" msgstr "mois" -#: inc/fields/payment-markup.php:582 +#: inc/fields/payment-markup.php:909 msgid "quarter" msgstr "quart" -#: inc/fields/payment-markup.php:583 +#: inc/fields/payment-markup.php:910 msgid "year" msgstr "année" -#: inc/fields/payment-markup.php:608 +#: inc/fields/payment-markup.php:935 msgid "Test mode is enabled:" msgstr "Le mode test est activé :" -#: inc/fields/payment-markup.php:610 +#: inc/fields/payment-markup.php:937 msgid "Click here to enable live mode and accept payment" msgstr "Cliquez ici pour activer le mode en direct et accepter le paiement" @@ -12195,6 +12192,7 @@ msgstr "Formulaire inconnu" msgid "N/A" msgstr "N/A" +#: inc/fields/payment-markup.php:247 #: inc/payments/admin/admin-handler.php:975 #: inc/payments/payment-history-shortcode.php:306 #: assets/build/blocks.js:172 @@ -12223,21 +12221,21 @@ msgstr "Inconnu" #: inc/payments/admin/admin-handler.php:1468 #: inc/payments/admin/admin-handler.php:1472 #: inc/payments/admin/admin-handler.php:1476 -#: inc/payments/front-end.php:811 -#: inc/payments/front-end.php:1209 +#: inc/payments/front-end.php:854 +#: inc/payments/front-end.php:1253 msgid "Guest User" msgstr "Utilisateur Invité" -#: inc/payments/front-end.php:91 +#: inc/payments/front-end.php:92 msgid "Invalid payment amount." msgstr "Montant de paiement invalide." -#: inc/payments/front-end.php:107 +#: inc/payments/front-end.php:109 msgid "Valid customer email is required for payments." msgstr "Un e-mail client valide est requis pour les paiements." -#: inc/payments/front-end.php:113 -#: inc/payments/front-end.php:320 +#: inc/payments/front-end.php:115 +#: inc/payments/front-end.php:340 #: inc/payments/stripe/admin-stripe-handler.php:877 #: inc/payments/stripe/payments-settings.php:349 #: inc/payments/stripe/payments-settings.php:474 @@ -12247,137 +12245,137 @@ msgstr "Un e-mail client valide est requis pour les paiements." msgid "Stripe is not connected." msgstr "Stripe n'est pas connecté." -#: inc/payments/front-end.php:119 -#: inc/payments/front-end.php:326 -#: inc/payments/front-end.php:610 -#: inc/payments/front-end.php:1099 +#: inc/payments/front-end.php:121 +#: inc/payments/front-end.php:346 +#: inc/payments/front-end.php:634 +#: inc/payments/front-end.php:1142 msgid "Stripe secret key not found." msgstr "Clé secrète Stripe introuvable." #. translators: %s: formatted payment amount -#: inc/payments/front-end.php:201 +#: inc/payments/front-end.php:203 #, php-format msgid "The payment amount (%s) is below the minimum allowed. Stripe only processes amounts above 50¢." msgstr "Le montant du paiement (%s) est inférieur au minimum autorisé. Stripe ne traite que les montants supérieurs à 50¢." #. translators: %s: Field name -#: inc/payments/front-end.php:268 +#: inc/payments/front-end.php:273 #, php-format msgid "Missing required field: %s" msgstr "Champ requis manquant : %s" -#: inc/payments/front-end.php:287 +#: inc/payments/front-end.php:292 msgid "Valid customer email is required for subscriptions." msgstr "Un e-mail client valide est requis pour les abonnements." -#: inc/payments/front-end.php:292 +#: inc/payments/front-end.php:297 msgid "Customer name is required for subscriptions." msgstr "Le nom du client est requis pour les abonnements." -#: inc/payments/front-end.php:308 +#: inc/payments/front-end.php:314 msgid "Amount must be greater than 0" msgstr "Le montant doit être supérieur à 0" -#: inc/payments/front-end.php:314 +#: inc/payments/front-end.php:322 msgid "Invalid billing interval" msgstr "Intervalle de facturation invalide" -#: inc/payments/front-end.php:337 +#: inc/payments/front-end.php:357 msgid "Failed to create customer for subscription." msgstr "Échec de la création du client pour l'abonnement." -#: inc/payments/front-end.php:370 -#: inc/payments/front-end.php:386 +#: inc/payments/front-end.php:390 +#: inc/payments/front-end.php:406 msgid "Failed to create subscription through middleware." msgstr "Échec de la création de l'abonnement via le middleware." -#: inc/payments/front-end.php:391 +#: inc/payments/front-end.php:411 msgid "Empty response from subscription creation." msgstr "Réponse vide de la création d'abonnement." -#: inc/payments/front-end.php:396 +#: inc/payments/front-end.php:416 msgid "Invalid JSON response from subscription creation." msgstr "Réponse JSON invalide lors de la création de l'abonnement." -#: inc/payments/front-end.php:400 -#: inc/payments/front-end.php:404 +#: inc/payments/front-end.php:420 +#: inc/payments/front-end.php:424 msgid "Invalid subscription data." msgstr "Données d'abonnement invalides." -#: inc/payments/front-end.php:411 +#: inc/payments/front-end.php:431 msgid "Failed to create subscription." msgstr "Échec de la création de l'abonnement." #. translators: %s: Error message -#: inc/payments/front-end.php:441 +#: inc/payments/front-end.php:464 #, php-format msgid "Unexpected error: %s" msgstr "Erreur inattendue : %s" -#: inc/payments/front-end.php:581 +#: inc/payments/front-end.php:604 #: inc/payments/stripe/admin-stripe-handler.php:103 #: inc/payments/stripe/admin-stripe-handler.php:184 #: inc/payments/stripe/admin-stripe-handler.php:489 msgid "Subscription ID not found." msgstr "ID d'abonnement introuvable." -#: inc/payments/front-end.php:599 +#: inc/payments/front-end.php:623 msgid "Customer ID not found for the payment." msgstr "ID client introuvable pour le paiement." -#: inc/payments/front-end.php:627 +#: inc/payments/front-end.php:651 msgid "Failed to retrieve setup intent." msgstr "Échec de la récupération de l'intention de configuration." -#: inc/payments/front-end.php:656 +#: inc/payments/front-end.php:699 msgid "Failed to update subscription." msgstr "Échec de la mise à jour de l'abonnement." -#: inc/payments/front-end.php:664 +#: inc/payments/front-end.php:707 msgid "Latest invoice not found on subscription." msgstr "Dernière facture introuvable sur l'abonnement." -#: inc/payments/front-end.php:677 +#: inc/payments/front-end.php:720 msgid "Failed to retrieve invoice." msgstr "Échec de la récupération de la facture." -#: inc/payments/front-end.php:699 +#: inc/payments/front-end.php:742 msgid "Payment intent not found on invoice." msgstr "Intention de paiement introuvable sur la facture." -#: inc/payments/front-end.php:714 +#: inc/payments/front-end.php:757 msgid "Failed to confirm payment." msgstr "Échec de la confirmation du paiement." -#: inc/payments/front-end.php:730 +#: inc/payments/front-end.php:773 msgid "Failed to retrieve subscription." msgstr "Échec de la récupération de l'abonnement." -#: inc/payments/front-end.php:745 +#: inc/payments/front-end.php:788 msgid "Subscription not found for the payment." msgstr "Abonnement non trouvé pour le paiement." #. translators: %d: User ID -#: inc/payments/front-end.php:809 -#: inc/payments/front-end.php:1209 +#: inc/payments/front-end.php:852 +#: inc/payments/front-end.php:1253 #, php-format msgid "User ID: %d" msgstr "ID utilisateur : %d" #. translators: %s: Invoice status -#: inc/payments/front-end.php:817 +#: inc/payments/front-end.php:860 #, php-format msgid "Invoice Status: %s" msgstr "Statut de la facture : %s" #. translators: Title for subscription verification log -#: inc/payments/front-end.php:824 +#: inc/payments/front-end.php:867 msgid "Subscription Verification" msgstr "Vérification de l'abonnement" #. translators: %s: Subscription ID #. translators: %s: Stripe subscription ID -#: inc/payments/front-end.php:828 +#: inc/payments/front-end.php:871 #: inc/payments/stripe/admin-stripe-handler.php:119 #: inc/payments/stripe/admin-stripe-handler.php:204 #: inc/payments/stripe/admin-stripe-handler.php:505 @@ -12393,8 +12391,8 @@ msgstr "ID d'abonnement : %s" #. 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:830 -#: inc/payments/front-end.php:1220 +#: inc/payments/front-end.php:873 +#: inc/payments/front-end.php:1264 #: inc/payments/stripe/admin-stripe-handler.php:124 #: inc/payments/stripe/admin-stripe-handler.php:209 #: inc/payments/stripe/admin-stripe-handler.php:510 @@ -12409,13 +12407,13 @@ msgid "Payment Gateway: %s" msgstr "Passerelle de paiement : %s" #. translators: %s: Payment Intent ID -#: inc/payments/front-end.php:832 +#: inc/payments/front-end.php:875 #, php-format msgid "Payment Intent ID: %s" msgstr "ID d'intention de paiement : %s" #. translators: %s: Charge ID -#: inc/payments/front-end.php:834 +#: inc/payments/front-end.php:877 #: inc/payments/stripe/stripe-webhook.php:1048 #, php-format msgid "Charge ID: %s" @@ -12423,7 +12421,7 @@ msgstr "ID de charge : %s" #. translators: %s: Subscription Status #. translators: %s: subscription status -#: inc/payments/front-end.php:836 +#: inc/payments/front-end.php:879 #: inc/payments/stripe/admin-stripe-handler.php:129 #: inc/payments/stripe/admin-stripe-handler.php:214 #: inc/payments/stripe/admin-stripe-handler.php:515 @@ -12432,7 +12430,7 @@ msgid "Subscription Status: %s" msgstr "Statut de l'abonnement : %s" #. translators: %s: Customer ID -#: inc/payments/front-end.php:838 +#: inc/payments/front-end.php:881 #: inc/payments/stripe/stripe-webhook.php:1122 #, php-format msgid "Customer ID: %s" @@ -12440,8 +12438,8 @@ msgstr "ID client : %s" #. translators: 1: Amount, 2: Currency #. translators: %1$s: amount, %2$s: currency. -#: inc/payments/front-end.php:840 -#: inc/payments/front-end.php:1222 +#: inc/payments/front-end.php:883 +#: inc/payments/front-end.php:1266 #: inc/payments/stripe/stripe-webhook.php:1053 #: inc/payments/stripe/stripe-webhook.php:1114 #, php-format @@ -12450,34 +12448,34 @@ msgstr "Montant : %1$s %2$s" #. translators: %s: Payment mode (e.g. Live or Test) #. translators: %s: payment mode -#: inc/payments/front-end.php:843 -#: inc/payments/front-end.php:1227 +#: inc/payments/front-end.php:886 +#: inc/payments/front-end.php:1271 #, php-format msgid "Mode: %s" msgstr "Mode : %s" -#: inc/payments/front-end.php:877 +#: inc/payments/front-end.php:920 msgid "Failed to verify subscription." msgstr "Échec de la vérification de l'abonnement." -#: inc/payments/front-end.php:1131 -#: inc/payments/front-end.php:1149 -#: inc/payments/front-end.php:1157 -#: inc/payments/front-end.php:1164 +#: inc/payments/front-end.php:1175 +#: inc/payments/front-end.php:1193 +#: inc/payments/front-end.php:1201 +#: inc/payments/front-end.php:1208 msgid "Failed to retrieve payment intent." msgstr "Échec de la récupération de l'intention de paiement." -#: inc/payments/front-end.php:1172 +#: inc/payments/front-end.php:1216 msgid "Payment was not confirmed successfully." msgstr "Le paiement n'a pas été confirmé avec succès." -#: inc/payments/front-end.php:1214 +#: inc/payments/front-end.php:1258 msgid "Payment Verification" msgstr "Vérification de paiement" #. translators: %s: Stripe transaction ID #. translators: %s: Charge ID -#: inc/payments/front-end.php:1218 +#: inc/payments/front-end.php:1262 #: inc/payments/stripe/stripe-webhook.php:1110 #, php-format msgid "Transaction ID: %s" @@ -12485,18 +12483,18 @@ msgstr "ID de transaction : %s" #. translators: %s: payment status #. translators: %s: Status -#: inc/payments/front-end.php:1224 +#: inc/payments/front-end.php:1268 #: inc/payments/stripe/stripe-webhook.php:576 #: inc/payments/stripe/stripe-webhook.php:1116 #, php-format msgid "Status: %s" msgstr "Statut : %s" -#: inc/payments/front-end.php:1330 +#: inc/payments/front-end.php:1374 msgid "Failed to create Stripe customer." msgstr "Échec de la création du client Stripe." -#: inc/payments/front-end.php:1394 +#: inc/payments/front-end.php:1438 msgid "Failed to create Stripe guest customer." msgstr "Échec de la création du client invité Stripe." @@ -12859,6 +12857,7 @@ msgstr "Erreur inconnue" msgid "Missing payment ID." msgstr "ID de paiement manquant." +#: inc/admin/editor-nudge.php:209 #: inc/payments/stripe/admin-stripe-handler.php:84 #: inc/payments/stripe/admin-stripe-handler.php:470 msgid "You are not allowed to perform this action." @@ -13538,10 +13537,6 @@ msgstr "Choisissez le champ Montant" msgid "Select a field…" msgstr "Sélectionnez un champ…" -#: assets/build/blocks.js:172 -msgid "Pick a field from your form like a number, dropdown, or multichoice whose value should decide the payment amount." -msgstr "Choisissez un champ de votre formulaire, tel qu'un nombre, une liste déroulante ou un choix multiple, dont la valeur doit déterminer le montant du paiement." - #: assets/build/blocks.js:172 msgid "Minimum Amount" msgstr "Montant minimum" @@ -14121,6 +14116,7 @@ msgstr "Utilisez l'IA pour générer des formulaires instantanément à partir d msgid "Build engaging conversational, calculation, and multi-step forms." msgstr "Créez des formulaires engageants de conversation, de calcul et à étapes multiples." +#: inc/admin/editor-nudge.php:192 #: assets/build/forms.js:172 msgid "Create Form" msgstr "Créer un formulaire" @@ -14979,76 +14975,78 @@ msgstr "Le post spécifié n'est pas un formulaire SureForms." msgid "Failed to create duplicate form." msgstr "Échec de la création du formulaire en double." -#: inc/payments/front-end.php:97 -#: inc/payments/front-end.php:298 -#: inc/payments/payment-helper.php:594 +#: inc/payments/front-end.php:98 +#: inc/payments/front-end.php:303 +#: inc/payments/payment-helper.php:595 msgid "Invalid form configuration." msgstr "Configuration de formulaire invalide." -#: inc/payments/payment-helper.php:602 +#: inc/payments/payment-helper.php:603 msgid "Payment configuration not found for this form." msgstr "Configuration de paiement introuvable pour ce formulaire." #. translators: 1: expected currency, 2: received currency -#: inc/payments/payment-helper.php:613 +#: inc/payments/payment-helper.php:614 #, php-format msgid "Currency mismatch: expected %1$s, received %2$s." msgstr "Incohérence de devise : attendu %1$s, reçu %2$s." #. translators: 1: expected amount with currency -#: inc/payments/payment-helper.php:630 +#: inc/payments/payment-helper.php:649 #, php-format msgid "Payment amount must be exactly %1$s." msgstr "Le montant du paiement doit être exactement %1$s." #. translators: 1: minimum amount with currency -#: inc/payments/payment-helper.php:641 +#: inc/payments/payment-helper.php:660 #, php-format msgid "Payment amount must be at least %1$s." msgstr "Le montant du paiement doit être d'au moins %1$s." -#: inc/payments/payment-helper.php:717 +#: inc/payments/payment-helper.php:737 msgid "Invalid payment verification parameters." msgstr "Paramètres de vérification de paiement invalides." -#: inc/payments/payment-helper.php:728 +#: inc/payments/payment-helper.php:748 msgid "Payment verification failed. Invalid payment intent." msgstr "Échec de la vérification du paiement. Intention de paiement invalide." -#: inc/payments/payment-helper.php:814 -#: inc/payments/payment-helper.php:952 +#: inc/payments/payment-helper.php:903 +#: inc/payments/payment-helper.php:1043 msgid "Variable amount field configuration not found." msgstr "Configuration du champ de montant variable introuvable." -#: inc/payments/payment-helper.php:835 +#: inc/payments/payment-helper.php:924 msgid "No payment options are configured for this field." msgstr "Aucune option de paiement n'est configurée pour ce champ." #. translators: %s: currency code -#: inc/payments/payment-helper.php:861 +#: inc/payments/payment-helper.php:950 msgid "Invalid payment amount. Please select a valid amount from the available options." msgstr "Montant de paiement invalide. Veuillez sélectionner un montant valide parmi les options disponibles." #. translators: %1$s: expected amount, %2$s: payment amount -#: inc/payments/payment-helper.php:896 +#: inc/payments/payment-helper.php:986 msgid "Payment configuration not found." msgstr "Configuration de paiement introuvable." #. translators: %1$s: expected amount, %2$s: payment amount -#: inc/payments/payment-helper.php:912 -#: inc/payments/payment-helper.php:964 -#: inc/payments/payment-helper.php:1000 +#: inc/payments/payment-helper.php:1003 +#: inc/payments/payment-helper.php:1055 +#: inc/payments/payment-helper.php:1091 +#: inc/payments/payment-helper.php:1111 #, php-format msgid "Payment amount mismatch. Expected %1$s, received %2$s." msgstr "Incohérence du montant du paiement. Montant attendu %1$s, reçu %2$s." -#: inc/payments/payment-helper.php:941 -#: inc/payments/payment-helper.php:991 +#: 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." msgstr "La valeur du champ de montant variable est requise." #. translators: %1$s: minimum amount, %2$s: payment amount -#: inc/payments/payment-helper.php:1012 +#: inc/payments/payment-helper.php:1125 #, php-format msgid "Payment amount below minimum. Minimum: %1$s, received %2$s." msgstr "Montant du paiement inférieur au minimum. Minimum : %1$s, reçu %2$s." @@ -15110,7 +15108,7 @@ msgstr "Une erreur s'est produite lors de la duplication du formulaire." msgid "This will create a copy of \"%s\" with all its settings." msgstr "Cela créera une copie de \"%s\" avec tous ses paramètres." -#: inc/fields/payment-markup.php:413 +#: inc/fields/payment-markup.php:514 msgid "Pay with credit or debit card" msgstr "Payer par carte de crédit ou de débit" @@ -15118,8 +15116,8 @@ msgstr "Payer par carte de crédit ou de débit" msgid "This form is not yet available. Please check back after the scheduled start time." msgstr "Ce formulaire n'est pas encore disponible. Veuillez revenir après l'heure de début prévue." -#: inc/form-restriction.php:165 -#: inc/form-restriction.php:166 +#: inc/form-restriction.php:187 +#: inc/form-restriction.php:188 #: assets/build/formEditor.js:172 msgid "This form is no longer accepting submissions. The submission period has ended." msgstr "Ce formulaire n'accepte plus les soumissions. La période de soumission est terminée." @@ -15134,7 +15132,7 @@ msgstr "Passerelle de paiement introuvable." msgid "Refund processing is not supported for %s gateway." msgstr "Le traitement des remboursements n'est pas pris en charge pour la passerelle %s." -#: inc/payments/payment-helper.php:974 +#: inc/payments/payment-helper.php:1065 msgid "Number field configuration not found." msgstr "Configuration du champ numérique introuvable." @@ -15511,11 +15509,11 @@ msgstr "Le titre du formulaire est requis." msgid "At least one form field is required." msgstr "Au moins un champ de formulaire est requis." -#: inc/abilities/forms/create-form.php:322 +#: inc/abilities/forms/create-form.php:326 msgid "Failed to generate form fields from the provided data." msgstr "Échec de la génération des champs de formulaire à partir des données fournies." -#: inc/abilities/forms/create-form.php:372 +#: inc/abilities/forms/create-form.php:376 msgid "Failed to create the form." msgstr "Échec de la création du formulaire." @@ -15691,23 +15689,23 @@ msgstr "La session d'authentification a expiré. Veuillez réessayer." msgid "Invalid access key format." msgstr "Format de clé d'accès invalide." -#: inc/ai-form-builder/ai-helper.php:182 +#: inc/ai-form-builder/ai-helper.php:175 msgid "Unable to connect to SureForms API. Please check your connection." msgstr "Impossible de se connecter à l'API SureForms. Veuillez vérifier votre connexion." -#: inc/ai-form-builder/ai-helper.php:186 +#: inc/ai-form-builder/ai-helper.php:179 msgid "Unable to verify license. Please check your license key." msgstr "Impossible de vérifier la licence. Veuillez vérifier votre clé de licence." -#: inc/ai-form-builder/ai-helper.php:190 +#: inc/ai-form-builder/ai-helper.php:183 msgid "An error occurred while trying to verify your email. Please check your email you have used to log in or sign up on billing.sureforms.com." msgstr "Une erreur s'est produite lors de la tentative de vérification de votre e-mail. Veuillez vérifier l'e-mail que vous avez utilisé pour vous connecter ou vous inscrire sur billing.sureforms.com." -#: inc/ai-form-builder/ai-helper.php:194 +#: inc/ai-form-builder/ai-helper.php:187 msgid "Unable to verify referer. Please check your referer." msgstr "Impossible de vérifier le référent. Veuillez vérifier votre référent." -#: inc/ai-form-builder/ai-helper.php:202 +#: inc/ai-form-builder/ai-helper.php:195 msgid "Domain Verification Failed on current site. Please try again on another website." msgstr "La vérification de domaine a échoué sur le site actuel. Veuillez réessayer sur un autre site web." @@ -15733,8 +15731,8 @@ msgstr "Je consens à ce que ce site web stocke mes informations afin qu'ils pui msgid "Text field" msgstr "Champ de texte" -#: inc/form-restriction.php:160 -#: inc/form-restriction.php:161 +#: inc/form-restriction.php:182 +#: inc/form-restriction.php:183 #: inc/post-types.php:1203 #: inc/post-types.php:1243 msgid "This form is not yet available. Check back after the scheduled start time." @@ -15744,8 +15742,8 @@ msgstr "Ce formulaire n'est pas encore disponible. Revenez après l'heure de dé #: inc/form-submit.php:400 #: inc/form-submit.php:445 #: inc/form-submit.php:968 -#: inc/payments/front-end.php:77 -#: inc/payments/front-end.php:258 +#: 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 @@ -16100,32 +16098,32 @@ msgid "Enter a valid email address." msgstr "Entrez une adresse e-mail valide." #. translators: %s represents the minimum acceptable value -#: inc/translatable.php:94 +#: inc/translatable.php:97 #, php-format msgid "Minimum value is %s." msgstr "La valeur minimale est %s." #. translators: %s represents the maximum acceptable value -#: inc/translatable.php:97 +#: inc/translatable.php:100 #, php-format msgid "Maximum value is %s." msgstr "La valeur maximale est %s." #. translators: %s represents the minimum number of options to select -#: inc/translatable.php:100 -#: inc/translatable.php:106 +#: inc/translatable.php:103 +#: inc/translatable.php:109 #, php-format msgid "Select at least %s options." msgstr "Sélectionnez au moins %s options." #. translators: %s represents the maximum number of options that can be selected -#: inc/translatable.php:103 -#: inc/translatable.php:109 +#: inc/translatable.php:106 +#: inc/translatable.php:112 #, php-format msgid "You can select up to %s options." msgstr "Vous pouvez sélectionner jusqu'à %s options." -#: inc/translatable.php:120 +#: inc/translatable.php:123 msgid "This form is now closed as we have reached the maximum number of entries." msgstr "Ce formulaire est maintenant fermé car nous avons atteint le nombre maximum d'entrées." @@ -16652,35 +16650,35 @@ msgstr "Récupérer les paramètres globaux de SureForms. Filtrer éventuellemen msgid "Setting categories to retrieve. Omit for all categories." msgstr "Définir les catégories à récupérer. Omettre pour toutes les catégories." -#: inc/abilities/settings/update-global-settings.php:105 +#: inc/abilities/settings/update-global-settings.php:106 msgid "Update Global Settings" msgstr "Mettre à jour les paramètres globaux" -#: inc/abilities/settings/update-global-settings.php:106 +#: inc/abilities/settings/update-global-settings.php:107 msgid "Update SureForms global settings for a specific category: general, validation-messages, email-summary, or security." msgstr "Mettez à jour les paramètres globaux de SureForms pour une catégorie spécifique : général, messages de validation, résumé par e-mail ou sécurité." -#: inc/abilities/settings/update-global-settings.php:139 +#: inc/abilities/settings/update-global-settings.php:140 msgid "The settings category to update." msgstr "La catégorie de paramètres à mettre à jour." -#: inc/abilities/settings/update-global-settings.php:144 +#: inc/abilities/settings/update-global-settings.php:145 msgid "Key-value pairs of settings to update." msgstr "Paires clé-valeur de paramètres à mettre à jour." -#: inc/abilities/settings/update-global-settings.php:180 +#: inc/abilities/settings/update-global-settings.php:181 msgid "Settings category is required." msgstr "La catégorie des paramètres est requise." -#: inc/abilities/settings/update-global-settings.php:188 +#: inc/abilities/settings/update-global-settings.php:189 msgid "Settings data is required." msgstr "Les données de configuration sont requises." -#: inc/abilities/settings/update-global-settings.php:199 +#: inc/abilities/settings/update-global-settings.php:200 msgid "No valid settings keys provided for this category." msgstr "Aucune clé de paramètres valide fournie pour cette catégorie." -#: inc/abilities/settings/update-global-settings.php:225 +#: inc/abilities/settings/update-global-settings.php:226 msgid "Invalid settings category." msgstr "Catégorie de paramètres invalide." @@ -17581,6 +17579,212 @@ msgstr "Złoty polonais" msgid "Dynamic Default Value" msgstr "Valeur par défaut dynamique" +#: inc/admin/editor-nudge.php:191 +msgid "Hey! It looks like you're creating a form. Build a ready-to-use form in under 30 seconds with SureForms AI, with no extra setup required." +msgstr "Hé ! On dirait que vous créez un formulaire. Créez un formulaire prêt à l'emploi en moins de 30 secondes avec SureForms AI, sans configuration supplémentaire requise." + +#: inc/admin/editor-nudge.php:228 +#: inc/admin/editor-nudge.php:237 +msgid "Invalid post." +msgstr "Publication invalide." + +#: inc/admin/editor-nudge.php:246 +msgid "You cannot edit this post." +msgstr "Vous ne pouvez pas modifier ce message." + +#: inc/ai-form-builder/ai-form-builder.php:96 +msgid "The AI did not return a form. Please refine your prompt and try again." +msgstr "L'IA n'a pas renvoyé de formulaire. Veuillez affiner votre invite et réessayer." + +#: inc/ai-form-builder/ai-form-builder.php:104 +msgid "The AI response is missing a form title. Please try again." +msgstr "La réponse de l'IA manque d'un titre de formulaire. Veuillez réessayer." + +#: inc/ai-form-builder/ai-form-builder.php:115 +#: inc/ai-form-builder/field-mapping.php:69 +msgid "The AI was unable to generate form fields. Please try again." +msgstr "L'IA n'a pas pu générer les champs de formulaire. Veuillez réessayer." + +#: inc/ai-form-builder/field-mapping.php:41 +msgid "The AI form data is missing. Please try again." +msgstr "Les données du formulaire d'IA sont manquantes. Veuillez réessayer." + +#: inc/ai-form-builder/field-mapping.php:51 +msgid "The AI form data is not in the expected format." +msgstr "Les données du formulaire d'IA ne sont pas dans le format attendu." + +#: inc/ai-form-builder/field-mapping.php:60 +msgid "The AI response did not include a form. Please try again." +msgstr "La réponse de l'IA n'incluait pas de formulaire. Veuillez réessayer." + +#: inc/ai-form-builder/field-mapping.php:90 +msgid "The AI returned a malformed form field. Please try again." +msgstr "L'IA a renvoyé un champ de formulaire mal formé. Veuillez réessayer." + +#: inc/create-new-form.php:160 +#: inc/create-new-form.php:173 +msgid "Error creating SureForms Form." +msgstr "Erreur lors de la création du formulaire SureForms." + +#. translators: %s represents the minimum number of characters required +#: inc/field-validation.php:289 +#: inc/translatable.php:94 +#, php-format +msgid "Please enter at least %s characters." +msgstr "Veuillez entrer au moins %s caractères." + +#: inc/fields/payment-markup.php:246 +msgid "One-Time Payment" +msgstr "Paiement unique" + +#: inc/fields/payment-markup.php:562 +msgid "Choose payment type" +msgstr "Choisissez le type de paiement" + +#: inc/payments/front-end.php:333 +msgid "Billing interval does not match the form configuration." +msgstr "L'intervalle de facturation ne correspond pas à la configuration du formulaire." + +#: inc/payments/payment-helper.php:627 +msgid "Payment type does not match the form configuration." +msgstr "Le type de paiement ne correspond pas à la configuration du formulaire." + +#: inc/payments/payment-helper.php:760 +msgid "Payment verification failed. Payment type mismatch." +msgstr "Échec de la vérification du paiement. Incompatibilité du type de paiement." + +#: assets/build/blocks.js:172 +msgid "Minimum Characters" +msgstr "Caractères minimum" + +#: assets/build/blocks.js:172 +msgid "Minimum characters cannot exceed Maximum characters." +msgstr "Les caractères minimum ne peuvent pas dépasser les caractères maximum." + +#: assets/build/blocks.js:172 +msgid "Both" +msgstr "Les deux" + +#: assets/build/blocks.js:172 +msgid "One-Time Label" +msgstr "Étiquette unique" + +#: assets/build/blocks.js:172 +msgid "Label shown to users for the one-time payment option." +msgstr "Libellé affiché aux utilisateurs pour l'option de paiement unique." + +#: assets/build/blocks.js:172 +msgid "Subscription Label" +msgstr "Libellé d'abonnement" + +#: assets/build/blocks.js:172 +msgid "Label shown to users for the subscription option." +msgstr "Libellé affiché aux utilisateurs pour l'option d'abonnement." + +#: assets/build/blocks.js:172 +msgid "Default Selection" +msgstr "Sélection par défaut" + +#: assets/build/blocks.js:172 +msgid "Which option is pre-selected when the form loads." +msgstr "Quelle option est présélectionnée lorsque le formulaire se charge." + +#: assets/build/blocks.js:172 +msgid "One-Time Amount Type" +msgstr "Type de montant unique" + +#: assets/build/blocks.js:172 +msgid "Set how the one-time payment amount is determined." +msgstr "Définissez comment le montant du paiement unique est déterminé." + +#: assets/build/blocks.js:172 +msgid "One-Time Fixed Amount" +msgstr "Montant fixe unique" + +#: assets/build/blocks.js:172 +msgid "Amount charged for a one-time payment." +msgstr "Montant facturé pour un paiement unique." + +#: assets/build/blocks.js:172 +msgid "One-Time Amount Field" +msgstr "Champ de montant unique" + +#: assets/build/blocks.js:172 +msgid "Pick a form field whose value determines the one-time payment amount." +msgstr "Sélectionnez un champ de formulaire dont la valeur détermine le montant du paiement unique." + +#: assets/build/blocks.js:172 +msgid "One-Time Minimum Amount" +msgstr "Montant minimum unique" + +#: assets/build/blocks.js:172 +msgid "Minimum amount users can enter for one-time payment (0 for no minimum)." +msgstr "Montant minimum que les utilisateurs peuvent entrer pour un paiement unique (0 pour aucun minimum)." + +#: assets/build/blocks.js:172 +msgid "Subscription Amount Type" +msgstr "Type de montant d'abonnement" + +#: assets/build/blocks.js:172 +msgid "Set how the subscription amount is determined." +msgstr "Définissez comment le montant de l'abonnement est déterminé." + +#: assets/build/blocks.js:172 +msgid "Subscription Fixed Amount" +msgstr "Montant fixe de l'abonnement" + +#: assets/build/blocks.js:172 +msgid "Recurring amount charged per billing interval." +msgstr "Montant récurrent facturé par intervalle de facturation." + +#: assets/build/blocks.js:172 +msgid "Subscription Amount Field" +msgstr "Champ Montant de l'abonnement" + +#: assets/build/blocks.js:172 +msgid "Pick a form field whose value determines the subscription amount." +msgstr "Choisissez un champ de formulaire dont la valeur détermine le montant de l'abonnement." + +#: assets/build/blocks.js:172 +msgid "Subscription Minimum Amount" +msgstr "Montant minimum de l'abonnement" + +#: assets/build/blocks.js:172 +msgid "Minimum amount users can enter for subscription (0 for no minimum)." +msgstr "Montant minimum que les utilisateurs peuvent entrer pour l'abonnement (0 pour aucun minimum)." + +#: 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 "Choisissez un champ de votre formulaire comme un nombre, une liste déroulante, un choix multiple ou un champ caché dont la valeur doit déterminer le montant du paiement." + +#: assets/build/templatePicker.js:172 +msgid "You do not have permission to create forms." +msgstr "Vous n'avez pas la permission de créer des formulaires." + +#: assets/build/templatePicker.js:172 +msgid "The form could not be saved. Please try again." +msgstr "Le formulaire n'a pas pu être enregistré. Veuillez réessayer." + +#: assets/build/templatePicker.js:172 +msgid "Unable to reach the SureForms AI service. Please check your connection and try again." +msgstr "Impossible d'atteindre le service SureForms AI. Veuillez vérifier votre connexion et réessayer." + +#: assets/build/templatePicker.js:172 +msgid "The AI service did not return a response. Please try again." +msgstr "Le service d'IA n'a pas renvoyé de réponse. Veuillez réessayer." + +#: assets/build/templatePicker.js:172 +msgid "Form generation failed. Please try again." +msgstr "La génération du formulaire a échoué. Veuillez réessayer." + +#: assets/build/templatePicker.js:172 +msgid "The AI response was empty. Please refine your prompt and try again." +msgstr "La réponse de l'IA était vide. Veuillez affiner votre invite et réessayer." + +#: assets/build/templatePicker.js:172 +msgid "Unable to build form fields from the AI response." +msgstr "Impossible de créer les champs de formulaire à partir de la réponse de l'IA." + #: inc/post-types.php:205 msgctxt "post type general name" msgid "Forms" diff --git a/languages/sureforms-it_IT-120a6dad015d3891c70f578c2251576b.json b/languages/sureforms-it_IT-120a6dad015d3891c70f578c2251576b.json index a7e4f5f7e..9b7658ffb 100644 --- a/languages/sureforms-it_IT-120a6dad015d3891c70f578c2251576b.json +++ b/languages/sureforms-it_IT-120a6dad015d3891c70f578c2251576b.json @@ -1 +1 @@ -{"translation-revision-date":"2025-01-01T06:16:29+00:00","generator":"WP-CLI\/2.12.0","source":"assets\/build\/templatePicker.js","domain":"messages","locale_data":{"messages":{"":{"domain":"messages","lang":"en","plural-forms":"nplurals=2; plural=(n != 1);"},"Dashboard":["Cruscotto"],"Connect Now":["Connetti ora"],"Authentication Failed":["Autenticazione fallita"],"Contact Support":["Contatta il supporto"],"Click Here to Retry":["Fai clic qui per riprovare"],"Exit to Dashboard":["Esci alla Dashboard"],"AI Form Builder":["Costruttore di Moduli AI"],"Speech recognition is not supported in your current browser. Please use Google Chrome \/ Safari.":["Il riconoscimento vocale non \u00e8 supportato nel tuo browser attuale. Si prega di utilizzare Google Chrome \/ Safari."],"Please allow microphone access to use voice input.":["Si prega di consentire l'accesso al microfono per utilizzare l'input vocale."],"Voice Input":["Input vocale"],"Try Again":["Riprova"],"Please try again after %s.":["Per favore riprova dopo %s."],"You have reached the maximum number of form generations in your Free Plan.":["Hai raggiunto il numero massimo di generazioni di moduli nel tuo Piano Gratuito."],"Unlock Conversational Forms":["Sblocca moduli conversazionali"],"Simple":["Semplice"],"Upgrade Now":["Aggiorna ora"],"Generate with AI":["Genera con l'IA"],"Please check your username and password for the account, and try to reconnect again. Need help?":["Si prega di controllare il nome utente e la password per l'account e provare a riconnettersi. Hai bisogno di aiuto?"],"Describe the form you want to create":["Descrivi il modulo che desideri creare"],"We are building your form\u2026":["Stiamo creando il tuo modulo\u2026"],"Payment":["Pagamento"],"and ":["e"],"more\u2026":["di pi\u00f9\u2026"],"Calculations":["Calcoli"],"Unlock Calculator Forms":["Sblocca i moduli della calcolatrice"],"Build Smart Forms That Calculate Instantly":["Crea moduli intelligenti che calcolano istantaneamente"],"Empower your forms with advanced calculations. From loan calculators to BMI checkers - create interactive forms that give real-time results.":["Potenzia i tuoi moduli con calcoli avanzati. Dai calcolatori di prestiti ai controlli del BMI - crea moduli interattivi che forniscono risultati in tempo reale."],"Add complex formulas with ease":["Aggiungi formule complesse con facilit\u00e0"],"Provide instant answers to users":["Fornisci risposte immediate agli utenti"],"Perfect for finance, health, and pricing forms":["Perfetto per moduli di finanza, salute e prezzi"],"Conversational":["Conversazionale"],"Turn Simple Forms Into Conversations":["Trasforma i moduli semplici in conversazioni"],"Transform boring forms into friendly, chat-like experiences. Ask one question at a time, just like a real conversation, and see higher engagement.":["Trasforma moduli noiosi in esperienze amichevoli simili a una chat. Fai una domanda alla volta, proprio come in una vera conversazione, e osserva un maggiore coinvolgimento."],"One question at a time, in chat flow":["Una domanda alla volta, nel flusso della chat"],"More engaging than traditional forms":["Pi\u00f9 coinvolgente delle forme tradizionali"],"Boosts completion rates with a friendly interface":["Aumenta i tassi di completamento con un'interfaccia amichevole"],"Select this if you need calculations in your form. For example: Loan interest calculator.":["Seleziona questo se hai bisogno di calcoli nel tuo modulo. Ad esempio: Calcolatore di interessi sui prestiti."],"Select this if you want your form to display one question at a time, like a chat.":["Seleziona questo se desideri che il tuo modulo mostri una domanda alla volta, come in una chat."],"Select this if you want to collect payments through your form.":["Seleziona questo se desideri raccogliere pagamenti tramite il tuo modulo."],"%d AI Generations Left. SureForms Premium allows:":["%d Generazioni AI rimanenti. SureForms Premium consente:"],"%d AI Generations Left, Connect to SureForms AI to Get 10 More":["%d generazioni AI rimanenti, connettiti a SureForms AI per ottenerne altre 10"],"%d AI Generations Left. Upgrade to SureForms Premium":["%d Generazioni AI Rimaste. Passa a SureForms Premium"],"Contact form to collect name, email, and message from visitors":["Modulo di contatto per raccogliere nome, email e messaggio dai visitatori"],"Job application form for \"Marketing Manager\" with resume upload":["Modulo di domanda di lavoro per \"Responsabile Marketing\" con caricamento del curriculum"],"Feedback form to ask customers: \"How would you rate our product and what should we improve?\"":["Modulo di feedback per chiedere ai clienti: \"Come valuteresti il nostro prodotto e cosa dovremmo migliorare?\""],"Event registration form for \"Photography Workshop\" with date and seat selection":["Modulo di registrazione per l'evento \"Workshop di Fotografia\" con selezione della data e del posto"],"Newsletter signup form with name and email to join mailing list":["Modulo di iscrizione alla newsletter con nome ed email per unirsi alla lista di distribuzione"],"Order form for \"Custom T-Shirt\" with size, color, and quantity options":["Modulo d'ordine per \"Maglietta personalizzata\" con opzioni di taglia, colore e quantit\u00e0"],"Survey form: \"How satisfied are you with our service? (1\u20135 stars)\"":["Modulo di sondaggio: \"Quanto sei soddisfatto del nostro servizio? (1\u20135 stelle)\""],"Appointment booking form for \"Consultation Call\" with preferred time":["Modulo di prenotazione appuntamento per \"Chiamata di consulenza\" con orario preferito"],"Describe the form that you want":["Descrivi la forma che desideri"],"Generate":["Genera"],"Create Unlimited Forms with AI":["Crea moduli illimitati con l'IA"],"Add Advanced Field Types":["Aggiungi tipi di campo avanzati"],"Create Calculators, Surveys, etc.":["Crea calcolatrici, sondaggi, ecc."],"Form Generation Limit Reached":["Limite di generazione del modulo raggiunto"],"You have reached the maximum number of form generations in your Free Plan. SureForms Premium allows:":["Hai raggiunto il numero massimo di generazioni di moduli nel tuo Piano Gratuito. SureForms Premium consente:"],"%s AI Generations Left.":["%s generazioni di AI rimaste."],"Unlock Unlimited Generations":["Sblocca Generazioni Illimitate"],"Connect to SureForms AI":["Connettiti a SureForms AI"],"You Have Hit Your Free Limit.":["Hai raggiunto il tuo limite gratuito."],"Connect to SureForms AI to Get 10 More.":["Connettiti a SureForms AI per ottenere altri 10."],"Or create it yourself":["Oppure crealo tu stesso"],"Unable to create form":["Impossibile creare il modulo"],"Something went wrong. Please try again.":["Qualcosa \u00e8 andato storto. Per favore riprova."],"Describe what kind of form you want":["Descrivi il tipo di modulo che desideri"],"Click to generate the form":["Fai clic per generare il modulo"],"Connecting to AI service":["Connessione al servizio AI"],"Generating fields":["Generazione di campi"],"Finalizing your form":["Finalizzazione del tuo modulo"],"Opening form editor":["Apertura dell'editor di moduli"],"Design Multistep Forms":["Progetta moduli multistep"],"Send Form Entries to Your CRM or Any App":["Invia le voci del modulo al tuo CRM o a qualsiasi app"],"You've reached your daily generation limit.":["Hai raggiunto il tuo limite giornaliero di generazione."],"You've reached your daily limit for AI form generations.":["Hai raggiunto il tuo limite giornaliero per la generazione di moduli AI."],"Quiz":["Quiz"],"Unlock Quiz Forms":["Sblocca i moduli del quiz"],"Create Engaging Quizzes That Score Automatically":["Crea quiz coinvolgenti che si valutano automaticamente"],"Build interactive quizzes with scored questions and graded results. Perfect for assessments, trivia, and educational content.":["Crea quiz interattivi con domande a punteggio e risultati valutati. Perfetto per valutazioni, quiz e contenuti educativi."],"Auto-score responses instantly":["Valuta automaticamente le risposte all'istante"],"Display graded results to users":["Mostra i risultati valutati agli utenti"],"Perfect for education, training, and fun trivia":["Perfetto per l'istruzione, la formazione e i quiz divertenti"],"Select this to create a quiz with scored questions and graded results.":["Seleziona questo per creare un quiz con domande a punteggio e risultati valutati."],"Select this to create a survey to collect responses and opinions.":["Seleziona questo per creare un sondaggio per raccogliere risposte e opinioni."],"Survey":["Sondaggio"],"Unlock Survey Forms":["Sblocca i moduli del sondaggio"],"Collect Insights with Powerful Surveys":["Raccogli approfondimenti con sondaggi potenti"],"Create surveys to collect responses and opinions. Visualize results with charts and share aggregated insights with your audience.":["Crea sondaggi per raccogliere risposte e opinioni. Visualizza i risultati con grafici e condividi approfondimenti aggregati con il tuo pubblico."],"Aggregate and visualize responses":["Aggregare e visualizzare le risposte"],"Show live results to respondents":["Mostra i risultati in tempo reale ai rispondenti"],"Perfect for feedback, polls, and research":["Perfetto per feedback, sondaggi e ricerche"]}}} \ No newline at end of file +{"translation-revision-date":"2025-01-01T06:16:29+00:00","generator":"WP-CLI\/2.12.0","source":"assets\/build\/templatePicker.js","domain":"messages","locale_data":{"messages":{"":{"domain":"messages","lang":"en","plural-forms":"nplurals=2; plural=(n != 1);"},"Dashboard":["Cruscotto"],"Connect Now":["Connetti ora"],"Authentication Failed":["Autenticazione fallita"],"Contact Support":["Contatta il supporto"],"Click Here to Retry":["Fai clic qui per riprovare"],"Exit to Dashboard":["Esci alla Dashboard"],"AI Form Builder":["Costruttore di Moduli AI"],"Speech recognition is not supported in your current browser. Please use Google Chrome \/ Safari.":["Il riconoscimento vocale non \u00e8 supportato nel tuo browser attuale. Si prega di utilizzare Google Chrome \/ Safari."],"Please allow microphone access to use voice input.":["Si prega di consentire l'accesso al microfono per utilizzare l'input vocale."],"Voice Input":["Input vocale"],"Try Again":["Riprova"],"Please try again after %s.":["Per favore riprova dopo %s."],"You have reached the maximum number of form generations in your Free Plan.":["Hai raggiunto il numero massimo di generazioni di moduli nel tuo Piano Gratuito."],"Unlock Conversational Forms":["Sblocca moduli conversazionali"],"Simple":["Semplice"],"Upgrade Now":["Aggiorna ora"],"Generate with AI":["Genera con l'IA"],"Please check your username and password for the account, and try to reconnect again. Need help?":["Si prega di controllare il nome utente e la password per l'account e provare a riconnettersi. Hai bisogno di aiuto?"],"Describe the form you want to create":["Descrivi il modulo che desideri creare"],"We are building your form\u2026":["Stiamo creando il tuo modulo\u2026"],"Payment":["Pagamento"],"and ":["e"],"more\u2026":["di pi\u00f9\u2026"],"Calculations":["Calcoli"],"Unlock Calculator Forms":["Sblocca i moduli della calcolatrice"],"Build Smart Forms That Calculate Instantly":["Crea moduli intelligenti che calcolano istantaneamente"],"Empower your forms with advanced calculations. From loan calculators to BMI checkers - create interactive forms that give real-time results.":["Potenzia i tuoi moduli con calcoli avanzati. Dai calcolatori di prestiti ai controlli del BMI - crea moduli interattivi che forniscono risultati in tempo reale."],"Add complex formulas with ease":["Aggiungi formule complesse con facilit\u00e0"],"Provide instant answers to users":["Fornisci risposte immediate agli utenti"],"Perfect for finance, health, and pricing forms":["Perfetto per moduli di finanza, salute e prezzi"],"Conversational":["Conversazionale"],"Turn Simple Forms Into Conversations":["Trasforma i moduli semplici in conversazioni"],"Transform boring forms into friendly, chat-like experiences. Ask one question at a time, just like a real conversation, and see higher engagement.":["Trasforma moduli noiosi in esperienze amichevoli simili a una chat. Fai una domanda alla volta, proprio come in una vera conversazione, e osserva un maggiore coinvolgimento."],"One question at a time, in chat flow":["Una domanda alla volta, nel flusso della chat"],"More engaging than traditional forms":["Pi\u00f9 coinvolgente delle forme tradizionali"],"Boosts completion rates with a friendly interface":["Aumenta i tassi di completamento con un'interfaccia amichevole"],"Select this if you need calculations in your form. For example: Loan interest calculator.":["Seleziona questo se hai bisogno di calcoli nel tuo modulo. Ad esempio: Calcolatore di interessi sui prestiti."],"Select this if you want your form to display one question at a time, like a chat.":["Seleziona questo se desideri che il tuo modulo mostri una domanda alla volta, come in una chat."],"Select this if you want to collect payments through your form.":["Seleziona questo se desideri raccogliere pagamenti tramite il tuo modulo."],"%d AI Generations Left. SureForms Premium allows:":["%d Generazioni AI rimanenti. SureForms Premium consente:"],"%d AI Generations Left, Connect to SureForms AI to Get 10 More":["%d generazioni AI rimanenti, connettiti a SureForms AI per ottenerne altre 10"],"%d AI Generations Left. Upgrade to SureForms Premium":["%d Generazioni AI Rimaste. Passa a SureForms Premium"],"Contact form to collect name, email, and message from visitors":["Modulo di contatto per raccogliere nome, email e messaggio dai visitatori"],"Job application form for \"Marketing Manager\" with resume upload":["Modulo di domanda di lavoro per \"Responsabile Marketing\" con caricamento del curriculum"],"Feedback form to ask customers: \"How would you rate our product and what should we improve?\"":["Modulo di feedback per chiedere ai clienti: \"Come valuteresti il nostro prodotto e cosa dovremmo migliorare?\""],"Event registration form for \"Photography Workshop\" with date and seat selection":["Modulo di registrazione per l'evento \"Workshop di Fotografia\" con selezione della data e del posto"],"Newsletter signup form with name and email to join mailing list":["Modulo di iscrizione alla newsletter con nome ed email per unirsi alla lista di distribuzione"],"Order form for \"Custom T-Shirt\" with size, color, and quantity options":["Modulo d'ordine per \"Maglietta personalizzata\" con opzioni di taglia, colore e quantit\u00e0"],"Survey form: \"How satisfied are you with our service? (1\u20135 stars)\"":["Modulo di sondaggio: \"Quanto sei soddisfatto del nostro servizio? (1\u20135 stelle)\""],"Appointment booking form for \"Consultation Call\" with preferred time":["Modulo di prenotazione appuntamento per \"Chiamata di consulenza\" con orario preferito"],"Describe the form that you want":["Descrivi la forma che desideri"],"Generate":["Genera"],"Create Unlimited Forms with AI":["Crea moduli illimitati con l'IA"],"Add Advanced Field Types":["Aggiungi tipi di campo avanzati"],"Create Calculators, Surveys, etc.":["Crea calcolatrici, sondaggi, ecc."],"Form Generation Limit Reached":["Limite di generazione del modulo raggiunto"],"You have reached the maximum number of form generations in your Free Plan. SureForms Premium allows:":["Hai raggiunto il numero massimo di generazioni di moduli nel tuo Piano Gratuito. SureForms Premium consente:"],"%s AI Generations Left.":["%s generazioni di AI rimaste."],"Unlock Unlimited Generations":["Sblocca Generazioni Illimitate"],"Connect to SureForms AI":["Connettiti a SureForms AI"],"You Have Hit Your Free Limit.":["Hai raggiunto il tuo limite gratuito."],"Connect to SureForms AI to Get 10 More.":["Connettiti a SureForms AI per ottenere altri 10."],"Or create it yourself":["Oppure crealo tu stesso"],"Unable to create form":["Impossibile creare il modulo"],"Something went wrong. Please try again.":["Qualcosa \u00e8 andato storto. Per favore riprova."],"Describe what kind of form you want":["Descrivi il tipo di modulo che desideri"],"Click to generate the form":["Fai clic per generare il modulo"],"Connecting to AI service":["Connessione al servizio AI"],"Generating fields":["Generazione di campi"],"Finalizing your form":["Finalizzazione del tuo modulo"],"Opening form editor":["Apertura dell'editor di moduli"],"Design Multistep Forms":["Progetta moduli multistep"],"Send Form Entries to Your CRM or Any App":["Invia le voci del modulo al tuo CRM o a qualsiasi app"],"You've reached your daily generation limit.":["Hai raggiunto il tuo limite giornaliero di generazione."],"You've reached your daily limit for AI form generations.":["Hai raggiunto il tuo limite giornaliero per la generazione di moduli AI."],"Quiz":["Quiz"],"Unlock Quiz Forms":["Sblocca i moduli del quiz"],"Create Engaging Quizzes That Score Automatically":["Crea quiz coinvolgenti che si valutano automaticamente"],"Build interactive quizzes with scored questions and graded results. Perfect for assessments, trivia, and educational content.":["Crea quiz interattivi con domande a punteggio e risultati valutati. Perfetto per valutazioni, quiz e contenuti educativi."],"Auto-score responses instantly":["Valuta automaticamente le risposte all'istante"],"Display graded results to users":["Mostra i risultati valutati agli utenti"],"Perfect for education, training, and fun trivia":["Perfetto per l'istruzione, la formazione e i quiz divertenti"],"Select this to create a quiz with scored questions and graded results.":["Seleziona questo per creare un quiz con domande a punteggio e risultati valutati."],"Select this to create a survey to collect responses and opinions.":["Seleziona questo per creare un sondaggio per raccogliere risposte e opinioni."],"Survey":["Sondaggio"],"Unlock Survey Forms":["Sblocca i moduli del sondaggio"],"Collect Insights with Powerful Surveys":["Raccogli approfondimenti con sondaggi potenti"],"Create surveys to collect responses and opinions. Visualize results with charts and share aggregated insights with your audience.":["Crea sondaggi per raccogliere risposte e opinioni. Visualizza i risultati con grafici e condividi approfondimenti aggregati con il tuo pubblico."],"Aggregate and visualize responses":["Aggregare e visualizzare le risposte"],"Show live results to respondents":["Mostra i risultati in tempo reale ai rispondenti"],"Perfect for feedback, polls, and research":["Perfetto per feedback, sondaggi e ricerche"],"You do not have permission to create forms.":["Non hai il permesso di creare moduli."],"The form could not be saved. Please try again.":["Il modulo non pu\u00f2 essere salvato. Per favore riprova."],"Unable to reach the SureForms AI service. Please check your connection and try again.":["Impossibile raggiungere il servizio SureForms AI. Controlla la tua connessione e riprova."],"The AI service did not return a response. Please try again.":["Il servizio AI non ha restituito una risposta. Per favore riprova."],"Form generation failed. Please try again.":["La generazione del modulo non \u00e8 riuscita. Si prega di riprovare."],"The AI response was empty. Please refine your prompt and try again.":["La risposta dell'IA era vuota. Per favore, perfeziona il tuo prompt e riprova."],"Unable to build form fields from the AI response.":["Impossibile creare i campi del modulo dalla risposta dell'AI."]}}} \ No newline at end of file diff --git a/languages/sureforms-it_IT-4b62e3f004dea2c587b5a3069263d994.json b/languages/sureforms-it_IT-4b62e3f004dea2c587b5a3069263d994.json index 7a85419c9..e91d06769 100644 --- a/languages/sureforms-it_IT-4b62e3f004dea2c587b5a3069263d994.json +++ b/languages/sureforms-it_IT-4b62e3f004dea2c587b5a3069263d994.json @@ -1 +1 @@ -{"translation-revision-date":"2025-01-01T06:16:29+00:00","generator":"WP-CLI\/2.12.0","source":"assets\/build\/blocks.js","domain":"messages","locale_data":{"messages":{"":{"domain":"messages","lang":"en","plural-forms":"nplurals=2; plural=(n != 1);"},"Settings":["Impostazioni"],"Search":["Cerca"],"Fields":["Campi"],"Image":["Immagine"],"Submit":["Invia"],"Required":["Richiesto"],"Form Title":["Titolo del modulo"],"Show":["Mostra"],"Hide":["Nascondi"],"Edit Form":["Modifica modulo"],"Icon":["Icona"],"Desktop":["Desktop"],"Medium":["Medio"],"Mobile":["Cellulare"],"Repeat":["Ripeti"],"Scroll":["Scorri"],"Tablet":["Tablet"],"Basic":["Base"],"(no title)":["(nessun titolo)"],"Select a Form":["Seleziona un modulo"],"No forms found\u2026":["Nessun modulo trovato\u2026"],"Choose":["Scegli"],"Create New":["Crea Nuovo"],"Change Form":["Modifica modulo"],"This form has been deleted or is unavailable.":["Questo modulo \u00e8 stato eliminato o non \u00e8 disponibile."],"Form Settings":["Impostazioni del modulo"],"Show Form Title on this Page":["Mostra il titolo del modulo su questa pagina"],"Note: For editing SureForms, please refer to the SureForms Editor - ":["Nota: Per modificare i SureForms, fare riferimento all'Editor di SureForms -"],"Field preview":["Anteprima del campo"],"General":["Generale"],"Style":["Stile"],"Advanced":["Avanzato"],"No tags available":["Nessun tag disponibile"],"Device":["Dispositivo"],"Select Shortcodes":["Seleziona i codici brevi"],"Page Break Label":["Etichetta di interruzione di pagina"],"Next":["Avanti"],"Back":["Indietro"],"Reset":["Reimposta"],"Generic tags":["Tag generici"],"Pixel":["Pixel"],"Em":["Em"],"Select Units":["Seleziona unit\u00e0"],"%s units":["%s unit\u00e0"],"Margin":["Margine"],"Attributes":["Attributi"],"Input Pattern":["Schema di input"],"None":["Nessuno"],"(###) ###-####":["(###) ###-####"],"(##) ####-####":["(##) ####-####"],"27\/08\/2024":["27\/08\/2024"],"23:59:59":["23:59:59"],"27\/08\/2024 23:59:59":["27\/08\/2024 23:59:59"],"Custom":["Personalizzato"],"Custom Mask":["Maschera personalizzata"],"Please check the documentation to manage custom input pattern ":["Si prega di controllare la documentazione per gestire il modello di input personalizzato"],"here":["qui"],"Default Value":["Valore predefinito"],"Error Message":["Messaggio di errore"],"Help Text":["Testo di aiuto"],"Number Format":["Formato numero"],"US Style (Eg: 9,999.99)":["Stile USA (Es: 9.999,99)"],"EU Style (Eg: 9.999,99)":["Stile UE (Es: 9.999,99)"],"Minimum Value":["Valore minimo"],"Maximum Value":["Valore massimo"],"Please check the Minimum and Maximum value":["Si prega di controllare il valore minimo e massimo"],"Enable Email Confirmation":["Abilita la conferma email"],"Checked by Default":["Selezionato per impostazione predefinita"],"Error message":["Messaggio di errore"],"Checked by default":["Selezionato per impostazione predefinita"],"Please add a option props to MultiButtonsControl":["Si prega di aggiungere un'opzione props a MultiButtonsControl"],"Icon Library":["Libreria di icone"],"Close":["Chiudi"],"All Icons":["Tutte le icone"],"Other":["Altro"],"No Icons Found":["Nessuna icona trovata"],"Insert Icon":["Inserisci icona"],"Change Icon":["Cambia icona"],"Choose Icon":["Scegli icona"],"Confirm":["Conferma"],"Cancel":["Annulla"],"Processing\u2026":["Elaborazione\u2026"],"Select Video":["Seleziona video"],"Change Video":["Cambia video"],"Select Lottie Animation":["Seleziona animazione Lottie"],"Change Lottie Animation":["Cambia animazione Lottie"],"Upload SVG":["Carica SVG"],"Change SVG":["Cambia SVG"],"Select Image":["Seleziona immagine"],"Change Image":["Cambia immagine"],"Upload SVG?":["Caricare SVG?"],"Upload SVG can be potentially risky. Are you sure?":["Caricare SVG pu\u00f2 essere potenzialmente rischioso. Sei sicuro?"],"Upload Anyway":["Carica comunque"],"Bulk Add":["Aggiunta in blocco"],"Bulk Add Options":["Aggiungi opzioni in blocco"],"Enter each option on a new line.":["Inserisci ogni opzione su una nuova riga."],"Insert Options":["Inserisci opzioni"],"Full Width":["Larghezza completa"],"Option Type":["Tipo di opzione"],"Edit Options":["Opzioni di modifica"],"Add New Option":["Aggiungi nuova opzione"],"ADD":["AGGIUNGI"],"Enable Auto Country Detection":["Abilita il rilevamento automatico del paese"],"%s Width":["Larghezza %s"],"Upgrade":["Aggiornamento"],"Clear":["Chiaro"],"Select Color":["Seleziona colore"],"Primary Color":["Colore primario"],"Text Color":["Colore del testo"],"Field Spacing":["Spaziatura del campo"],"Small":["Piccolo"],"Large":["Grande"],"Left":["Sinistra"],"Center":["Centro"],"Right":["Destra"],"Color":["Colore"],"Background Color":["Colore di sfondo"],"Auto":["Auto"],"Default":["Predefinito"],"Normal":["Normale"],"%":["%"],"Top":["In alto"],"Bottom":["Fondo"],"Width":["Larghezza"],"Size":["Dimensione"],"EM":["EM"],"Padding":["Riempimento"],"Color 1":["Colore 1"],"Color 2":["Colore 2"],"Type":["Tipo"],"Linear":["Lineare"],"Radial":["Radiale"],"Location 1":["Posizione 1"],"Location 2":["Posizione 2"],"Angle":["Angolo"],"Classic":["Classico"],"Gradient":["Gradiente"],"Horizontal":["Orizzontale"],"Vertical":["Verticale"],"Background":["Sfondo"],"Cover":["Copertina"],"Contain":["Contenere"],"Layout":["Layout"],"Overlay":["Sovrapposizione"],"No Repeat":["Nessuna ripetizione"],"Overlay Opacity":["Opacit\u00e0 dell'overlay"],"Conditional Logic":["Logica Condizionale"],"Upgrade to the SureForms Starter Plan to create dynamic forms that adapt based on user input, offering a personalised and efficient form experience.":["Passa al piano Starter di SureForms per creare moduli dinamici che si adattano in base all'input dell'utente, offrendo un'esperienza modulare personalizzata ed efficiente."],"Enable Conditional Logic":["Abilita la logica condizionale"],"this field if":["questo campo se"],"Configure Conditions":["Configura condizioni"],"Premium":["Premium"],"Overlay Type":["Tipo di sovrapposizione"],"Image Overlay Color":["Colore di sovrapposizione dell'immagine"],"Image Position":["Posizione dell'immagine"],"Attachment":["Allegato"],"Fixed":["Fisso"],"Blend Mode":["Modalit\u00e0 di fusione"],"Multiply":["Moltiplica"],"Screen":["Schermo"],"Darken":["Scurisci"],"Lighten":["Alleggerire"],"Color Dodge":["Schiarisci colore"],"Saturation":["Saturazione"],"Repeat-x":["Ripeti-x"],"Repeat-y":["Ripeti-y"],"PX":["PX"],"Button":["Pulsante"],"Prefix Label":["Etichetta prefisso"],"Suffix Label":["Etichetta suffisso"],"Border Radius":["Raggio del bordo"],"Form Theme":["Tema del modulo"],"Select Gradient":["Seleziona sfumatura"],"Unlock Conditional Logic Editor":["Sblocca l'editor di logica condizionale"],"Rich Text Editor":["Editor di testo ricco"],"Read Only":["Solo lettura"],"Select Country":["Seleziona Paese"],"Default Country":["Paese predefinito"],"Subscription":["Abbonamento"],"One Time":["Una volta"],"Unique Entry":["Ingresso Unico"],"Maximum Characters":["Caratteri massimi"],"Textarea Height":["Altezza dell'area di testo"],"Minimum Selections":["Selezioni Minime"],"Maximum Selections":["Selezioni massime"],"Add Numeric Values to Options":["Aggiungi valori numerici alle opzioni"],"Single Choice Only":["Solo una scelta"],"Enable Dropdown Search":["Abilita la ricerca a discesa"],"Allow Multiple":["Consenti multipli"],"%1$s fields are required. Please configure these fields in the block settings.":["I campi %1$s sono obbligatori. Si prega di configurare questi campi nelle impostazioni del blocco."],"%1$s field is required. Please configure this field in the block settings.":["Il campo %1$s \u00e8 obbligatorio. Si prega di configurare questo campo nelle impostazioni del blocco."],"You need to configure a payment account to collect payments from this form. Please configure your payment provider to proceed.":["\u00c8 necessario configurare un account di pagamento per raccogliere i pagamenti da questo modulo. Si prega di configurare il proprio fornitore di pagamento per procedere."],"Configure Payment Account":["Configura l'account di pagamento"],"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.":["Questo \u00e8 un segnaposto per il blocco di pagamento. I campi di pagamento effettivi per il\/i fornitore\/i di pagamento configurato\/i appariranno solo quando visualizzi in anteprima o pubblichi il modulo."],"2 Payments":["2 Pagamenti"],"3 Payments":["3 Pagamenti"],"4 Payments":["4 Pagamenti"],"5 Payments":["5 Pagamenti"],"Never":["Mai"],"Stop Subscription After":["Interrompi l'abbonamento dopo"],"Choose when to automatically stop the subscription":["Scegli quando interrompere automaticamente l'abbonamento"],"Number of Payments":["Numero di pagamenti"],"Enter a number between 1 to 100":["Inserisci un numero tra 1 e 100"],"Form Field":["Campo del modulo"],"Payment Type":["Tipo di pagamento"],"Subscription Plan Name":["Nome del piano di abbonamento"],"Billing Interval":["Intervallo di fatturazione"],"Daily":["Quotidiano"],"Weekly":["Settimanale"],"Monthly":["Mensile"],"Quarterly":["Trimestrale"],"Yearly":["Annuale"],"Amount Type":["Tipo di importo"],"Fixed Amount":["Importo fisso"],"Dynamic Amount":["Importo Dinamico"],"Choose whether to charge a fixed amount or charge the amount based on user input in other form fields.":["Scegli se addebitare un importo fisso o addebitare l'importo in base all'input dell'utente in altri campi del modulo."],"Set the exact amount you want to charge. Users won\u2019t be able to change it":["Imposta l'importo esatto che desideri addebitare. Gli utenti non potranno modificarlo"],"Choose Amount Field":["Scegli il campo Importo"],"Select a field\u2026":["Seleziona un campo\u2026"],"Pick a field from your form like a number, dropdown, or multichoice whose value should decide the payment amount.":["Scegli un campo dal tuo modulo, come un numero, un menu a tendina o una scelta multipla, il cui valore dovrebbe determinare l'importo del pagamento."],"Minimum Amount":["Importo minimo"],"Set the minimum amount users can enter (0 for no minimum)":["Imposta l'importo minimo che gli utenti possono inserire (0 per nessun minimo)"],"Customer Name Field (Required)":["Campo Nome Cliente (Obbligatorio)"],"Customer Name Field (Optional)":["Campo Nome Cliente (Facoltativo)"],"Select the input field that contains the customer name (Required for subscriptions)":["Seleziona il campo di input che contiene il nome del cliente (Richiesto per gli abbonamenti)"],"Select the input field that contains the customer name":["Seleziona il campo di input che contiene il nome del cliente"],"Customer Email Field (Required)":["Campo Email Cliente (Obbligatorio)"],"Select the email field that contains the customer email":["Seleziona il campo email che contiene l'email del cliente"],"Payment":["Pagamento"],"%s - Order ID":["%s - ID Ordine"],"%s - Amount":["%s - Importo"],"%s - Customer Email":["%s - Email del cliente"],"%s - Customer Name":["%s - Nome del cliente"],"%s - Status":["%s - Stato"],"Button Alignment":["Allineamento del pulsante"],"Placeholder":["Segnaposto"],"Preselect this option":["Preseleziona questa opzione"],"Restrict Country Codes":["Limita i codici paese"],"Restriction Type":["Tipo di restrizione"],"Allow":["Permetti"],"Block":["Blocca"],"Select Allowed Countries":["Seleziona i Paesi consentiti"],"Choose countries\u2026":["Scegli i paesi\u2026"],"Choose which country codes users can select in the phone number field. Leave empty to allow all country codes.":["Scegli quali codici paese gli utenti possono selezionare nel campo del numero di telefono. Lascia vuoto per consentire tutti i codici paese."],"Select Blocked Countries":["Seleziona Paesi Bloccati"],"These countries will be hidden from the dropdown.":["Questi paesi saranno nascosti dal menu a tendina."],"Bulk Edit":["Modifica in blocco"],"Select Layout":["Seleziona layout"],"Number of Columns":["Numero di colonne"],"Validation Message for Duplicate":["Messaggio di convalida per duplicato"],"Click here to insert a form":["Fai clic qui per inserire un modulo"],"Inherit Form's Original Style":["Eredita lo stile originale del modulo"],"Text on Primary":["Testo su Primario"],"%s - Description":["%s - Descrizione"],"Upgrade to Unlock":["Aggiorna per sbloccare"],"Custom (Premium)":["Personalizzato (Premium)"],"Select a theme style for this form embed.":["Seleziona uno stile tema per questo modulo incorporato."],"Colors":["Colori"],"Advanced Styling":["Stile avanzato"],"Unlock Custom Styling":["Sblocca lo stile personalizzato"],"Switch to Custom Mode to take full control of your form's design and spacing.":["Passa alla Modalit\u00e0 Personalizzata per avere il pieno controllo del design e della spaziatura del tuo modulo."],"Full color control (buttons, fields, text)":["Controllo completo del colore (bottoni, campi, testo)"],"Row and column gap control":["Controllo dello spazio tra righe e colonne"],"Field spacing and layout precision":["Spaziatura dei campi e precisione del layout"],"Complete button styling":["Completare lo stile del pulsante"],"Payment Description":["Descrizione del pagamento"],"Shown on payment receipts and in your payment dashboard (Stripe and PayPal). Leave blank to use the default.":["Mostrato sulle ricevute di pagamento e nel tuo cruscotto dei pagamenti (Stripe e PayPal). Lascia vuoto per utilizzare il predefinito."],"Slug":["Lumaca"],"Auto-generated on save":["Generato automaticamente al salvataggio"],"This slug is already used by another field. It will revert to the previous value.":["Questo slug \u00e8 gi\u00e0 utilizzato da un altro campo. Torner\u00e0 al valore precedente."],"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.":["La modifica dello slug potrebbe interrompere l'invio dei moduli, la logica condizionale, le integrazioni o qualsiasi altra funzione che attualmente fa riferimento a questo slug. Dovrai aggiornare manualmente tutti questi riferimenti."],"Field Slug":["Slug del campo"],"Location Services":["Servizi di localizzazione"],"Unlock Address Autocomplete":["Sblocca il completamento automatico degli indirizzi"],"Upgrade to enable Google Address Autocomplete with interactive map preview, making address entry faster and more accurate for your users.":["Aggiorna per abilitare il completamento automatico degli indirizzi di Google con l'anteprima interattiva della mappa, rendendo l'inserimento degli indirizzi pi\u00f9 veloce e preciso per i tuoi utenti."],"Enable Google Autocomplete":["Abilita il completamento automatico di Google"],"Show Interactive Map":["Mostra mappa interattiva"],"Payments Per Page":["Pagamenti per pagina"],"Show Subscriptions Section":["Mostra la sezione Abbonamenti"],"Show a dedicated subscriptions section above payment history.":["Mostra una sezione dedicata agli abbonamenti sopra la cronologia dei pagamenti."],"Payment Dashboard":["Dashboard dei pagamenti"],"View your payments and manage subscriptions in a single dashboard.":["Visualizza i tuoi pagamenti e gestisci gli abbonamenti in un'unica dashboard."],"Dynamic Default Value":["Valore predefinito dinamico"]}}} \ No newline at end of file +{"translation-revision-date":"2025-01-01T06:16:29+00:00","generator":"WP-CLI\/2.12.0","source":"assets\/build\/blocks.js","domain":"messages","locale_data":{"messages":{"":{"domain":"messages","lang":"en","plural-forms":"nplurals=2; plural=(n != 1);"},"Settings":["Impostazioni"],"Search":["Cerca"],"Fields":["Campi"],"Image":["Immagine"],"Submit":["Invia"],"Required":["Richiesto"],"Form Title":["Titolo del modulo"],"Show":["Mostra"],"Hide":["Nascondi"],"Edit Form":["Modifica modulo"],"Icon":["Icona"],"Desktop":["Desktop"],"Medium":["Medio"],"Mobile":["Cellulare"],"Repeat":["Ripeti"],"Scroll":["Scorri"],"Tablet":["Tablet"],"Basic":["Base"],"(no title)":["(nessun titolo)"],"Select a Form":["Seleziona un modulo"],"No forms found\u2026":["Nessun modulo trovato\u2026"],"Choose":["Scegli"],"Create New":["Crea Nuovo"],"Change Form":["Modifica modulo"],"This form has been deleted or is unavailable.":["Questo modulo \u00e8 stato eliminato o non \u00e8 disponibile."],"Form Settings":["Impostazioni del modulo"],"Show Form Title on this Page":["Mostra il titolo del modulo su questa pagina"],"Note: For editing SureForms, please refer to the SureForms Editor - ":["Nota: Per modificare i SureForms, fare riferimento all'Editor di SureForms -"],"Field preview":["Anteprima del campo"],"General":["Generale"],"Style":["Stile"],"Advanced":["Avanzato"],"No tags available":["Nessun tag disponibile"],"Device":["Dispositivo"],"Select Shortcodes":["Seleziona i codici brevi"],"Page Break Label":["Etichetta di interruzione di pagina"],"Next":["Avanti"],"Back":["Indietro"],"Reset":["Reimposta"],"Generic tags":["Tag generici"],"Pixel":["Pixel"],"Em":["Em"],"Select Units":["Seleziona unit\u00e0"],"%s units":["%s unit\u00e0"],"Margin":["Margine"],"Attributes":["Attributi"],"Input Pattern":["Schema di input"],"None":["Nessuno"],"(###) ###-####":["(###) ###-####"],"(##) ####-####":["(##) ####-####"],"27\/08\/2024":["27\/08\/2024"],"23:59:59":["23:59:59"],"27\/08\/2024 23:59:59":["27\/08\/2024 23:59:59"],"Custom":["Personalizzato"],"Custom Mask":["Maschera personalizzata"],"Please check the documentation to manage custom input pattern ":["Si prega di controllare la documentazione per gestire il modello di input personalizzato"],"here":["qui"],"Default Value":["Valore predefinito"],"Error Message":["Messaggio di errore"],"Help Text":["Testo di aiuto"],"Number Format":["Formato numero"],"US Style (Eg: 9,999.99)":["Stile USA (Es: 9.999,99)"],"EU Style (Eg: 9.999,99)":["Stile UE (Es: 9.999,99)"],"Minimum Value":["Valore minimo"],"Maximum Value":["Valore massimo"],"Please check the Minimum and Maximum value":["Si prega di controllare il valore minimo e massimo"],"Enable Email Confirmation":["Abilita la conferma email"],"Checked by Default":["Selezionato per impostazione predefinita"],"Error message":["Messaggio di errore"],"Checked by default":["Selezionato per impostazione predefinita"],"Please add a option props to MultiButtonsControl":["Si prega di aggiungere un'opzione props a MultiButtonsControl"],"Icon Library":["Libreria di icone"],"Close":["Chiudi"],"All Icons":["Tutte le icone"],"Other":["Altro"],"No Icons Found":["Nessuna icona trovata"],"Insert Icon":["Inserisci icona"],"Change Icon":["Cambia icona"],"Choose Icon":["Scegli icona"],"Confirm":["Conferma"],"Cancel":["Annulla"],"Processing\u2026":["Elaborazione\u2026"],"Select Video":["Seleziona video"],"Change Video":["Cambia video"],"Select Lottie Animation":["Seleziona animazione Lottie"],"Change Lottie Animation":["Cambia animazione Lottie"],"Upload SVG":["Carica SVG"],"Change SVG":["Cambia SVG"],"Select Image":["Seleziona immagine"],"Change Image":["Cambia immagine"],"Upload SVG?":["Caricare SVG?"],"Upload SVG can be potentially risky. Are you sure?":["Caricare SVG pu\u00f2 essere potenzialmente rischioso. Sei sicuro?"],"Upload Anyway":["Carica comunque"],"Bulk Add":["Aggiunta in blocco"],"Bulk Add Options":["Aggiungi opzioni in blocco"],"Enter each option on a new line.":["Inserisci ogni opzione su una nuova riga."],"Insert Options":["Inserisci opzioni"],"Full Width":["Larghezza completa"],"Option Type":["Tipo di opzione"],"Edit Options":["Opzioni di modifica"],"Add New Option":["Aggiungi nuova opzione"],"ADD":["AGGIUNGI"],"Enable Auto Country Detection":["Abilita il rilevamento automatico del paese"],"%s Width":["Larghezza %s"],"Upgrade":["Aggiornamento"],"Clear":["Chiaro"],"Select Color":["Seleziona colore"],"Primary Color":["Colore primario"],"Text Color":["Colore del testo"],"Field Spacing":["Spaziatura del campo"],"Small":["Piccolo"],"Large":["Grande"],"Left":["Sinistra"],"Center":["Centro"],"Right":["Destra"],"Color":["Colore"],"Background Color":["Colore di sfondo"],"Auto":["Auto"],"Default":["Predefinito"],"Normal":["Normale"],"%":["%"],"Top":["In alto"],"Bottom":["Fondo"],"Width":["Larghezza"],"Size":["Dimensione"],"EM":["EM"],"Padding":["Riempimento"],"Color 1":["Colore 1"],"Color 2":["Colore 2"],"Type":["Tipo"],"Linear":["Lineare"],"Radial":["Radiale"],"Location 1":["Posizione 1"],"Location 2":["Posizione 2"],"Angle":["Angolo"],"Classic":["Classico"],"Gradient":["Gradiente"],"Horizontal":["Orizzontale"],"Vertical":["Verticale"],"Background":["Sfondo"],"Cover":["Copertina"],"Contain":["Contenere"],"Layout":["Layout"],"Overlay":["Sovrapposizione"],"No Repeat":["Nessuna ripetizione"],"Overlay Opacity":["Opacit\u00e0 dell'overlay"],"Conditional Logic":["Logica Condizionale"],"Upgrade to the SureForms Starter Plan to create dynamic forms that adapt based on user input, offering a personalised and efficient form experience.":["Passa al piano Starter di SureForms per creare moduli dinamici che si adattano in base all'input dell'utente, offrendo un'esperienza modulare personalizzata ed efficiente."],"Enable Conditional Logic":["Abilita la logica condizionale"],"this field if":["questo campo se"],"Configure Conditions":["Configura condizioni"],"Premium":["Premium"],"Overlay Type":["Tipo di sovrapposizione"],"Image Overlay Color":["Colore di sovrapposizione dell'immagine"],"Image Position":["Posizione dell'immagine"],"Attachment":["Allegato"],"Fixed":["Fisso"],"Blend Mode":["Modalit\u00e0 di fusione"],"Multiply":["Moltiplica"],"Screen":["Schermo"],"Darken":["Scurisci"],"Lighten":["Alleggerire"],"Color Dodge":["Schiarisci colore"],"Saturation":["Saturazione"],"Repeat-x":["Ripeti-x"],"Repeat-y":["Ripeti-y"],"PX":["PX"],"Button":["Pulsante"],"Prefix Label":["Etichetta prefisso"],"Suffix Label":["Etichetta suffisso"],"Border Radius":["Raggio del bordo"],"Form Theme":["Tema del modulo"],"Select Gradient":["Seleziona sfumatura"],"Unlock Conditional Logic Editor":["Sblocca l'editor di logica condizionale"],"Rich Text Editor":["Editor di testo ricco"],"Read Only":["Solo lettura"],"Select Country":["Seleziona Paese"],"Default Country":["Paese predefinito"],"Subscription":["Abbonamento"],"One Time":["Una volta"],"Unique Entry":["Ingresso Unico"],"Maximum Characters":["Caratteri massimi"],"Textarea Height":["Altezza dell'area di testo"],"Minimum Selections":["Selezioni Minime"],"Maximum Selections":["Selezioni massime"],"Add Numeric Values to Options":["Aggiungi valori numerici alle opzioni"],"Single Choice Only":["Solo una scelta"],"Enable Dropdown Search":["Abilita la ricerca a discesa"],"Allow Multiple":["Consenti multipli"],"%1$s fields are required. Please configure these fields in the block settings.":["I campi %1$s sono obbligatori. Si prega di configurare questi campi nelle impostazioni del blocco."],"%1$s field is required. Please configure this field in the block settings.":["Il campo %1$s \u00e8 obbligatorio. Si prega di configurare questo campo nelle impostazioni del blocco."],"You need to configure a payment account to collect payments from this form. Please configure your payment provider to proceed.":["\u00c8 necessario configurare un account di pagamento per raccogliere i pagamenti da questo modulo. Si prega di configurare il proprio fornitore di pagamento per procedere."],"Configure Payment Account":["Configura l'account di pagamento"],"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.":["Questo \u00e8 un segnaposto per il blocco di pagamento. I campi di pagamento effettivi per il\/i fornitore\/i di pagamento configurato\/i appariranno solo quando visualizzi in anteprima o pubblichi il modulo."],"2 Payments":["2 Pagamenti"],"3 Payments":["3 Pagamenti"],"4 Payments":["4 Pagamenti"],"5 Payments":["5 Pagamenti"],"Never":["Mai"],"Stop Subscription After":["Interrompi l'abbonamento dopo"],"Choose when to automatically stop the subscription":["Scegli quando interrompere automaticamente l'abbonamento"],"Number of Payments":["Numero di pagamenti"],"Enter a number between 1 to 100":["Inserisci un numero tra 1 e 100"],"Form Field":["Campo del modulo"],"Payment Type":["Tipo di pagamento"],"Subscription Plan Name":["Nome del piano di abbonamento"],"Billing Interval":["Intervallo di fatturazione"],"Daily":["Quotidiano"],"Weekly":["Settimanale"],"Monthly":["Mensile"],"Quarterly":["Trimestrale"],"Yearly":["Annuale"],"Amount Type":["Tipo di importo"],"Fixed Amount":["Importo fisso"],"Dynamic Amount":["Importo Dinamico"],"Choose whether to charge a fixed amount or charge the amount based on user input in other form fields.":["Scegli se addebitare un importo fisso o addebitare l'importo in base all'input dell'utente in altri campi del modulo."],"Set the exact amount you want to charge. Users won\u2019t be able to change it":["Imposta l'importo esatto che desideri addebitare. Gli utenti non potranno modificarlo"],"Choose Amount Field":["Scegli il campo Importo"],"Select a field\u2026":["Seleziona un campo\u2026"],"Minimum Amount":["Importo minimo"],"Set the minimum amount users can enter (0 for no minimum)":["Imposta l'importo minimo che gli utenti possono inserire (0 per nessun minimo)"],"Customer Name Field (Required)":["Campo Nome Cliente (Obbligatorio)"],"Customer Name Field (Optional)":["Campo Nome Cliente (Facoltativo)"],"Select the input field that contains the customer name (Required for subscriptions)":["Seleziona il campo di input che contiene il nome del cliente (Richiesto per gli abbonamenti)"],"Select the input field that contains the customer name":["Seleziona il campo di input che contiene il nome del cliente"],"Customer Email Field (Required)":["Campo Email Cliente (Obbligatorio)"],"Select the email field that contains the customer email":["Seleziona il campo email che contiene l'email del cliente"],"Payment":["Pagamento"],"%s - Order ID":["%s - ID Ordine"],"%s - Amount":["%s - Importo"],"%s - Customer Email":["%s - Email del cliente"],"%s - Customer Name":["%s - Nome del cliente"],"%s - Status":["%s - Stato"],"Button Alignment":["Allineamento del pulsante"],"Placeholder":["Segnaposto"],"Preselect this option":["Preseleziona questa opzione"],"Restrict Country Codes":["Limita i codici paese"],"Restriction Type":["Tipo di restrizione"],"Allow":["Permetti"],"Block":["Blocca"],"Select Allowed Countries":["Seleziona i Paesi consentiti"],"Choose countries\u2026":["Scegli i paesi\u2026"],"Choose which country codes users can select in the phone number field. Leave empty to allow all country codes.":["Scegli quali codici paese gli utenti possono selezionare nel campo del numero di telefono. Lascia vuoto per consentire tutti i codici paese."],"Select Blocked Countries":["Seleziona Paesi Bloccati"],"These countries will be hidden from the dropdown.":["Questi paesi saranno nascosti dal menu a tendina."],"Bulk Edit":["Modifica in blocco"],"Select Layout":["Seleziona layout"],"Number of Columns":["Numero di colonne"],"Validation Message for Duplicate":["Messaggio di convalida per duplicato"],"Click here to insert a form":["Fai clic qui per inserire un modulo"],"Inherit Form's Original Style":["Eredita lo stile originale del modulo"],"Text on Primary":["Testo su Primario"],"%s - Description":["%s - Descrizione"],"Upgrade to Unlock":["Aggiorna per sbloccare"],"Custom (Premium)":["Personalizzato (Premium)"],"Select a theme style for this form embed.":["Seleziona uno stile tema per questo modulo incorporato."],"Colors":["Colori"],"Advanced Styling":["Stile avanzato"],"Unlock Custom Styling":["Sblocca lo stile personalizzato"],"Switch to Custom Mode to take full control of your form's design and spacing.":["Passa alla Modalit\u00e0 Personalizzata per avere il pieno controllo del design e della spaziatura del tuo modulo."],"Full color control (buttons, fields, text)":["Controllo completo del colore (bottoni, campi, testo)"],"Row and column gap control":["Controllo dello spazio tra righe e colonne"],"Field spacing and layout precision":["Spaziatura dei campi e precisione del layout"],"Complete button styling":["Completare lo stile del pulsante"],"Payment Description":["Descrizione del pagamento"],"Shown on payment receipts and in your payment dashboard (Stripe and PayPal). Leave blank to use the default.":["Mostrato sulle ricevute di pagamento e nel tuo cruscotto dei pagamenti (Stripe e PayPal). Lascia vuoto per utilizzare il predefinito."],"Slug":["Lumaca"],"Auto-generated on save":["Generato automaticamente al salvataggio"],"This slug is already used by another field. It will revert to the previous value.":["Questo slug \u00e8 gi\u00e0 utilizzato da un altro campo. Torner\u00e0 al valore precedente."],"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.":["La modifica dello slug potrebbe interrompere l'invio dei moduli, la logica condizionale, le integrazioni o qualsiasi altra funzione che attualmente fa riferimento a questo slug. Dovrai aggiornare manualmente tutti questi riferimenti."],"Field Slug":["Slug del campo"],"Location Services":["Servizi di localizzazione"],"Unlock Address Autocomplete":["Sblocca il completamento automatico degli indirizzi"],"Upgrade to enable Google Address Autocomplete with interactive map preview, making address entry faster and more accurate for your users.":["Aggiorna per abilitare il completamento automatico degli indirizzi di Google con l'anteprima interattiva della mappa, rendendo l'inserimento degli indirizzi pi\u00f9 veloce e preciso per i tuoi utenti."],"Enable Google Autocomplete":["Abilita il completamento automatico di Google"],"Show Interactive Map":["Mostra mappa interattiva"],"Payments Per Page":["Pagamenti per pagina"],"Show Subscriptions Section":["Mostra la sezione Abbonamenti"],"Show a dedicated subscriptions section above payment history.":["Mostra una sezione dedicata agli abbonamenti sopra la cronologia dei pagamenti."],"Payment Dashboard":["Dashboard dei pagamenti"],"View your payments and manage subscriptions in a single dashboard.":["Visualizza i tuoi pagamenti e gestisci gli abbonamenti in un'unica dashboard."],"Dynamic Default Value":["Valore predefinito dinamico"],"Minimum Characters":["Caratteri Minimi"],"Minimum characters cannot exceed Maximum characters.":["I caratteri minimi non possono superare i caratteri massimi."],"Both":["Entrambi"],"One-Time Label":["Etichetta monouso"],"Label shown to users for the one-time payment option.":["Etichetta mostrata agli utenti per l'opzione di pagamento una tantum."],"Subscription Label":["Etichetta di abbonamento"],"Label shown to users for the subscription option.":["Etichetta mostrata agli utenti per l'opzione di abbonamento."],"Default Selection":["Selezione predefinita"],"Which option is pre-selected when the form loads.":["Quale opzione \u00e8 preselezionata quando il modulo viene caricato."],"One-Time Amount Type":["Tipo di importo una tantum"],"Set how the one-time payment amount is determined.":["Imposta come viene determinato l'importo del pagamento una tantum."],"One-Time Fixed Amount":["Importo fisso una tantum"],"Amount charged for a one-time payment.":["Importo addebitato per un pagamento una tantum."],"One-Time Amount Field":["Campo Importo Una Tantum"],"Pick a form field whose value determines the one-time payment amount.":["Scegli un campo del modulo il cui valore determina l'importo del pagamento una tantum."],"One-Time Minimum Amount":["Importo minimo una tantum"],"Minimum amount users can enter for one-time payment (0 for no minimum).":["Importo minimo che gli utenti possono inserire per un pagamento una tantum (0 per nessun minimo)."],"Subscription Amount Type":["Tipo di importo dell'abbonamento"],"Set how the subscription amount is determined.":["Imposta come viene determinato l'importo dell'abbonamento."],"Subscription Fixed Amount":["Importo fisso dell'abbonamento"],"Recurring amount charged per billing interval.":["Importo ricorrente addebitato per intervallo di fatturazione."],"Subscription Amount Field":["Campo Importo Abbonamento"],"Pick a form field whose value determines the subscription amount.":["Scegli un campo del modulo il cui valore determina l'importo dell'abbonamento."],"Subscription Minimum Amount":["Importo minimo di sottoscrizione"],"Minimum amount users can enter for subscription (0 for no minimum).":["Importo minimo che gli utenti possono inserire per l'abbonamento (0 per nessun minimo)."],"Pick a field from your form like a number, dropdown, multichoice, or hidden whose value should decide the payment amount.":["Scegli un campo dal tuo modulo come un numero, un menu a tendina, una scelta multipla o nascosto il cui valore dovrebbe determinare l'importo del pagamento."]}}} \ No newline at end of file diff --git a/languages/sureforms-it_IT.mo b/languages/sureforms-it_IT.mo index f20702528..a0b7e69f1 100644 Binary files a/languages/sureforms-it_IT.mo and b/languages/sureforms-it_IT.mo differ diff --git a/languages/sureforms-it_IT.po b/languages/sureforms-it_IT.po index 4dbff1017..7d485082a 100644 --- a/languages/sureforms-it_IT.po +++ b/languages/sureforms-it_IT.po @@ -106,13 +106,13 @@ msgstr "Modifica %1$s" #: inc/ai-form-builder/ai-auth.php:93 #: inc/ai-form-builder/ai-auth.php:167 #: inc/background-process.php:112 -#: inc/create-new-form.php:101 +#: inc/create-new-form.php:102 #: inc/duplicate-form.php:176 #: inc/export.php:118 #: inc/export.php:176 #: inc/forms-data.php:88 #: inc/global-settings/global-settings.php:86 -#: inc/global-settings/global-settings.php:403 +#: inc/global-settings/global-settings.php:404 #: inc/rest-api.php:177 msgid "Nonce verification failed." msgstr "Verifica del nonce fallita." @@ -388,7 +388,7 @@ msgid "Selected radio option" msgstr "Opzione radio selezionata" #: inc/admin-ajax.php:341 -#: inc/create-new-form.php:63 +#: inc/create-new-form.php:64 #: assets/build/blocks.js:172 #: assets/build/formEditor.js:172 msgid "Submit" @@ -427,53 +427,53 @@ msgid "The message array was not supplied" msgstr "L'array di messaggi non è stato fornito" #: inc/ai-form-builder/ai-form-builder.php:68 -#: inc/ai-form-builder/ai-form-builder.php:78 -#: inc/ai-form-builder/ai-helper.php:73 +#: inc/ai-form-builder/ai-form-builder.php:87 +#: inc/ai-form-builder/ai-helper.php:294 msgid "The SureForms AI Middleware encountered an error." msgstr "Il middleware AI di SureForms ha riscontrato un errore." -#: inc/ai-form-builder/ai-helper.php:95 +#: inc/ai-form-builder/ai-helper.php:91 msgid "Unable to get usage response." msgstr "Impossibile ottenere una risposta sull'uso." -#: inc/ai-form-builder/ai-helper.php:148 +#: inc/ai-form-builder/ai-helper.php:145 msgid "The SureForms API server encountered an error." msgstr "Il server API di SureForms ha riscontrato un errore." -#: inc/ai-form-builder/ai-helper.php:174 -#: inc/ai-form-builder/ai-helper.php:206 +#: inc/ai-form-builder/ai-helper.php:167 +#: inc/ai-form-builder/ai-helper.php:199 msgid "An unknown error occurred." msgstr "Si è verificato un errore sconosciuto." -#: inc/ai-form-builder/ai-helper.php:181 +#: inc/ai-form-builder/ai-helper.php:174 msgid "HTTP Request Failed" msgstr "Richiesta HTTP fallita" -#: inc/ai-form-builder/ai-helper.php:185 +#: inc/ai-form-builder/ai-helper.php:178 msgid "License Verification Failed" msgstr "Verifica della licenza fallita" -#: inc/ai-form-builder/ai-helper.php:189 +#: inc/ai-form-builder/ai-helper.php:182 msgid "User Verification Failed" msgstr "Verifica utente fallita" -#: inc/ai-form-builder/ai-helper.php:193 +#: inc/ai-form-builder/ai-helper.php:186 msgid "Referer Mismatch" msgstr "Discrepanza del Referer" -#: inc/ai-form-builder/ai-helper.php:197 +#: inc/ai-form-builder/ai-helper.php:190 msgid "Invalid Website URL" msgstr "URL del sito web non valido" -#: inc/ai-form-builder/ai-helper.php:198 +#: inc/ai-form-builder/ai-helper.php:191 msgid "AI Form Builder does not work on localhost. Please try on a live website." msgstr "Il generatore di moduli AI non funziona su localhost. Si prega di provare su un sito web live." -#: inc/ai-form-builder/ai-helper.php:201 +#: inc/ai-form-builder/ai-helper.php:194 msgid "Domain Verification Failed" msgstr "Verifica del dominio fallita" -#: inc/ai-form-builder/ai-helper.php:205 +#: inc/ai-form-builder/ai-helper.php:198 msgid "Unknown Error" msgstr "Errore sconosciuto" @@ -481,22 +481,18 @@ msgstr "Errore sconosciuto" msgid "Submission id missing." msgstr "ID di invio mancante." -#: inc/create-new-form.php:113 +#: inc/create-new-form.php:114 msgid "Invalid JSON format." msgstr "Formato JSON non valido." -#: inc/create-new-form.php:125 +#: inc/create-new-form.php:126 msgid "Missing required properties in form info." msgstr "Mancano le proprietà richieste nelle informazioni del modulo." -#: inc/create-new-form.php:161 +#: inc/create-new-form.php:187 msgid "SureForms Form created successfully." msgstr "Modulo SureForms creato con successo." -#: inc/create-new-form.php:168 -msgid "Error creating SureForms Form, " -msgstr "Errore nella creazione del modulo SureForms," - #: inc/email/email-template.php:46 msgid "New form submission" msgstr "Nuova invio del modulo" @@ -558,7 +554,7 @@ msgstr "Numero" msgid "Phone" msgstr "Telefono" -#: inc/fields/textarea-markup.php:95 +#: inc/fields/textarea-markup.php:111 msgid "Textarea" msgstr "Area di testo" @@ -601,8 +597,8 @@ msgstr "Nessun modulo trovato." #: inc/abilities/settings/get-global-settings.php:192 #: inc/global-settings/email-summary.php:571 -#: inc/global-settings/global-settings.php:250 -#: inc/global-settings/global-settings.php:456 +#: inc/global-settings/global-settings.php:251 +#: inc/global-settings/global-settings.php:457 #: assets/build/settings.js:172 msgid "Monday" msgstr "Lunedì" @@ -7009,7 +7005,7 @@ msgstr "Vista Stradale" msgid "Strikethrough" msgstr "Barrato" -#: inc/fields/payment-markup.php:412 +#: inc/fields/payment-markup.php:513 #: modules/gutenberg/icons/icons-v6-3.php:1812 #: assets/build/payments.js:172 msgid "Stripe" @@ -11593,6 +11589,7 @@ msgstr "Crea il tuo primo modulo" msgid "Invalid nonce action or name." msgstr "Azione o nome del nonce non valido." +#: inc/admin/editor-nudge.php:216 #: inc/helper.php:2029 #: inc/helper.php:2037 msgid "Invalid security token." @@ -11776,7 +11773,7 @@ msgstr "Esplora SureDash" msgid "Something went wrong. We have logged the error for further investigation" msgstr "Qualcosa è andato storto. Abbiamo registrato l'errore per ulteriori indagini." -#: inc/field-validation.php:273 +#: inc/field-validation.php:276 msgid "Field is not valid." msgstr "Il campo non è valido." @@ -11934,82 +11931,82 @@ msgstr "Nessun dato dei moduli fornito per l'importazione." msgid "Invalid form data structure provided." msgstr "Struttura dei dati del modulo non valida fornita." -#: inc/fields/payment-markup.php:249 +#: inc/fields/payment-markup.php:346 #: inc/payments/payment-helper.php:543 msgid "Subscription Plan" msgstr "Piano di abbonamento" #. translators: 1: Amount with currency, 2: Interval (day/week/month/quarter/year) -#: inc/fields/payment-markup.php:288 +#: inc/fields/payment-markup.php:672 #, php-format msgid "%1$s per %2$s (until cancelled)" msgstr "%1$s per %2$s (fino a cancellazione)" #. translators: 1: Amount with currency, 2: Interval (day/week/month/quarter/year), 3: Number of billing cycles -#: inc/fields/payment-markup.php:297 +#: inc/fields/payment-markup.php:681 #, php-format msgid "%1$s per %2$s (%3$s payments)" msgstr "%1$s per %2$s (%3$s pagamenti)" #. translators: 1: Amount with currency, 2: Interval (day/week/month/quarter/year) -#: inc/fields/payment-markup.php:307 +#: inc/fields/payment-markup.php:691 #, php-format msgid "%1$s per %2$s" msgstr "%1$s per %2$s" #. translators: 1: Amount with currency placeholder, 2: Interval (day/week/month/quarter/year) -#: inc/fields/payment-markup.php:334 +#: inc/fields/payment-markup.php:714 #, php-format msgid "{amount} per %s (until cancelled)" msgstr "{amount} per %s (fino a cancellazione)" #. translators: 1: Amount with currency placeholder, 2: Interval (day/week/month/quarter/year), 3: Number of billing cycles -#: inc/fields/payment-markup.php:337 +#: inc/fields/payment-markup.php:717 #, php-format msgid "{amount} per %1$s (%2$s payments)" msgstr "{amount} per %1$s (%2$s pagamenti)" #. translators: 1: Amount with currency placeholder, 2: Interval (day/week/month/quarter/year) -#: inc/fields/payment-markup.php:340 +#: inc/fields/payment-markup.php:720 #, php-format msgid "{amount} per %s" msgstr "{amount} per %s" #. translators: %s: Minimum amount with currency -#: inc/fields/payment-markup.php:353 +#: inc/fields/payment-markup.php:740 #, php-format msgid "Minimum amount: %s" msgstr "Importo minimo: %s" -#: inc/fields/payment-markup.php:385 +#: inc/fields/payment-markup.php:486 msgid "Processing payment..." msgstr "Elaborazione del pagamento..." -#: inc/fields/payment-markup.php:579 +#: inc/fields/payment-markup.php:906 msgid "day" msgstr "giorno" -#: inc/fields/payment-markup.php:580 +#: inc/fields/payment-markup.php:907 msgid "week" msgstr "settimana" -#: inc/fields/payment-markup.php:581 +#: inc/fields/payment-markup.php:908 msgid "month" msgstr "mese" -#: inc/fields/payment-markup.php:582 +#: inc/fields/payment-markup.php:909 msgid "quarter" msgstr "trimestre" -#: inc/fields/payment-markup.php:583 +#: inc/fields/payment-markup.php:910 msgid "year" msgstr "anno" -#: inc/fields/payment-markup.php:608 +#: inc/fields/payment-markup.php:935 msgid "Test mode is enabled:" msgstr "La modalità di test è attivata:" -#: inc/fields/payment-markup.php:610 +#: inc/fields/payment-markup.php:937 msgid "Click here to enable live mode and accept payment" msgstr "Fai clic qui per abilitare la modalità live e accettare il pagamento" @@ -12192,6 +12189,7 @@ msgstr "Modulo sconosciuto" msgid "N/A" msgstr "N/D" +#: inc/fields/payment-markup.php:247 #: inc/payments/admin/admin-handler.php:975 #: inc/payments/payment-history-shortcode.php:306 #: assets/build/blocks.js:172 @@ -12220,21 +12218,21 @@ msgstr "Sconosciuto" #: inc/payments/admin/admin-handler.php:1468 #: inc/payments/admin/admin-handler.php:1472 #: inc/payments/admin/admin-handler.php:1476 -#: inc/payments/front-end.php:811 -#: inc/payments/front-end.php:1209 +#: inc/payments/front-end.php:854 +#: inc/payments/front-end.php:1253 msgid "Guest User" msgstr "Utente Ospite" -#: inc/payments/front-end.php:91 +#: inc/payments/front-end.php:92 msgid "Invalid payment amount." msgstr "Importo del pagamento non valido." -#: inc/payments/front-end.php:107 +#: inc/payments/front-end.php:109 msgid "Valid customer email is required for payments." msgstr "È richiesta un'email cliente valida per i pagamenti." -#: inc/payments/front-end.php:113 -#: inc/payments/front-end.php:320 +#: inc/payments/front-end.php:115 +#: inc/payments/front-end.php:340 #: inc/payments/stripe/admin-stripe-handler.php:877 #: inc/payments/stripe/payments-settings.php:349 #: inc/payments/stripe/payments-settings.php:474 @@ -12244,137 +12242,137 @@ msgstr "È richiesta un'email cliente valida per i pagamenti." msgid "Stripe is not connected." msgstr "Stripe non è connesso." -#: inc/payments/front-end.php:119 -#: inc/payments/front-end.php:326 -#: inc/payments/front-end.php:610 -#: inc/payments/front-end.php:1099 +#: inc/payments/front-end.php:121 +#: inc/payments/front-end.php:346 +#: inc/payments/front-end.php:634 +#: inc/payments/front-end.php:1142 msgid "Stripe secret key not found." msgstr "Chiave segreta di Stripe non trovata." #. translators: %s: formatted payment amount -#: inc/payments/front-end.php:201 +#: inc/payments/front-end.php:203 #, php-format msgid "The payment amount (%s) is below the minimum allowed. Stripe only processes amounts above 50¢." msgstr "L'importo del pagamento (%s) è inferiore al minimo consentito. Stripe elabora solo importi superiori a 50¢." #. translators: %s: Field name -#: inc/payments/front-end.php:268 +#: inc/payments/front-end.php:273 #, php-format msgid "Missing required field: %s" msgstr "Manca il campo richiesto: %s" -#: inc/payments/front-end.php:287 +#: inc/payments/front-end.php:292 msgid "Valid customer email is required for subscriptions." msgstr "È richiesta un'email valida del cliente per gli abbonamenti." -#: inc/payments/front-end.php:292 +#: inc/payments/front-end.php:297 msgid "Customer name is required for subscriptions." msgstr "Il nome del cliente è richiesto per gli abbonamenti." -#: inc/payments/front-end.php:308 +#: inc/payments/front-end.php:314 msgid "Amount must be greater than 0" msgstr "L'importo deve essere maggiore di 0" -#: inc/payments/front-end.php:314 +#: inc/payments/front-end.php:322 msgid "Invalid billing interval" msgstr "Intervallo di fatturazione non valido" -#: inc/payments/front-end.php:337 +#: inc/payments/front-end.php:357 msgid "Failed to create customer for subscription." msgstr "Impossibile creare il cliente per l'abbonamento." -#: inc/payments/front-end.php:370 -#: inc/payments/front-end.php:386 +#: inc/payments/front-end.php:390 +#: inc/payments/front-end.php:406 msgid "Failed to create subscription through middleware." msgstr "Impossibile creare l'abbonamento tramite middleware." -#: inc/payments/front-end.php:391 +#: inc/payments/front-end.php:411 msgid "Empty response from subscription creation." msgstr "Risposta vuota dalla creazione dell'abbonamento." -#: inc/payments/front-end.php:396 +#: inc/payments/front-end.php:416 msgid "Invalid JSON response from subscription creation." msgstr "Risposta JSON non valida dalla creazione dell'abbonamento." -#: inc/payments/front-end.php:400 -#: inc/payments/front-end.php:404 +#: inc/payments/front-end.php:420 +#: inc/payments/front-end.php:424 msgid "Invalid subscription data." msgstr "Dati di abbonamento non validi." -#: inc/payments/front-end.php:411 +#: inc/payments/front-end.php:431 msgid "Failed to create subscription." msgstr "Creazione dell'abbonamento non riuscita." #. translators: %s: Error message -#: inc/payments/front-end.php:441 +#: inc/payments/front-end.php:464 #, php-format msgid "Unexpected error: %s" msgstr "Errore imprevisto: %s" -#: inc/payments/front-end.php:581 +#: inc/payments/front-end.php:604 #: inc/payments/stripe/admin-stripe-handler.php:103 #: inc/payments/stripe/admin-stripe-handler.php:184 #: inc/payments/stripe/admin-stripe-handler.php:489 msgid "Subscription ID not found." msgstr "ID di abbonamento non trovato." -#: inc/payments/front-end.php:599 +#: inc/payments/front-end.php:623 msgid "Customer ID not found for the payment." msgstr "ID cliente non trovato per il pagamento." -#: inc/payments/front-end.php:627 +#: inc/payments/front-end.php:651 msgid "Failed to retrieve setup intent." msgstr "Impossibile recuperare l'intento di configurazione." -#: inc/payments/front-end.php:656 +#: inc/payments/front-end.php:699 msgid "Failed to update subscription." msgstr "Impossibile aggiornare l'abbonamento." -#: inc/payments/front-end.php:664 +#: inc/payments/front-end.php:707 msgid "Latest invoice not found on subscription." msgstr "Ultima fattura non trovata nell'abbonamento." -#: inc/payments/front-end.php:677 +#: inc/payments/front-end.php:720 msgid "Failed to retrieve invoice." msgstr "Impossibile recuperare la fattura." -#: inc/payments/front-end.php:699 +#: inc/payments/front-end.php:742 msgid "Payment intent not found on invoice." msgstr "Intento di pagamento non trovato sulla fattura." -#: inc/payments/front-end.php:714 +#: inc/payments/front-end.php:757 msgid "Failed to confirm payment." msgstr "Impossibile confermare il pagamento." -#: inc/payments/front-end.php:730 +#: inc/payments/front-end.php:773 msgid "Failed to retrieve subscription." msgstr "Impossibile recuperare l'abbonamento." -#: inc/payments/front-end.php:745 +#: inc/payments/front-end.php:788 msgid "Subscription not found for the payment." msgstr "Abbonamento non trovato per il pagamento." #. translators: %d: User ID -#: inc/payments/front-end.php:809 -#: inc/payments/front-end.php:1209 +#: inc/payments/front-end.php:852 +#: inc/payments/front-end.php:1253 #, php-format msgid "User ID: %d" msgstr "ID utente: %d" #. translators: %s: Invoice status -#: inc/payments/front-end.php:817 +#: inc/payments/front-end.php:860 #, php-format msgid "Invoice Status: %s" msgstr "Stato della fattura: %s" #. translators: Title for subscription verification log -#: inc/payments/front-end.php:824 +#: inc/payments/front-end.php:867 msgid "Subscription Verification" msgstr "Verifica dell'abbonamento" #. translators: %s: Subscription ID #. translators: %s: Stripe subscription ID -#: inc/payments/front-end.php:828 +#: inc/payments/front-end.php:871 #: inc/payments/stripe/admin-stripe-handler.php:119 #: inc/payments/stripe/admin-stripe-handler.php:204 #: inc/payments/stripe/admin-stripe-handler.php:505 @@ -12390,8 +12388,8 @@ msgstr "ID di abbonamento: %s" #. 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:830 -#: inc/payments/front-end.php:1220 +#: inc/payments/front-end.php:873 +#: inc/payments/front-end.php:1264 #: inc/payments/stripe/admin-stripe-handler.php:124 #: inc/payments/stripe/admin-stripe-handler.php:209 #: inc/payments/stripe/admin-stripe-handler.php:510 @@ -12406,13 +12404,13 @@ msgid "Payment Gateway: %s" msgstr "Gateway di Pagamento: %s" #. translators: %s: Payment Intent ID -#: inc/payments/front-end.php:832 +#: inc/payments/front-end.php:875 #, php-format msgid "Payment Intent ID: %s" msgstr "ID dell'intento di pagamento: %s" #. translators: %s: Charge ID -#: inc/payments/front-end.php:834 +#: inc/payments/front-end.php:877 #: inc/payments/stripe/stripe-webhook.php:1048 #, php-format msgid "Charge ID: %s" @@ -12420,7 +12418,7 @@ msgstr "ID di addebito: %s" #. translators: %s: Subscription Status #. translators: %s: subscription status -#: inc/payments/front-end.php:836 +#: inc/payments/front-end.php:879 #: inc/payments/stripe/admin-stripe-handler.php:129 #: inc/payments/stripe/admin-stripe-handler.php:214 #: inc/payments/stripe/admin-stripe-handler.php:515 @@ -12429,7 +12427,7 @@ msgid "Subscription Status: %s" msgstr "Stato dell'abbonamento: %s" #. translators: %s: Customer ID -#: inc/payments/front-end.php:838 +#: inc/payments/front-end.php:881 #: inc/payments/stripe/stripe-webhook.php:1122 #, php-format msgid "Customer ID: %s" @@ -12437,8 +12435,8 @@ msgstr "ID cliente: %s" #. translators: 1: Amount, 2: Currency #. translators: %1$s: amount, %2$s: currency. -#: inc/payments/front-end.php:840 -#: inc/payments/front-end.php:1222 +#: inc/payments/front-end.php:883 +#: inc/payments/front-end.php:1266 #: inc/payments/stripe/stripe-webhook.php:1053 #: inc/payments/stripe/stripe-webhook.php:1114 #, php-format @@ -12447,34 +12445,34 @@ msgstr "Importo: %1$s %2$s" #. translators: %s: Payment mode (e.g. Live or Test) #. translators: %s: payment mode -#: inc/payments/front-end.php:843 -#: inc/payments/front-end.php:1227 +#: inc/payments/front-end.php:886 +#: inc/payments/front-end.php:1271 #, php-format msgid "Mode: %s" msgstr "Modalità: %s" -#: inc/payments/front-end.php:877 +#: inc/payments/front-end.php:920 msgid "Failed to verify subscription." msgstr "Verifica dell'abbonamento non riuscita." -#: inc/payments/front-end.php:1131 -#: inc/payments/front-end.php:1149 -#: inc/payments/front-end.php:1157 -#: inc/payments/front-end.php:1164 +#: inc/payments/front-end.php:1175 +#: inc/payments/front-end.php:1193 +#: inc/payments/front-end.php:1201 +#: inc/payments/front-end.php:1208 msgid "Failed to retrieve payment intent." msgstr "Impossibile recuperare l'intento di pagamento." -#: inc/payments/front-end.php:1172 +#: inc/payments/front-end.php:1216 msgid "Payment was not confirmed successfully." msgstr "Il pagamento non è stato confermato con successo." -#: inc/payments/front-end.php:1214 +#: inc/payments/front-end.php:1258 msgid "Payment Verification" msgstr "Verifica del pagamento" #. translators: %s: Stripe transaction ID #. translators: %s: Charge ID -#: inc/payments/front-end.php:1218 +#: inc/payments/front-end.php:1262 #: inc/payments/stripe/stripe-webhook.php:1110 #, php-format msgid "Transaction ID: %s" @@ -12482,18 +12480,18 @@ msgstr "ID transazione: %s" #. translators: %s: payment status #. translators: %s: Status -#: inc/payments/front-end.php:1224 +#: inc/payments/front-end.php:1268 #: inc/payments/stripe/stripe-webhook.php:576 #: inc/payments/stripe/stripe-webhook.php:1116 #, php-format msgid "Status: %s" msgstr "Stato: %s" -#: inc/payments/front-end.php:1330 +#: inc/payments/front-end.php:1374 msgid "Failed to create Stripe customer." msgstr "Creazione del cliente Stripe non riuscita." -#: inc/payments/front-end.php:1394 +#: inc/payments/front-end.php:1438 msgid "Failed to create Stripe guest customer." msgstr "Impossibile creare un cliente ospite di Stripe." @@ -12856,6 +12854,7 @@ msgstr "Errore sconosciuto" msgid "Missing payment ID." msgstr "ID di pagamento mancante." +#: inc/admin/editor-nudge.php:209 #: inc/payments/stripe/admin-stripe-handler.php:84 #: inc/payments/stripe/admin-stripe-handler.php:470 msgid "You are not allowed to perform this action." @@ -13535,10 +13534,6 @@ msgstr "Scegli il campo Importo" msgid "Select a field…" msgstr "Seleziona un campo…" -#: assets/build/blocks.js:172 -msgid "Pick a field from your form like a number, dropdown, or multichoice whose value should decide the payment amount." -msgstr "Scegli un campo dal tuo modulo, come un numero, un menu a tendina o una scelta multipla, il cui valore dovrebbe determinare l'importo del pagamento." - #: assets/build/blocks.js:172 msgid "Minimum Amount" msgstr "Importo minimo" @@ -14118,6 +14113,7 @@ msgstr "Usa l'IA per generare moduli istantaneamente da un semplice prompt." msgid "Build engaging conversational, calculation, and multi-step forms." msgstr "Crea moduli conversazionali, di calcolo e multi-step coinvolgenti." +#: inc/admin/editor-nudge.php:192 #: assets/build/forms.js:172 msgid "Create Form" msgstr "Crea modulo" @@ -14976,76 +14972,78 @@ msgstr "Il post specificato non è un modulo SureForms." msgid "Failed to create duplicate form." msgstr "Impossibile creare un modulo duplicato." -#: inc/payments/front-end.php:97 -#: inc/payments/front-end.php:298 -#: inc/payments/payment-helper.php:594 +#: inc/payments/front-end.php:98 +#: inc/payments/front-end.php:303 +#: inc/payments/payment-helper.php:595 msgid "Invalid form configuration." msgstr "Configurazione del modulo non valida." -#: inc/payments/payment-helper.php:602 +#: inc/payments/payment-helper.php:603 msgid "Payment configuration not found for this form." msgstr "Configurazione di pagamento non trovata per questo modulo." #. translators: 1: expected currency, 2: received currency -#: inc/payments/payment-helper.php:613 +#: inc/payments/payment-helper.php:614 #, php-format msgid "Currency mismatch: expected %1$s, received %2$s." msgstr "Discrepanza di valuta: previsto %1$s, ricevuto %2$s." #. translators: 1: expected amount with currency -#: inc/payments/payment-helper.php:630 +#: inc/payments/payment-helper.php:649 #, php-format msgid "Payment amount must be exactly %1$s." msgstr "L'importo del pagamento deve essere esattamente %1$s." #. translators: 1: minimum amount with currency -#: inc/payments/payment-helper.php:641 +#: inc/payments/payment-helper.php:660 #, php-format msgid "Payment amount must be at least %1$s." msgstr "L'importo del pagamento deve essere almeno %1$s." -#: inc/payments/payment-helper.php:717 +#: inc/payments/payment-helper.php:737 msgid "Invalid payment verification parameters." msgstr "Parametri di verifica del pagamento non validi." -#: inc/payments/payment-helper.php:728 +#: inc/payments/payment-helper.php:748 msgid "Payment verification failed. Invalid payment intent." msgstr "Verifica del pagamento fallita. Intento di pagamento non valido." -#: inc/payments/payment-helper.php:814 -#: inc/payments/payment-helper.php:952 +#: inc/payments/payment-helper.php:903 +#: inc/payments/payment-helper.php:1043 msgid "Variable amount field configuration not found." msgstr "Configurazione del campo dell'importo variabile non trovata." -#: inc/payments/payment-helper.php:835 +#: inc/payments/payment-helper.php:924 msgid "No payment options are configured for this field." msgstr "Nessuna opzione di pagamento è configurata per questo campo." #. translators: %s: currency code -#: inc/payments/payment-helper.php:861 +#: inc/payments/payment-helper.php:950 msgid "Invalid payment amount. Please select a valid amount from the available options." msgstr "Importo di pagamento non valido. Si prega di selezionare un importo valido tra le opzioni disponibili." #. translators: %1$s: expected amount, %2$s: payment amount -#: inc/payments/payment-helper.php:896 +#: inc/payments/payment-helper.php:986 msgid "Payment configuration not found." msgstr "Configurazione del pagamento non trovata." #. translators: %1$s: expected amount, %2$s: payment amount -#: inc/payments/payment-helper.php:912 -#: inc/payments/payment-helper.php:964 -#: inc/payments/payment-helper.php:1000 +#: inc/payments/payment-helper.php:1003 +#: inc/payments/payment-helper.php:1055 +#: inc/payments/payment-helper.php:1091 +#: inc/payments/payment-helper.php:1111 #, php-format msgid "Payment amount mismatch. Expected %1$s, received %2$s." msgstr "Importo del pagamento non corrispondente. Previsto %1$s, ricevuto %2$s." -#: inc/payments/payment-helper.php:941 -#: inc/payments/payment-helper.php:991 +#: 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." msgstr "È richiesto il valore del campo importo variabile." #. translators: %1$s: minimum amount, %2$s: payment amount -#: inc/payments/payment-helper.php:1012 +#: inc/payments/payment-helper.php:1125 #, php-format msgid "Payment amount below minimum. Minimum: %1$s, received %2$s." msgstr "Importo del pagamento inferiore al minimo. Minimo: %1$s, ricevuto %2$s." @@ -15107,7 +15105,7 @@ msgstr "Si è verificato un errore durante la duplicazione del modulo." msgid "This will create a copy of \"%s\" with all its settings." msgstr "Questo creerà una copia di \"%s\" con tutte le sue impostazioni." -#: inc/fields/payment-markup.php:413 +#: inc/fields/payment-markup.php:514 msgid "Pay with credit or debit card" msgstr "Paga con carta di credito o debito" @@ -15115,8 +15113,8 @@ msgstr "Paga con carta di credito o debito" msgid "This form is not yet available. Please check back after the scheduled start time." msgstr "Questo modulo non è ancora disponibile. Si prega di ricontrollare dopo l'orario di inizio programmato." -#: inc/form-restriction.php:165 -#: inc/form-restriction.php:166 +#: inc/form-restriction.php:187 +#: inc/form-restriction.php:188 #: assets/build/formEditor.js:172 msgid "This form is no longer accepting submissions. The submission period has ended." msgstr "Questo modulo non accetta più invii. Il periodo di invio è terminato." @@ -15131,7 +15129,7 @@ msgstr "Gateway di pagamento non trovato." msgid "Refund processing is not supported for %s gateway." msgstr "Il rimborso non è supportato per il gateway %s." -#: inc/payments/payment-helper.php:974 +#: inc/payments/payment-helper.php:1065 msgid "Number field configuration not found." msgstr "Configurazione del campo numerico non trovata." @@ -15508,11 +15506,11 @@ msgstr "Il titolo del modulo è obbligatorio." msgid "At least one form field is required." msgstr "È richiesto almeno un campo del modulo." -#: inc/abilities/forms/create-form.php:322 +#: inc/abilities/forms/create-form.php:326 msgid "Failed to generate form fields from the provided data." msgstr "Impossibile generare i campi del modulo dai dati forniti." -#: inc/abilities/forms/create-form.php:372 +#: inc/abilities/forms/create-form.php:376 msgid "Failed to create the form." msgstr "Creazione del modulo non riuscita." @@ -15688,23 +15686,23 @@ msgstr "Sessione di autenticazione scaduta. Per favore riprova." msgid "Invalid access key format." msgstr "Formato della chiave di accesso non valido." -#: inc/ai-form-builder/ai-helper.php:182 +#: inc/ai-form-builder/ai-helper.php:175 msgid "Unable to connect to SureForms API. Please check your connection." msgstr "Impossibile connettersi all'API di SureForms. Si prega di controllare la connessione." -#: inc/ai-form-builder/ai-helper.php:186 +#: inc/ai-form-builder/ai-helper.php:179 msgid "Unable to verify license. Please check your license key." msgstr "Impossibile verificare la licenza. Si prega di controllare il proprio codice di licenza." -#: inc/ai-form-builder/ai-helper.php:190 +#: inc/ai-form-builder/ai-helper.php:183 msgid "An error occurred while trying to verify your email. Please check your email you have used to log in or sign up on billing.sureforms.com." msgstr "Si è verificato un errore durante il tentativo di verificare la tua email. Controlla l'email che hai utilizzato per accedere o registrarti su billing.sureforms.com." -#: inc/ai-form-builder/ai-helper.php:194 +#: inc/ai-form-builder/ai-helper.php:187 msgid "Unable to verify referer. Please check your referer." msgstr "Impossibile verificare il referer. Si prega di controllare il proprio referer." -#: inc/ai-form-builder/ai-helper.php:202 +#: inc/ai-form-builder/ai-helper.php:195 msgid "Domain Verification Failed on current site. Please try again on another website." msgstr "Verifica del dominio fallita sul sito attuale. Si prega di riprovare su un altro sito web." @@ -15730,8 +15728,8 @@ msgstr "Acconsento a che questo sito web memorizzi le mie informazioni in modo c msgid "Text field" msgstr "Campo di testo" -#: inc/form-restriction.php:160 -#: inc/form-restriction.php:161 +#: inc/form-restriction.php:182 +#: inc/form-restriction.php:183 #: inc/post-types.php:1203 #: inc/post-types.php:1243 msgid "This form is not yet available. Check back after the scheduled start time." @@ -15741,8 +15739,8 @@ msgstr "Questo modulo non è ancora disponibile. Ricontrolla dopo l'orario di in #: inc/form-submit.php:400 #: inc/form-submit.php:445 #: inc/form-submit.php:968 -#: inc/payments/front-end.php:77 -#: inc/payments/front-end.php:258 +#: 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 @@ -16097,32 +16095,32 @@ msgid "Enter a valid email address." msgstr "Inserisci un indirizzo email valido." #. translators: %s represents the minimum acceptable value -#: inc/translatable.php:94 +#: inc/translatable.php:97 #, php-format msgid "Minimum value is %s." msgstr "Il valore minimo è %s." #. translators: %s represents the maximum acceptable value -#: inc/translatable.php:97 +#: inc/translatable.php:100 #, php-format msgid "Maximum value is %s." msgstr "Il valore massimo è %s." #. translators: %s represents the minimum number of options to select -#: inc/translatable.php:100 -#: inc/translatable.php:106 +#: inc/translatable.php:103 +#: inc/translatable.php:109 #, php-format msgid "Select at least %s options." msgstr "Seleziona almeno %s opzioni." #. translators: %s represents the maximum number of options that can be selected -#: inc/translatable.php:103 -#: inc/translatable.php:109 +#: inc/translatable.php:106 +#: inc/translatable.php:112 #, php-format msgid "You can select up to %s options." msgstr "Puoi selezionare fino a %s opzioni." -#: inc/translatable.php:120 +#: inc/translatable.php:123 msgid "This form is now closed as we have reached the maximum number of entries." msgstr "Questo modulo è ora chiuso poiché abbiamo raggiunto il numero massimo di iscrizioni." @@ -16649,35 +16647,35 @@ msgstr "Recupera le impostazioni globali di SureForms. Facoltativamente, filtra msgid "Setting categories to retrieve. Omit for all categories." msgstr "Impostazione delle categorie da recuperare. Omesso per tutte le categorie." -#: inc/abilities/settings/update-global-settings.php:105 +#: inc/abilities/settings/update-global-settings.php:106 msgid "Update Global Settings" msgstr "Aggiorna impostazioni globali" -#: inc/abilities/settings/update-global-settings.php:106 +#: inc/abilities/settings/update-global-settings.php:107 msgid "Update SureForms global settings for a specific category: general, validation-messages, email-summary, or security." msgstr "Aggiorna le impostazioni globali di SureForms per una categoria specifica: generale, messaggi di validazione, riepilogo email o sicurezza." -#: inc/abilities/settings/update-global-settings.php:139 +#: inc/abilities/settings/update-global-settings.php:140 msgid "The settings category to update." msgstr "La categoria di impostazioni da aggiornare." -#: inc/abilities/settings/update-global-settings.php:144 +#: inc/abilities/settings/update-global-settings.php:145 msgid "Key-value pairs of settings to update." msgstr "Coppie chiave-valore delle impostazioni da aggiornare." -#: inc/abilities/settings/update-global-settings.php:180 +#: inc/abilities/settings/update-global-settings.php:181 msgid "Settings category is required." msgstr "La categoria delle impostazioni è obbligatoria." -#: inc/abilities/settings/update-global-settings.php:188 +#: inc/abilities/settings/update-global-settings.php:189 msgid "Settings data is required." msgstr "È necessario fornire i dati delle impostazioni." -#: inc/abilities/settings/update-global-settings.php:199 +#: inc/abilities/settings/update-global-settings.php:200 msgid "No valid settings keys provided for this category." msgstr "Nessuna chiave di impostazione valida fornita per questa categoria." -#: inc/abilities/settings/update-global-settings.php:225 +#: inc/abilities/settings/update-global-settings.php:226 msgid "Invalid settings category." msgstr "Categoria di impostazioni non valida." @@ -17578,6 +17576,212 @@ msgstr "Złoty polacco" msgid "Dynamic Default Value" msgstr "Valore predefinito dinamico" +#: inc/admin/editor-nudge.php:191 +msgid "Hey! It looks like you're creating a form. Build a ready-to-use form in under 30 seconds with SureForms AI, with no extra setup required." +msgstr "Ehi! Sembra che tu stia creando un modulo. Crea un modulo pronto all'uso in meno di 30 secondi con SureForms AI, senza bisogno di configurazioni aggiuntive." + +#: inc/admin/editor-nudge.php:228 +#: inc/admin/editor-nudge.php:237 +msgid "Invalid post." +msgstr "Post non valido." + +#: inc/admin/editor-nudge.php:246 +msgid "You cannot edit this post." +msgstr "Non puoi modificare questo post." + +#: inc/ai-form-builder/ai-form-builder.php:96 +msgid "The AI did not return a form. Please refine your prompt and try again." +msgstr "L'IA non ha restituito un modulo. Per favore, perfeziona il tuo prompt e riprova." + +#: inc/ai-form-builder/ai-form-builder.php:104 +msgid "The AI response is missing a form title. Please try again." +msgstr "La risposta dell'IA manca di un titolo del modulo. Per favore riprova." + +#: inc/ai-form-builder/ai-form-builder.php:115 +#: inc/ai-form-builder/field-mapping.php:69 +msgid "The AI was unable to generate form fields. Please try again." +msgstr "L'IA non è riuscita a generare i campi del modulo. Per favore, riprova." + +#: inc/ai-form-builder/field-mapping.php:41 +msgid "The AI form data is missing. Please try again." +msgstr "I dati del modulo AI sono mancanti. Per favore, riprova." + +#: inc/ai-form-builder/field-mapping.php:51 +msgid "The AI form data is not in the expected format." +msgstr "I dati del modulo AI non sono nel formato previsto." + +#: inc/ai-form-builder/field-mapping.php:60 +msgid "The AI response did not include a form. Please try again." +msgstr "La risposta dell'IA non includeva un modulo. Per favore, riprova." + +#: inc/ai-form-builder/field-mapping.php:90 +msgid "The AI returned a malformed form field. Please try again." +msgstr "L'IA ha restituito un campo del modulo malformato. Per favore riprova." + +#: inc/create-new-form.php:160 +#: inc/create-new-form.php:173 +msgid "Error creating SureForms Form." +msgstr "Errore nella creazione del modulo SureForms." + +#. translators: %s represents the minimum number of characters required +#: inc/field-validation.php:289 +#: inc/translatable.php:94 +#, php-format +msgid "Please enter at least %s characters." +msgstr "Si prega di inserire almeno %s caratteri." + +#: inc/fields/payment-markup.php:246 +msgid "One-Time Payment" +msgstr "Pagamento una tantum" + +#: inc/fields/payment-markup.php:562 +msgid "Choose payment type" +msgstr "Scegli il tipo di pagamento" + +#: inc/payments/front-end.php:333 +msgid "Billing interval does not match the form configuration." +msgstr "L'intervallo di fatturazione non corrisponde alla configurazione del modulo." + +#: inc/payments/payment-helper.php:627 +msgid "Payment type does not match the form configuration." +msgstr "Il tipo di pagamento non corrisponde alla configurazione del modulo." + +#: inc/payments/payment-helper.php:760 +msgid "Payment verification failed. Payment type mismatch." +msgstr "Verifica del pagamento fallita. Tipo di pagamento non corrispondente." + +#: assets/build/blocks.js:172 +msgid "Minimum Characters" +msgstr "Caratteri Minimi" + +#: assets/build/blocks.js:172 +msgid "Minimum characters cannot exceed Maximum characters." +msgstr "I caratteri minimi non possono superare i caratteri massimi." + +#: assets/build/blocks.js:172 +msgid "Both" +msgstr "Entrambi" + +#: assets/build/blocks.js:172 +msgid "One-Time Label" +msgstr "Etichetta monouso" + +#: assets/build/blocks.js:172 +msgid "Label shown to users for the one-time payment option." +msgstr "Etichetta mostrata agli utenti per l'opzione di pagamento una tantum." + +#: assets/build/blocks.js:172 +msgid "Subscription Label" +msgstr "Etichetta di abbonamento" + +#: assets/build/blocks.js:172 +msgid "Label shown to users for the subscription option." +msgstr "Etichetta mostrata agli utenti per l'opzione di abbonamento." + +#: assets/build/blocks.js:172 +msgid "Default Selection" +msgstr "Selezione predefinita" + +#: assets/build/blocks.js:172 +msgid "Which option is pre-selected when the form loads." +msgstr "Quale opzione è preselezionata quando il modulo viene caricato." + +#: assets/build/blocks.js:172 +msgid "One-Time Amount Type" +msgstr "Tipo di importo una tantum" + +#: assets/build/blocks.js:172 +msgid "Set how the one-time payment amount is determined." +msgstr "Imposta come viene determinato l'importo del pagamento una tantum." + +#: assets/build/blocks.js:172 +msgid "One-Time Fixed Amount" +msgstr "Importo fisso una tantum" + +#: assets/build/blocks.js:172 +msgid "Amount charged for a one-time payment." +msgstr "Importo addebitato per un pagamento una tantum." + +#: assets/build/blocks.js:172 +msgid "One-Time Amount Field" +msgstr "Campo Importo Una Tantum" + +#: assets/build/blocks.js:172 +msgid "Pick a form field whose value determines the one-time payment amount." +msgstr "Scegli un campo del modulo il cui valore determina l'importo del pagamento una tantum." + +#: assets/build/blocks.js:172 +msgid "One-Time Minimum Amount" +msgstr "Importo minimo una tantum" + +#: assets/build/blocks.js:172 +msgid "Minimum amount users can enter for one-time payment (0 for no minimum)." +msgstr "Importo minimo che gli utenti possono inserire per un pagamento una tantum (0 per nessun minimo)." + +#: assets/build/blocks.js:172 +msgid "Subscription Amount Type" +msgstr "Tipo di importo dell'abbonamento" + +#: assets/build/blocks.js:172 +msgid "Set how the subscription amount is determined." +msgstr "Imposta come viene determinato l'importo dell'abbonamento." + +#: assets/build/blocks.js:172 +msgid "Subscription Fixed Amount" +msgstr "Importo fisso dell'abbonamento" + +#: assets/build/blocks.js:172 +msgid "Recurring amount charged per billing interval." +msgstr "Importo ricorrente addebitato per intervallo di fatturazione." + +#: assets/build/blocks.js:172 +msgid "Subscription Amount Field" +msgstr "Campo Importo Abbonamento" + +#: assets/build/blocks.js:172 +msgid "Pick a form field whose value determines the subscription amount." +msgstr "Scegli un campo del modulo il cui valore determina l'importo dell'abbonamento." + +#: assets/build/blocks.js:172 +msgid "Subscription Minimum Amount" +msgstr "Importo minimo di sottoscrizione" + +#: assets/build/blocks.js:172 +msgid "Minimum amount users can enter for subscription (0 for no minimum)." +msgstr "Importo minimo che gli utenti possono inserire per l'abbonamento (0 per nessun minimo)." + +#: 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 "Scegli un campo dal tuo modulo come un numero, un menu a tendina, una scelta multipla o nascosto il cui valore dovrebbe determinare l'importo del pagamento." + +#: assets/build/templatePicker.js:172 +msgid "You do not have permission to create forms." +msgstr "Non hai il permesso di creare moduli." + +#: assets/build/templatePicker.js:172 +msgid "The form could not be saved. Please try again." +msgstr "Il modulo non può essere salvato. Per favore riprova." + +#: assets/build/templatePicker.js:172 +msgid "Unable to reach the SureForms AI service. Please check your connection and try again." +msgstr "Impossibile raggiungere il servizio SureForms AI. Controlla la tua connessione e riprova." + +#: assets/build/templatePicker.js:172 +msgid "The AI service did not return a response. Please try again." +msgstr "Il servizio AI non ha restituito una risposta. Per favore riprova." + +#: assets/build/templatePicker.js:172 +msgid "Form generation failed. Please try again." +msgstr "La generazione del modulo non è riuscita. Si prega di riprovare." + +#: assets/build/templatePicker.js:172 +msgid "The AI response was empty. Please refine your prompt and try again." +msgstr "La risposta dell'IA era vuota. Per favore, perfeziona il tuo prompt e riprova." + +#: assets/build/templatePicker.js:172 +msgid "Unable to build form fields from the AI response." +msgstr "Impossibile creare i campi del modulo dalla risposta dell'AI." + #: inc/post-types.php:205 msgctxt "post type general name" msgid "Forms" diff --git a/languages/sureforms-nl_NL-120a6dad015d3891c70f578c2251576b.json b/languages/sureforms-nl_NL-120a6dad015d3891c70f578c2251576b.json index bcba13a00..e3e9f16c5 100644 --- a/languages/sureforms-nl_NL-120a6dad015d3891c70f578c2251576b.json +++ b/languages/sureforms-nl_NL-120a6dad015d3891c70f578c2251576b.json @@ -1 +1 @@ -{"translation-revision-date":"2024-12-13T12:33:48+00:00","generator":"WP-CLI\/2.12.0","source":"assets\/build\/templatePicker.js","domain":"messages","locale_data":{"messages":{"":{"domain":"messages","lang":"en","plural-forms":"nplurals=2; plural=(n != 1);"},"Dashboard":["Dashboard"],"Connect Now":["Nu verbinden"],"Authentication Failed":["Verificatie mislukt"],"Contact Support":["Neem contact op met de ondersteuning"],"Click Here to Retry":["Klik hier om het opnieuw te proberen"],"Exit to Dashboard":["Verlaat naar Dashboard"],"AI Form Builder":["AI Formulierbouwer"],"Speech recognition is not supported in your current browser. Please use Google Chrome \/ Safari.":["Spraakherkenning wordt niet ondersteund in uw huidige browser. Gebruik alstublieft Google Chrome \/ Safari."],"Please allow microphone access to use voice input.":["Sta microfoontoegang toe om spraakinvoer te gebruiken."],"Voice Input":["Spraakinvoer"],"Try Again":["Probeer opnieuw"],"Please try again after %s.":["Probeer het alstublieft opnieuw na %s."],"You have reached the maximum number of form generations in your Free Plan.":["U heeft het maximale aantal formuliergeneraties in uw Gratis Plan bereikt."],"Unlock Conversational Forms":["Ontgrendel Gespreksformulieren"],"Simple":["Eenvoudig"],"Upgrade Now":["Nu upgraden"],"Generate with AI":["Genereer met AI"],"Please check your username and password for the account, and try to reconnect again. Need help?":["Controleer uw gebruikersnaam en wachtwoord voor het account en probeer opnieuw verbinding te maken. Hulp nodig?"],"Describe the form you want to create":["Beschrijf het formulier dat je wilt maken"],"We are building your form\u2026":["We zijn uw formulier aan het maken\u2026"],"Payment":["Betaling"],"and ":["en"],"more\u2026":["meer\u2026"],"Calculations":["Berekeningen"],"Unlock Calculator Forms":["Rekenmachineformulieren ontgrendelen"],"Build Smart Forms That Calculate Instantly":["Bouw slimme formulieren die direct berekenen"],"Empower your forms with advanced calculations. From loan calculators to BMI checkers - create interactive forms that give real-time results.":["Geef uw formulieren meer kracht met geavanceerde berekeningen. Van leningcalculators tot BMI-checkers - maak interactieve formulieren die real-time resultaten geven."],"Add complex formulas with ease":["Voeg eenvoudig complexe formules toe"],"Provide instant answers to users":["Geef gebruikers direct antwoord"],"Perfect for finance, health, and pricing forms":["Perfect voor financi\u00eble, gezondheids- en prijsformulieren"],"Conversational":["Gesprek"],"Turn Simple Forms Into Conversations":["Verander eenvoudige formulieren in gesprekken"],"Transform boring forms into friendly, chat-like experiences. Ask one question at a time, just like a real conversation, and see higher engagement.":["Verander saaie formulieren in vriendelijke, chat-achtige ervaringen. Stel \u00e9\u00e9n vraag tegelijk, net als in een echt gesprek, en zie een hogere betrokkenheid."],"One question at a time, in chat flow":["E\u00e9n vraag tegelijk, in de chatstroom"],"More engaging than traditional forms":["Meer boeiend dan traditionele vormen"],"Boosts completion rates with a friendly interface":["Verhoogt de voltooiingspercentages met een gebruiksvriendelijke interface"],"Select this if you need calculations in your form. For example: Loan interest calculator.":["Selecteer dit als u berekeningen in uw formulier nodig heeft. Bijvoorbeeld: Lening rente calculator."],"Select this if you want your form to display one question at a time, like a chat.":["Selecteer dit als u wilt dat uw formulier \u00e9\u00e9n vraag tegelijk weergeeft, zoals in een chat."],"Select this if you want to collect payments through your form.":["Selecteer dit als u betalingen via uw formulier wilt innen."],"%d AI Generations Left. SureForms Premium allows:":["%d AI-generaties over. SureForms Premium biedt:"],"%d AI Generations Left, Connect to SureForms AI to Get 10 More":["%d AI-generaties over, verbind met SureForms AI om er 10 meer te krijgen"],"%d AI Generations Left. Upgrade to SureForms Premium":["%d AI-generaties over. Upgrade naar SureForms Premium"],"Contact form to collect name, email, and message from visitors":["Contactformulier om naam, e-mail en bericht van bezoekers te verzamelen"],"Job application form for \"Marketing Manager\" with resume upload":["Sollicitatieformulier voor \"Marketing Manager\" met cv-upload"],"Feedback form to ask customers: \"How would you rate our product and what should we improve?\"":["Feedbackformulier om klanten te vragen: \"Hoe zou u ons product beoordelen en wat moeten we verbeteren?\""],"Event registration form for \"Photography Workshop\" with date and seat selection":["Inschrijfformulier voor het \"Fotografie Workshop\" met datum- en stoelkeuze"],"Newsletter signup form with name and email to join mailing list":["Inschrijfformulier voor nieuwsbrief met naam en e-mail om lid te worden van de mailinglijst"],"Order form for \"Custom T-Shirt\" with size, color, and quantity options":["Bestelformulier voor \"Aangepast T-shirt\" met opties voor maat, kleur en hoeveelheid"],"Survey form: \"How satisfied are you with our service? (1\u20135 stars)\"":["Enqu\u00eateformulier: \"Hoe tevreden bent u met onze service? (1\u20135 sterren)\""],"Appointment booking form for \"Consultation Call\" with preferred time":["Afsprakenboekingsformulier voor \"Consultatiegesprek\" met voorkeurstijd"],"Describe the form that you want":["Beschrijf de vorm die je wilt"],"Generate":["Genereren"],"Create Unlimited Forms with AI":["Maak onbeperkte formulieren met AI"],"Add Advanced Field Types":["Geavanceerde veldtypen toevoegen"],"Create Calculators, Surveys, etc.":["Maak rekenmachines, enqu\u00eates, enz."],"Form Generation Limit Reached":["Limiet voor formuliergeneratie bereikt"],"You have reached the maximum number of form generations in your Free Plan. SureForms Premium allows:":["Je hebt het maximale aantal formuliergeneraties in je Gratis Plan bereikt. SureForms Premium biedt:"],"%s AI Generations Left.":["%s AI-generaties over."],"Unlock Unlimited Generations":["Ontgrendel Onbeperkte Generaties"],"Connect to SureForms AI":["Verbind met SureForms AI"],"You Have Hit Your Free Limit.":["U heeft uw gratis limiet bereikt."],"Connect to SureForms AI to Get 10 More.":["Verbind met SureForms AI om er 10 meer te krijgen."],"Or create it yourself":["Of maak het zelf"],"Unable to create form":["Kan formulier niet maken"],"Something went wrong. Please try again.":["Er is iets misgegaan. Probeer het alstublieft opnieuw."],"Describe what kind of form you want":["Beschrijf welk soort formulier je wilt"],"Click to generate the form":["Klik om het formulier te genereren"],"Connecting to AI service":["Verbinden met AI-service"],"Generating fields":["Velden genereren"],"Finalizing your form":["Uw formulier afronden"],"Opening form editor":["Formuliereditor openen"],"Design Multistep Forms":["Ontwerp meerstapsformulieren"],"Send Form Entries to Your CRM or Any App":["Verzend formulierinzendingen naar uw CRM of een andere app"],"You've reached your daily generation limit.":["Je hebt je dagelijkse generatielimiet bereikt."],"You've reached your daily limit for AI form generations.":["Je hebt je dagelijkse limiet voor AI-formuliergeneraties bereikt."],"Quiz":["Quiz"],"Unlock Quiz Forms":["Quizformulieren ontgrendelen"],"Create Engaging Quizzes That Score Automatically":["Maak boeiende quizzen die automatisch scoren"],"Build interactive quizzes with scored questions and graded results. Perfect for assessments, trivia, and educational content.":["Bouw interactieve quizzen met gescoorde vragen en beoordeelde resultaten. Perfect voor beoordelingen, trivia en educatieve inhoud."],"Auto-score responses instantly":["Antwoorden direct automatisch scoren"],"Display graded results to users":["Toon beoordeelde resultaten aan gebruikers"],"Perfect for education, training, and fun trivia":["Perfect voor educatie, training en leuke trivia"],"Select this to create a quiz with scored questions and graded results.":["Selecteer dit om een quiz te maken met gescoorde vragen en beoordeelde resultaten."],"Select this to create a survey to collect responses and opinions.":["Selecteer dit om een enqu\u00eate te maken om reacties en meningen te verzamelen."],"Survey":["Enqu\u00eate"],"Unlock Survey Forms":["Enqu\u00eateformulieren ontgrendelen"],"Collect Insights with Powerful Surveys":["Verzamel inzichten met krachtige enqu\u00eates"],"Create surveys to collect responses and opinions. Visualize results with charts and share aggregated insights with your audience.":["Maak enqu\u00eates om reacties en meningen te verzamelen. Visualiseer resultaten met grafieken en deel geaggregeerde inzichten met uw publiek."],"Aggregate and visualize responses":["Responses aggregeren en visualiseren"],"Show live results to respondents":["Toon live resultaten aan respondenten"],"Perfect for feedback, polls, and research":["Perfect voor feedback, peilingen en onderzoek"]}}} \ No newline at end of file +{"translation-revision-date":"2024-12-13T12:33:48+00:00","generator":"WP-CLI\/2.12.0","source":"assets\/build\/templatePicker.js","domain":"messages","locale_data":{"messages":{"":{"domain":"messages","lang":"en","plural-forms":"nplurals=2; plural=(n != 1);"},"Dashboard":["Dashboard"],"Connect Now":["Nu verbinden"],"Authentication Failed":["Verificatie mislukt"],"Contact Support":["Neem contact op met de ondersteuning"],"Click Here to Retry":["Klik hier om het opnieuw te proberen"],"Exit to Dashboard":["Verlaat naar Dashboard"],"AI Form Builder":["AI Formulierbouwer"],"Speech recognition is not supported in your current browser. Please use Google Chrome \/ Safari.":["Spraakherkenning wordt niet ondersteund in uw huidige browser. Gebruik alstublieft Google Chrome \/ Safari."],"Please allow microphone access to use voice input.":["Sta microfoontoegang toe om spraakinvoer te gebruiken."],"Voice Input":["Spraakinvoer"],"Try Again":["Probeer opnieuw"],"Please try again after %s.":["Probeer het alstublieft opnieuw na %s."],"You have reached the maximum number of form generations in your Free Plan.":["U heeft het maximale aantal formuliergeneraties in uw Gratis Plan bereikt."],"Unlock Conversational Forms":["Ontgrendel Gespreksformulieren"],"Simple":["Eenvoudig"],"Upgrade Now":["Nu upgraden"],"Generate with AI":["Genereer met AI"],"Please check your username and password for the account, and try to reconnect again. Need help?":["Controleer uw gebruikersnaam en wachtwoord voor het account en probeer opnieuw verbinding te maken. Hulp nodig?"],"Describe the form you want to create":["Beschrijf het formulier dat je wilt maken"],"We are building your form\u2026":["We zijn uw formulier aan het maken\u2026"],"Payment":["Betaling"],"and ":["en"],"more\u2026":["meer\u2026"],"Calculations":["Berekeningen"],"Unlock Calculator Forms":["Rekenmachineformulieren ontgrendelen"],"Build Smart Forms That Calculate Instantly":["Bouw slimme formulieren die direct berekenen"],"Empower your forms with advanced calculations. From loan calculators to BMI checkers - create interactive forms that give real-time results.":["Geef uw formulieren meer kracht met geavanceerde berekeningen. Van leningcalculators tot BMI-checkers - maak interactieve formulieren die real-time resultaten geven."],"Add complex formulas with ease":["Voeg eenvoudig complexe formules toe"],"Provide instant answers to users":["Geef gebruikers direct antwoord"],"Perfect for finance, health, and pricing forms":["Perfect voor financi\u00eble, gezondheids- en prijsformulieren"],"Conversational":["Gesprek"],"Turn Simple Forms Into Conversations":["Verander eenvoudige formulieren in gesprekken"],"Transform boring forms into friendly, chat-like experiences. Ask one question at a time, just like a real conversation, and see higher engagement.":["Verander saaie formulieren in vriendelijke, chat-achtige ervaringen. Stel \u00e9\u00e9n vraag tegelijk, net als in een echt gesprek, en zie een hogere betrokkenheid."],"One question at a time, in chat flow":["E\u00e9n vraag tegelijk, in de chatstroom"],"More engaging than traditional forms":["Meer boeiend dan traditionele vormen"],"Boosts completion rates with a friendly interface":["Verhoogt de voltooiingspercentages met een gebruiksvriendelijke interface"],"Select this if you need calculations in your form. For example: Loan interest calculator.":["Selecteer dit als u berekeningen in uw formulier nodig heeft. Bijvoorbeeld: Lening rente calculator."],"Select this if you want your form to display one question at a time, like a chat.":["Selecteer dit als u wilt dat uw formulier \u00e9\u00e9n vraag tegelijk weergeeft, zoals in een chat."],"Select this if you want to collect payments through your form.":["Selecteer dit als u betalingen via uw formulier wilt innen."],"%d AI Generations Left. SureForms Premium allows:":["%d AI-generaties over. SureForms Premium biedt:"],"%d AI Generations Left, Connect to SureForms AI to Get 10 More":["%d AI-generaties over, verbind met SureForms AI om er 10 meer te krijgen"],"%d AI Generations Left. Upgrade to SureForms Premium":["%d AI-generaties over. Upgrade naar SureForms Premium"],"Contact form to collect name, email, and message from visitors":["Contactformulier om naam, e-mail en bericht van bezoekers te verzamelen"],"Job application form for \"Marketing Manager\" with resume upload":["Sollicitatieformulier voor \"Marketing Manager\" met cv-upload"],"Feedback form to ask customers: \"How would you rate our product and what should we improve?\"":["Feedbackformulier om klanten te vragen: \"Hoe zou u ons product beoordelen en wat moeten we verbeteren?\""],"Event registration form for \"Photography Workshop\" with date and seat selection":["Inschrijfformulier voor het \"Fotografie Workshop\" met datum- en stoelkeuze"],"Newsletter signup form with name and email to join mailing list":["Inschrijfformulier voor nieuwsbrief met naam en e-mail om lid te worden van de mailinglijst"],"Order form for \"Custom T-Shirt\" with size, color, and quantity options":["Bestelformulier voor \"Aangepast T-shirt\" met opties voor maat, kleur en hoeveelheid"],"Survey form: \"How satisfied are you with our service? (1\u20135 stars)\"":["Enqu\u00eateformulier: \"Hoe tevreden bent u met onze service? (1\u20135 sterren)\""],"Appointment booking form for \"Consultation Call\" with preferred time":["Afsprakenboekingsformulier voor \"Consultatiegesprek\" met voorkeurstijd"],"Describe the form that you want":["Beschrijf de vorm die je wilt"],"Generate":["Genereren"],"Create Unlimited Forms with AI":["Maak onbeperkte formulieren met AI"],"Add Advanced Field Types":["Geavanceerde veldtypen toevoegen"],"Create Calculators, Surveys, etc.":["Maak rekenmachines, enqu\u00eates, enz."],"Form Generation Limit Reached":["Limiet voor formuliergeneratie bereikt"],"You have reached the maximum number of form generations in your Free Plan. SureForms Premium allows:":["Je hebt het maximale aantal formuliergeneraties in je Gratis Plan bereikt. SureForms Premium biedt:"],"%s AI Generations Left.":["%s AI-generaties over."],"Unlock Unlimited Generations":["Ontgrendel Onbeperkte Generaties"],"Connect to SureForms AI":["Verbind met SureForms AI"],"You Have Hit Your Free Limit.":["U heeft uw gratis limiet bereikt."],"Connect to SureForms AI to Get 10 More.":["Verbind met SureForms AI om er 10 meer te krijgen."],"Or create it yourself":["Of maak het zelf"],"Unable to create form":["Kan formulier niet maken"],"Something went wrong. Please try again.":["Er is iets misgegaan. Probeer het alstublieft opnieuw."],"Describe what kind of form you want":["Beschrijf welk soort formulier je wilt"],"Click to generate the form":["Klik om het formulier te genereren"],"Connecting to AI service":["Verbinden met AI-service"],"Generating fields":["Velden genereren"],"Finalizing your form":["Uw formulier afronden"],"Opening form editor":["Formuliereditor openen"],"Design Multistep Forms":["Ontwerp meerstapsformulieren"],"Send Form Entries to Your CRM or Any App":["Verzend formulierinzendingen naar uw CRM of een andere app"],"You've reached your daily generation limit.":["Je hebt je dagelijkse generatielimiet bereikt."],"You've reached your daily limit for AI form generations.":["Je hebt je dagelijkse limiet voor AI-formuliergeneraties bereikt."],"Quiz":["Quiz"],"Unlock Quiz Forms":["Quizformulieren ontgrendelen"],"Create Engaging Quizzes That Score Automatically":["Maak boeiende quizzen die automatisch scoren"],"Build interactive quizzes with scored questions and graded results. Perfect for assessments, trivia, and educational content.":["Bouw interactieve quizzen met gescoorde vragen en beoordeelde resultaten. Perfect voor beoordelingen, trivia en educatieve inhoud."],"Auto-score responses instantly":["Antwoorden direct automatisch scoren"],"Display graded results to users":["Toon beoordeelde resultaten aan gebruikers"],"Perfect for education, training, and fun trivia":["Perfect voor educatie, training en leuke trivia"],"Select this to create a quiz with scored questions and graded results.":["Selecteer dit om een quiz te maken met gescoorde vragen en beoordeelde resultaten."],"Select this to create a survey to collect responses and opinions.":["Selecteer dit om een enqu\u00eate te maken om reacties en meningen te verzamelen."],"Survey":["Enqu\u00eate"],"Unlock Survey Forms":["Enqu\u00eateformulieren ontgrendelen"],"Collect Insights with Powerful Surveys":["Verzamel inzichten met krachtige enqu\u00eates"],"Create surveys to collect responses and opinions. Visualize results with charts and share aggregated insights with your audience.":["Maak enqu\u00eates om reacties en meningen te verzamelen. Visualiseer resultaten met grafieken en deel geaggregeerde inzichten met uw publiek."],"Aggregate and visualize responses":["Responses aggregeren en visualiseren"],"Show live results to respondents":["Toon live resultaten aan respondenten"],"Perfect for feedback, polls, and research":["Perfect voor feedback, peilingen en onderzoek"],"You do not have permission to create forms.":["Je hebt geen toestemming om formulieren te maken."],"The form could not be saved. Please try again.":["Het formulier kon niet worden opgeslagen. Probeer het alstublieft opnieuw."],"Unable to reach the SureForms AI service. Please check your connection and try again.":["Kan geen verbinding maken met de SureForms AI-service. Controleer uw verbinding en probeer het opnieuw."],"The AI service did not return a response. Please try again.":["De AI-service gaf geen reactie. Probeer het alstublieft opnieuw."],"Form generation failed. Please try again.":["Het genereren van het formulier is mislukt. Probeer het alstublieft opnieuw."],"The AI response was empty. Please refine your prompt and try again.":["De AI-reactie was leeg. Gelieve uw prompt te verfijnen en het opnieuw te proberen."],"Unable to build form fields from the AI response.":["Kan formuliervelden niet opbouwen vanuit de AI-reactie."]}}} \ No newline at end of file diff --git a/languages/sureforms-nl_NL-4b62e3f004dea2c587b5a3069263d994.json b/languages/sureforms-nl_NL-4b62e3f004dea2c587b5a3069263d994.json index 1d9668d18..f6fd76771 100644 --- a/languages/sureforms-nl_NL-4b62e3f004dea2c587b5a3069263d994.json +++ b/languages/sureforms-nl_NL-4b62e3f004dea2c587b5a3069263d994.json @@ -1 +1 @@ -{"translation-revision-date":"2024-12-13T12:33:48+00:00","generator":"WP-CLI\/2.12.0","source":"assets\/build\/blocks.js","domain":"messages","locale_data":{"messages":{"":{"domain":"messages","lang":"en","plural-forms":"nplurals=2; plural=(n != 1);"},"Settings":["Instellingen"],"Search":["Zoeken"],"Fields":["Velden"],"Image":["Afbeelding"],"Submit":["Indienen"],"Required":["Vereist"],"Form Title":["Formuliertitel"],"Show":["Tonen"],"Hide":["Verbergen"],"Edit Form":["Formulier bewerken"],"Icon":["Icoon"],"Desktop":["Bureaublad"],"Medium":["Middelgroot"],"Mobile":["Mobiel"],"Repeat":["Herhaal"],"Scroll":["Scrollen"],"Tablet":["Tablet"],"Basic":["Basis"],"(no title)":["(geen titel)"],"Select a Form":["Selecteer een formulier"],"No forms found\u2026":["Geen formulieren gevonden\u2026"],"Choose":["Kies"],"Create New":["Nieuw maken"],"Change Form":["Formulier wijzigen"],"This form has been deleted or is unavailable.":["Dit formulier is verwijderd of is niet beschikbaar."],"Form Settings":["Formulierinstellingen"],"Show Form Title on this Page":["Toon formulier titel op deze pagina"],"Note: For editing SureForms, please refer to the SureForms Editor - ":["Opmerking: Voor het bewerken van SureForms, raadpleeg de SureForms Editor -"],"Field preview":["Veldvoorbeeld"],"General":["Algemeen"],"Style":["Stijl"],"Advanced":["Geavanceerd"],"No tags available":["Geen tags beschikbaar"],"Device":["Apparaat"],"Select Shortcodes":["Selecteer shortcodes"],"Page Break Label":["Pagina-einde label"],"Next":["Volgende"],"Back":["Terug"],"Reset":["Resetten"],"Generic tags":["Algemene tags"],"Pixel":["Pixel"],"Em":["Em"],"Select Units":["Selecteer eenheden"],"%s units":["%s eenheden"],"Margin":["Marge"],"Attributes":["Kenmerken"],"Input Pattern":["Invoermuster"],"None":["Geen"],"(###) ###-####":["(###) ###-####"],"(##) ####-####":["(##) ####-####"],"27\/08\/2024":["27\/08\/2024"],"23:59:59":["23:59:59"],"27\/08\/2024 23:59:59":["27\/08\/2024 23:59:59"],"Custom":["Aangepast"],"Custom Mask":["Aangepast masker"],"Please check the documentation to manage custom input pattern ":["Controleer de documentatie om het aangepaste invoerpatroon te beheren"],"here":["hier"],"Default Value":["Standaardwaarde"],"Error Message":["Foutmelding"],"Help Text":["Helptekst"],"Number Format":["Getalnotatie"],"US Style (Eg: 9,999.99)":["VS-stijl (Bijv: 9.999,99)"],"EU Style (Eg: 9.999,99)":["EU-stijl (Bijv: 9.999,99)"],"Minimum Value":["Minimumwaarde"],"Maximum Value":["Maximale waarde"],"Please check the Minimum and Maximum value":["Controleer de minimum- en maximumwaarde"],"Enable Email Confirmation":["E-mailbevestiging inschakelen"],"Checked by Default":["Standaard aangevinkt"],"Error message":["Foutmelding"],"Checked by default":["Standaard aangevinkt"],"Please add a option props to MultiButtonsControl":["Voeg alstublieft een optie-eigenschap toe aan MultiButtonsControl"],"Icon Library":["Iconenbibliotheek"],"Close":["Sluiten"],"All Icons":["Alle pictogrammen"],"Other":["Anders"],"No Icons Found":["Geen pictogrammen gevonden"],"Insert Icon":["Pictogram invoegen"],"Change Icon":["Pictogram wijzigen"],"Choose Icon":["Kies pictogram"],"Confirm":["Bevestigen"],"Cancel":["Annuleren"],"Processing\u2026":["Bezig met verwerken\u2026"],"Select Video":["Selecteer video"],"Change Video":["Video wijzigen"],"Select Lottie Animation":["Selecteer Lottie-animatie"],"Change Lottie Animation":["Wijzig Lottie-animatie"],"Upload SVG":["SVG uploaden"],"Change SVG":["SVG wijzigen"],"Select Image":["Selecteer afbeelding"],"Change Image":["Afbeelding wijzigen"],"Upload SVG?":["SVG uploaden?"],"Upload SVG can be potentially risky. Are you sure?":["Het uploaden van SVG kan potentieel riskant zijn. Weet je het zeker?"],"Upload Anyway":["Toch uploaden"],"Bulk Add":["Bulk toevoegen"],"Bulk Add Options":["Bulkopties toevoegen"],"Enter each option on a new line.":["Voer elke optie op een nieuwe regel in."],"Insert Options":["Opties invoegen"],"Full Width":["Volledige breedte"],"Option Type":["Optietype"],"Edit Options":["Bewerk opties"],"Add New Option":["Nieuwe optie toevoegen"],"ADD":["TOEVOEGEN"],"Enable Auto Country Detection":["Automatische landdetectie inschakelen"],"%s Width":["%s Breedte"],"Upgrade":["Upgrade"],"Clear":["Duidelijk"],"Select Color":["Selecteer kleur"],"Primary Color":["Primaire kleur"],"Text Color":["Tekstkleur"],"Field Spacing":["Veldafstand"],"Small":["Klein"],"Large":["Groot"],"Left":["Links"],"Center":["Centrum"],"Right":["Rechts"],"Color":["Kleur"],"Background Color":["Achtergrondkleur"],"Auto":["Auto"],"Default":["Standaard"],"Normal":["Normaal"],"%":["%"],"Top":["Top"],"Bottom":["Onderkant"],"Width":["Breedte"],"Size":["Grootte"],"EM":["EM"],"Padding":["Opvulling"],"Color 1":["Kleur 1"],"Color 2":["Kleur 2"],"Type":["Type"],"Linear":["Lineair"],"Radial":["Radiaal"],"Location 1":["Locatie 1"],"Location 2":["Locatie 2"],"Angle":["Hoek"],"Classic":["Klassiek"],"Gradient":["Gradi\u00ebnt"],"Horizontal":["Horizontaal"],"Vertical":["Verticaal"],"Background":["Achtergrond"],"Cover":["Omslag"],"Contain":["Bevatten"],"Layout":["Indeling"],"Overlay":["Overlay"],"No Repeat":["Geen herhaling"],"Overlay Opacity":["Overlay-opaciteit"],"Conditional Logic":["Conditionele logica"],"Upgrade to the SureForms Starter Plan to create dynamic forms that adapt based on user input, offering a personalised and efficient form experience.":["Upgrade naar het SureForms Starter Plan om dynamische formulieren te maken die zich aanpassen op basis van gebruikersinvoer, en zo een gepersonaliseerde en effici\u00ebnte formulierervaring bieden."],"Enable Conditional Logic":["Voorwaardelijke logica inschakelen"],"this field if":["dit veld indien"],"Configure Conditions":["Voorwaarden configureren"],"Premium":["Premium"],"Overlay Type":["Overlaytype"],"Image Overlay Color":["Afbeelding Overlay Kleur"],"Image Position":["Afbeeldingspositie"],"Attachment":["Bijlage"],"Fixed":["Vast"],"Blend Mode":["Overvloeimodus"],"Multiply":["Vermenigvuldigen"],"Screen":["Scherm"],"Darken":["Verduisteren"],"Lighten":["Verlichten"],"Color Dodge":["Kleur Dodge"],"Saturation":["Verzadiging"],"Repeat-x":["Herhaal-x"],"Repeat-y":["Herhaal-y"],"PX":["PX"],"Button":["Knop"],"Prefix Label":["Voorvoegsel Label"],"Suffix Label":["Achtervoegsel Label"],"Border Radius":["Randstraal"],"Form Theme":["Formulier Thema"],"Select Gradient":["Selecteer verloop"],"Unlock Conditional Logic Editor":["Ontgrendel de voorwaardelijke logica-editor"],"Rich Text Editor":["Rich Text Editor"],"Read Only":["Alleen lezen"],"Select Country":["Selecteer land"],"Default Country":["Standaardland"],"Subscription":["Abonnement"],"One Time":["E\u00e9n keer"],"Unique Entry":["Unieke invoer"],"Maximum Characters":["Maximale tekens"],"Textarea Height":["Hoogte van tekstvak"],"Minimum Selections":["Minimale selecties"],"Maximum Selections":["Maximale selecties"],"Add Numeric Values to Options":["Numerieke waarden aan opties toevoegen"],"Single Choice Only":["Enkel \u00e9\u00e9n keuze"],"Enable Dropdown Search":["Dropdown zoeken inschakelen"],"Allow Multiple":["Meerdere toestaan"],"%1$s fields are required. Please configure these fields in the block settings.":["%1$s velden zijn verplicht. Configureer deze velden in de blokinstellingen."],"%1$s field is required. Please configure this field in the block settings.":["%1$s veld is verplicht. Configureer dit veld in de blokinstellingen."],"You need to configure a payment account to collect payments from this form. Please configure your payment provider to proceed.":["U moet een betaalrekening configureren om betalingen van dit formulier te innen. Configureer uw betalingsprovider om door te gaan."],"Configure Payment Account":["Betaalrekening configureren"],"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.":["Dit is een tijdelijke aanduiding voor het betalingsblok. De daadwerkelijke betalingsvelden voor uw geconfigureerde betalingsprovider(s) verschijnen alleen wanneer u het formulier bekijkt of publiceert."],"2 Payments":["2 Betalingen"],"3 Payments":["3 Betalingen"],"4 Payments":["4 Betalingen"],"5 Payments":["5 Betalingen"],"Never":["Nooit"],"Stop Subscription After":["Abonnement Stoppen Na"],"Choose when to automatically stop the subscription":["Kies wanneer het abonnement automatisch moet worden stopgezet"],"Number of Payments":["Aantal betalingen"],"Enter a number between 1 to 100":["Voer een getal in tussen 1 en 100"],"Form Field":["Formulier Veld"],"Payment Type":["Betalingstype"],"Subscription Plan Name":["Abonnementsplan Naam"],"Billing Interval":["Factureringsinterval"],"Daily":["Dagelijks"],"Weekly":["Wekelijks"],"Monthly":["Maandelijks"],"Quarterly":["Per kwartaal"],"Yearly":["Jaarlijks"],"Amount Type":["Bedragstype"],"Fixed Amount":["Vast Bedrag"],"Dynamic Amount":["Dynamisch Bedrag"],"Choose whether to charge a fixed amount or charge the amount based on user input in other form fields.":["Kies of u een vast bedrag wilt rekenen of het bedrag wilt berekenen op basis van gebruikersinvoer in andere formuliervelden."],"Set the exact amount you want to charge. Users won\u2019t be able to change it":["Stel het exacte bedrag in dat u wilt berekenen. Gebruikers kunnen het niet wijzigen"],"Choose Amount Field":["Kies bedragveld"],"Select a field\u2026":["Selecteer een veld\u2026"],"Pick a field from your form like a number, dropdown, or multichoice whose value should decide the payment amount.":["Kies een veld uit uw formulier, zoals een nummer, dropdown of meerkeuze, waarvan de waarde het betalingsbedrag moet bepalen."],"Minimum Amount":["Minimumbedrag"],"Set the minimum amount users can enter (0 for no minimum)":["Stel het minimale bedrag in dat gebruikers kunnen invoeren (0 voor geen minimum)"],"Customer Name Field (Required)":["Klantnaamveld (Verplicht)"],"Customer Name Field (Optional)":["Klantnaamveld (Optioneel)"],"Select the input field that contains the customer name (Required for subscriptions)":["Selecteer het invoerveld dat de klantnaam bevat (Vereist voor abonnementen)"],"Select the input field that contains the customer name":["Selecteer het invoerveld dat de klantnaam bevat"],"Customer Email Field (Required)":["Klant e-mailveld (verplicht)"],"Select the email field that contains the customer email":["Selecteer het e-mailveld dat het e-mailadres van de klant bevat"],"Payment":["Betaling"],"%s - Order ID":["%s - Bestel-ID"],"%s - Amount":["%s - Bedrag"],"%s - Customer Email":["%s - Klant e-mail"],"%s - Customer Name":["%s - Klantnaam"],"%s - Status":["%s - Status"],"Button Alignment":["Knopuitlijning"],"Placeholder":["Placeholder"],"Preselect this option":["Selecteer deze optie vooraf"],"Restrict Country Codes":["Beperk landcodes"],"Restriction Type":["Beperkingstype"],"Allow":["Toestaan"],"Block":["Blok"],"Select Allowed Countries":["Selecteer Toegestane Landen"],"Choose countries\u2026":["Kies landen\u2026"],"Choose which country codes users can select in the phone number field. Leave empty to allow all country codes.":["Kies welke landcodes gebruikers kunnen selecteren in het telefoonnummer veld. Laat leeg om alle landcodes toe te staan."],"Select Blocked Countries":["Selecteer geblokkeerde landen"],"These countries will be hidden from the dropdown.":["Deze landen worden verborgen in de dropdown."],"Bulk Edit":["Bulk bewerken"],"Select Layout":["Selecteer indeling"],"Number of Columns":["Aantal kolommen"],"Validation Message for Duplicate":["Validatiebericht voor duplicaat"],"Click here to insert a form":["Klik hier om een formulier in te voegen"],"Inherit Form's Original Style":["De oorspronkelijke stijl van het formulier overnemen"],"Text on Primary":["Tekst op primair"],"%s - Description":["%s - Beschrijving"],"Upgrade to Unlock":["Upgrade om te ontgrendelen"],"Custom (Premium)":["Aangepast (Premium)"],"Select a theme style for this form embed.":["Selecteer een themastijl voor deze formulierinsluiting."],"Colors":["Kleuren"],"Advanced Styling":["Geavanceerde styling"],"Unlock Custom Styling":["Aangepaste styling ontgrendelen"],"Switch to Custom Mode to take full control of your form's design and spacing.":["Schakel over naar Aangepaste Modus om volledige controle te krijgen over het ontwerp en de ruimte van uw formulier."],"Full color control (buttons, fields, text)":["Volledige kleurcontrole (knoppen, velden, tekst)"],"Row and column gap control":["Regel de rij- en kolomafstand"],"Field spacing and layout precision":["Veldafstand en lay-outprecisie"],"Complete button styling":["Voltooi knopstijl"],"Payment Description":["Betalingsomschrijving"],"Shown on payment receipts and in your payment dashboard (Stripe and PayPal). Leave blank to use the default.":["Weergegeven op betalingsbewijzen en in uw betalingsdashboard (Stripe en PayPal). Laat leeg om de standaard te gebruiken."],"Slug":["Naaktslak"],"Auto-generated on save":["Automatisch gegenereerd bij opslaan"],"This slug is already used by another field. It will revert to the previous value.":["Deze slug wordt al gebruikt door een ander veld. Het zal terugkeren naar de vorige waarde."],"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.":["Het wijzigen van de slug kan ervoor zorgen dat formulierinzendingen, voorwaardelijke logica, integraties of andere functies die momenteel naar deze slug verwijzen, niet meer werken. U moet al deze verwijzingen handmatig bijwerken."],"Field Slug":["Veld Slug"],"Location Services":["Locatiediensten"],"Unlock Address Autocomplete":["Adres automatisch aanvullen ontgrendelen"],"Upgrade to enable Google Address Autocomplete with interactive map preview, making address entry faster and more accurate for your users.":["Upgrade om Google Address Autocomplete met interactieve kaartvoorvertoning in te schakelen, waardoor het invoeren van adressen sneller en nauwkeuriger wordt voor uw gebruikers."],"Enable Google Autocomplete":["Google Autocomplete inschakelen"],"Show Interactive Map":["Interactieve kaart weergeven"],"Payments Per Page":["Betalingen Per Pagina"],"Show Subscriptions Section":["Abonnementssectie weergeven"],"Show a dedicated subscriptions section above payment history.":["Toon een speciale abonnementssectie boven de betalingsgeschiedenis."],"Payment Dashboard":["Betalingsdashboard"],"View your payments and manage subscriptions in a single dashboard.":["Bekijk uw betalingen en beheer abonnementen in \u00e9\u00e9n dashboard."],"Dynamic Default Value":["Dynamische Standaardwaarde"]}}} \ No newline at end of file +{"translation-revision-date":"2024-12-13T12:33:48+00:00","generator":"WP-CLI\/2.12.0","source":"assets\/build\/blocks.js","domain":"messages","locale_data":{"messages":{"":{"domain":"messages","lang":"en","plural-forms":"nplurals=2; plural=(n != 1);"},"Settings":["Instellingen"],"Search":["Zoeken"],"Fields":["Velden"],"Image":["Afbeelding"],"Submit":["Indienen"],"Required":["Vereist"],"Form Title":["Formuliertitel"],"Show":["Tonen"],"Hide":["Verbergen"],"Edit Form":["Formulier bewerken"],"Icon":["Icoon"],"Desktop":["Bureaublad"],"Medium":["Middelgroot"],"Mobile":["Mobiel"],"Repeat":["Herhaal"],"Scroll":["Scrollen"],"Tablet":["Tablet"],"Basic":["Basis"],"(no title)":["(geen titel)"],"Select a Form":["Selecteer een formulier"],"No forms found\u2026":["Geen formulieren gevonden\u2026"],"Choose":["Kies"],"Create New":["Nieuw maken"],"Change Form":["Formulier wijzigen"],"This form has been deleted or is unavailable.":["Dit formulier is verwijderd of is niet beschikbaar."],"Form Settings":["Formulierinstellingen"],"Show Form Title on this Page":["Toon formulier titel op deze pagina"],"Note: For editing SureForms, please refer to the SureForms Editor - ":["Opmerking: Voor het bewerken van SureForms, raadpleeg de SureForms Editor -"],"Field preview":["Veldvoorbeeld"],"General":["Algemeen"],"Style":["Stijl"],"Advanced":["Geavanceerd"],"No tags available":["Geen tags beschikbaar"],"Device":["Apparaat"],"Select Shortcodes":["Selecteer shortcodes"],"Page Break Label":["Pagina-einde label"],"Next":["Volgende"],"Back":["Terug"],"Reset":["Resetten"],"Generic tags":["Algemene tags"],"Pixel":["Pixel"],"Em":["Em"],"Select Units":["Selecteer eenheden"],"%s units":["%s eenheden"],"Margin":["Marge"],"Attributes":["Kenmerken"],"Input Pattern":["Invoermuster"],"None":["Geen"],"(###) ###-####":["(###) ###-####"],"(##) ####-####":["(##) ####-####"],"27\/08\/2024":["27\/08\/2024"],"23:59:59":["23:59:59"],"27\/08\/2024 23:59:59":["27\/08\/2024 23:59:59"],"Custom":["Aangepast"],"Custom Mask":["Aangepast masker"],"Please check the documentation to manage custom input pattern ":["Controleer de documentatie om het aangepaste invoerpatroon te beheren"],"here":["hier"],"Default Value":["Standaardwaarde"],"Error Message":["Foutmelding"],"Help Text":["Helptekst"],"Number Format":["Getalnotatie"],"US Style (Eg: 9,999.99)":["VS-stijl (Bijv: 9.999,99)"],"EU Style (Eg: 9.999,99)":["EU-stijl (Bijv: 9.999,99)"],"Minimum Value":["Minimumwaarde"],"Maximum Value":["Maximale waarde"],"Please check the Minimum and Maximum value":["Controleer de minimum- en maximumwaarde"],"Enable Email Confirmation":["E-mailbevestiging inschakelen"],"Checked by Default":["Standaard aangevinkt"],"Error message":["Foutmelding"],"Checked by default":["Standaard aangevinkt"],"Please add a option props to MultiButtonsControl":["Voeg alstublieft een optie-eigenschap toe aan MultiButtonsControl"],"Icon Library":["Iconenbibliotheek"],"Close":["Sluiten"],"All Icons":["Alle pictogrammen"],"Other":["Anders"],"No Icons Found":["Geen pictogrammen gevonden"],"Insert Icon":["Pictogram invoegen"],"Change Icon":["Pictogram wijzigen"],"Choose Icon":["Kies pictogram"],"Confirm":["Bevestigen"],"Cancel":["Annuleren"],"Processing\u2026":["Bezig met verwerken\u2026"],"Select Video":["Selecteer video"],"Change Video":["Video wijzigen"],"Select Lottie Animation":["Selecteer Lottie-animatie"],"Change Lottie Animation":["Wijzig Lottie-animatie"],"Upload SVG":["SVG uploaden"],"Change SVG":["SVG wijzigen"],"Select Image":["Selecteer afbeelding"],"Change Image":["Afbeelding wijzigen"],"Upload SVG?":["SVG uploaden?"],"Upload SVG can be potentially risky. Are you sure?":["Het uploaden van SVG kan potentieel riskant zijn. Weet je het zeker?"],"Upload Anyway":["Toch uploaden"],"Bulk Add":["Bulk toevoegen"],"Bulk Add Options":["Bulkopties toevoegen"],"Enter each option on a new line.":["Voer elke optie op een nieuwe regel in."],"Insert Options":["Opties invoegen"],"Full Width":["Volledige breedte"],"Option Type":["Optietype"],"Edit Options":["Bewerk opties"],"Add New Option":["Nieuwe optie toevoegen"],"ADD":["TOEVOEGEN"],"Enable Auto Country Detection":["Automatische landdetectie inschakelen"],"%s Width":["%s Breedte"],"Upgrade":["Upgrade"],"Clear":["Duidelijk"],"Select Color":["Selecteer kleur"],"Primary Color":["Primaire kleur"],"Text Color":["Tekstkleur"],"Field Spacing":["Veldafstand"],"Small":["Klein"],"Large":["Groot"],"Left":["Links"],"Center":["Centrum"],"Right":["Rechts"],"Color":["Kleur"],"Background Color":["Achtergrondkleur"],"Auto":["Auto"],"Default":["Standaard"],"Normal":["Normaal"],"%":["%"],"Top":["Top"],"Bottom":["Onderkant"],"Width":["Breedte"],"Size":["Grootte"],"EM":["EM"],"Padding":["Opvulling"],"Color 1":["Kleur 1"],"Color 2":["Kleur 2"],"Type":["Type"],"Linear":["Lineair"],"Radial":["Radiaal"],"Location 1":["Locatie 1"],"Location 2":["Locatie 2"],"Angle":["Hoek"],"Classic":["Klassiek"],"Gradient":["Gradi\u00ebnt"],"Horizontal":["Horizontaal"],"Vertical":["Verticaal"],"Background":["Achtergrond"],"Cover":["Omslag"],"Contain":["Bevatten"],"Layout":["Indeling"],"Overlay":["Overlay"],"No Repeat":["Geen herhaling"],"Overlay Opacity":["Overlay-opaciteit"],"Conditional Logic":["Conditionele logica"],"Upgrade to the SureForms Starter Plan to create dynamic forms that adapt based on user input, offering a personalised and efficient form experience.":["Upgrade naar het SureForms Starter Plan om dynamische formulieren te maken die zich aanpassen op basis van gebruikersinvoer, en zo een gepersonaliseerde en effici\u00ebnte formulierervaring bieden."],"Enable Conditional Logic":["Voorwaardelijke logica inschakelen"],"this field if":["dit veld indien"],"Configure Conditions":["Voorwaarden configureren"],"Premium":["Premium"],"Overlay Type":["Overlaytype"],"Image Overlay Color":["Afbeelding Overlay Kleur"],"Image Position":["Afbeeldingspositie"],"Attachment":["Bijlage"],"Fixed":["Vast"],"Blend Mode":["Overvloeimodus"],"Multiply":["Vermenigvuldigen"],"Screen":["Scherm"],"Darken":["Verduisteren"],"Lighten":["Verlichten"],"Color Dodge":["Kleur Dodge"],"Saturation":["Verzadiging"],"Repeat-x":["Herhaal-x"],"Repeat-y":["Herhaal-y"],"PX":["PX"],"Button":["Knop"],"Prefix Label":["Voorvoegsel Label"],"Suffix Label":["Achtervoegsel Label"],"Border Radius":["Randstraal"],"Form Theme":["Formulier Thema"],"Select Gradient":["Selecteer verloop"],"Unlock Conditional Logic Editor":["Ontgrendel de voorwaardelijke logica-editor"],"Rich Text Editor":["Rich Text Editor"],"Read Only":["Alleen lezen"],"Select Country":["Selecteer land"],"Default Country":["Standaardland"],"Subscription":["Abonnement"],"One Time":["E\u00e9n keer"],"Unique Entry":["Unieke invoer"],"Maximum Characters":["Maximale tekens"],"Textarea Height":["Hoogte van tekstvak"],"Minimum Selections":["Minimale selecties"],"Maximum Selections":["Maximale selecties"],"Add Numeric Values to Options":["Numerieke waarden aan opties toevoegen"],"Single Choice Only":["Enkel \u00e9\u00e9n keuze"],"Enable Dropdown Search":["Dropdown zoeken inschakelen"],"Allow Multiple":["Meerdere toestaan"],"%1$s fields are required. Please configure these fields in the block settings.":["%1$s velden zijn verplicht. Configureer deze velden in de blokinstellingen."],"%1$s field is required. Please configure this field in the block settings.":["%1$s veld is verplicht. Configureer dit veld in de blokinstellingen."],"You need to configure a payment account to collect payments from this form. Please configure your payment provider to proceed.":["U moet een betaalrekening configureren om betalingen van dit formulier te innen. Configureer uw betalingsprovider om door te gaan."],"Configure Payment Account":["Betaalrekening configureren"],"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.":["Dit is een tijdelijke aanduiding voor het betalingsblok. De daadwerkelijke betalingsvelden voor uw geconfigureerde betalingsprovider(s) verschijnen alleen wanneer u het formulier bekijkt of publiceert."],"2 Payments":["2 Betalingen"],"3 Payments":["3 Betalingen"],"4 Payments":["4 Betalingen"],"5 Payments":["5 Betalingen"],"Never":["Nooit"],"Stop Subscription After":["Abonnement Stoppen Na"],"Choose when to automatically stop the subscription":["Kies wanneer het abonnement automatisch moet worden stopgezet"],"Number of Payments":["Aantal betalingen"],"Enter a number between 1 to 100":["Voer een getal in tussen 1 en 100"],"Form Field":["Formulier Veld"],"Payment Type":["Betalingstype"],"Subscription Plan Name":["Abonnementsplan Naam"],"Billing Interval":["Factureringsinterval"],"Daily":["Dagelijks"],"Weekly":["Wekelijks"],"Monthly":["Maandelijks"],"Quarterly":["Per kwartaal"],"Yearly":["Jaarlijks"],"Amount Type":["Bedragstype"],"Fixed Amount":["Vast Bedrag"],"Dynamic Amount":["Dynamisch Bedrag"],"Choose whether to charge a fixed amount or charge the amount based on user input in other form fields.":["Kies of u een vast bedrag wilt rekenen of het bedrag wilt berekenen op basis van gebruikersinvoer in andere formuliervelden."],"Set the exact amount you want to charge. Users won\u2019t be able to change it":["Stel het exacte bedrag in dat u wilt berekenen. Gebruikers kunnen het niet wijzigen"],"Choose Amount Field":["Kies bedragveld"],"Select a field\u2026":["Selecteer een veld\u2026"],"Minimum Amount":["Minimumbedrag"],"Set the minimum amount users can enter (0 for no minimum)":["Stel het minimale bedrag in dat gebruikers kunnen invoeren (0 voor geen minimum)"],"Customer Name Field (Required)":["Klantnaamveld (Verplicht)"],"Customer Name Field (Optional)":["Klantnaamveld (Optioneel)"],"Select the input field that contains the customer name (Required for subscriptions)":["Selecteer het invoerveld dat de klantnaam bevat (Vereist voor abonnementen)"],"Select the input field that contains the customer name":["Selecteer het invoerveld dat de klantnaam bevat"],"Customer Email Field (Required)":["Klant e-mailveld (verplicht)"],"Select the email field that contains the customer email":["Selecteer het e-mailveld dat het e-mailadres van de klant bevat"],"Payment":["Betaling"],"%s - Order ID":["%s - Bestel-ID"],"%s - Amount":["%s - Bedrag"],"%s - Customer Email":["%s - Klant e-mail"],"%s - Customer Name":["%s - Klantnaam"],"%s - Status":["%s - Status"],"Button Alignment":["Knopuitlijning"],"Placeholder":["Placeholder"],"Preselect this option":["Selecteer deze optie vooraf"],"Restrict Country Codes":["Beperk landcodes"],"Restriction Type":["Beperkingstype"],"Allow":["Toestaan"],"Block":["Blok"],"Select Allowed Countries":["Selecteer Toegestane Landen"],"Choose countries\u2026":["Kies landen\u2026"],"Choose which country codes users can select in the phone number field. Leave empty to allow all country codes.":["Kies welke landcodes gebruikers kunnen selecteren in het telefoonnummer veld. Laat leeg om alle landcodes toe te staan."],"Select Blocked Countries":["Selecteer geblokkeerde landen"],"These countries will be hidden from the dropdown.":["Deze landen worden verborgen in de dropdown."],"Bulk Edit":["Bulk bewerken"],"Select Layout":["Selecteer indeling"],"Number of Columns":["Aantal kolommen"],"Validation Message for Duplicate":["Validatiebericht voor duplicaat"],"Click here to insert a form":["Klik hier om een formulier in te voegen"],"Inherit Form's Original Style":["De oorspronkelijke stijl van het formulier overnemen"],"Text on Primary":["Tekst op primair"],"%s - Description":["%s - Beschrijving"],"Upgrade to Unlock":["Upgrade om te ontgrendelen"],"Custom (Premium)":["Aangepast (Premium)"],"Select a theme style for this form embed.":["Selecteer een themastijl voor deze formulierinsluiting."],"Colors":["Kleuren"],"Advanced Styling":["Geavanceerde styling"],"Unlock Custom Styling":["Aangepaste styling ontgrendelen"],"Switch to Custom Mode to take full control of your form's design and spacing.":["Schakel over naar Aangepaste Modus om volledige controle te krijgen over het ontwerp en de ruimte van uw formulier."],"Full color control (buttons, fields, text)":["Volledige kleurcontrole (knoppen, velden, tekst)"],"Row and column gap control":["Regel de rij- en kolomafstand"],"Field spacing and layout precision":["Veldafstand en lay-outprecisie"],"Complete button styling":["Voltooi knopstijl"],"Payment Description":["Betalingsomschrijving"],"Shown on payment receipts and in your payment dashboard (Stripe and PayPal). Leave blank to use the default.":["Weergegeven op betalingsbewijzen en in uw betalingsdashboard (Stripe en PayPal). Laat leeg om de standaard te gebruiken."],"Slug":["Naaktslak"],"Auto-generated on save":["Automatisch gegenereerd bij opslaan"],"This slug is already used by another field. It will revert to the previous value.":["Deze slug wordt al gebruikt door een ander veld. Het zal terugkeren naar de vorige waarde."],"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.":["Het wijzigen van de slug kan ervoor zorgen dat formulierinzendingen, voorwaardelijke logica, integraties of andere functies die momenteel naar deze slug verwijzen, niet meer werken. U moet al deze verwijzingen handmatig bijwerken."],"Field Slug":["Veld Slug"],"Location Services":["Locatiediensten"],"Unlock Address Autocomplete":["Adres automatisch aanvullen ontgrendelen"],"Upgrade to enable Google Address Autocomplete with interactive map preview, making address entry faster and more accurate for your users.":["Upgrade om Google Address Autocomplete met interactieve kaartvoorvertoning in te schakelen, waardoor het invoeren van adressen sneller en nauwkeuriger wordt voor uw gebruikers."],"Enable Google Autocomplete":["Google Autocomplete inschakelen"],"Show Interactive Map":["Interactieve kaart weergeven"],"Payments Per Page":["Betalingen Per Pagina"],"Show Subscriptions Section":["Abonnementssectie weergeven"],"Show a dedicated subscriptions section above payment history.":["Toon een speciale abonnementssectie boven de betalingsgeschiedenis."],"Payment Dashboard":["Betalingsdashboard"],"View your payments and manage subscriptions in a single dashboard.":["Bekijk uw betalingen en beheer abonnementen in \u00e9\u00e9n dashboard."],"Dynamic Default Value":["Dynamische Standaardwaarde"],"Minimum Characters":["Minimale tekens"],"Minimum characters cannot exceed Maximum characters.":["Minimumtekens kunnen niet groter zijn dan maximumtekens."],"Both":["Beide"],"One-Time Label":["Eenmalig label"],"Label shown to users for the one-time payment option.":["Label getoond aan gebruikers voor de eenmalige betalingsoptie."],"Subscription Label":["Abonnementslabel"],"Label shown to users for the subscription option.":["Label getoond aan gebruikers voor de abonnementsoptie."],"Default Selection":["Standaardselectie"],"Which option is pre-selected when the form loads.":["Welke optie is vooraf geselecteerd wanneer het formulier wordt geladen."],"One-Time Amount Type":["Eenmalig Bedragstype"],"Set how the one-time payment amount is determined.":["Stel in hoe het bedrag van de eenmalige betaling wordt bepaald."],"One-Time Fixed Amount":["Eenmalig vast bedrag"],"Amount charged for a one-time payment.":["Bedrag in rekening gebracht voor een eenmalige betaling."],"One-Time Amount Field":["Eenmalig Bedrag Veld"],"Pick a form field whose value determines the one-time payment amount.":["Kies een formulier veld waarvan de waarde het eenmalige betalingsbedrag bepaalt."],"One-Time Minimum Amount":["Eenmalig Minimum Bedrag"],"Minimum amount users can enter for one-time payment (0 for no minimum).":["Minimumbedrag dat gebruikers kunnen invoeren voor een eenmalige betaling (0 voor geen minimum)."],"Subscription Amount Type":["Type abonnementsbedrag"],"Set how the subscription amount is determined.":["Stel in hoe het abonnementsbedrag wordt bepaald."],"Subscription Fixed Amount":["Vast bedrag voor abonnement"],"Recurring amount charged per billing interval.":["Terugkerend bedrag dat per factureringsinterval in rekening wordt gebracht."],"Subscription Amount Field":["Veld Abonnementsbedrag"],"Pick a form field whose value determines the subscription amount.":["Kies een formulier veld waarvan de waarde het abonnementsbedrag bepaalt."],"Subscription Minimum Amount":["Minimumbedrag voor abonnement"],"Minimum amount users can enter for subscription (0 for no minimum).":["Minimumbedrag dat gebruikers kunnen invoeren voor abonnement (0 voor geen minimum)."],"Pick a field from your form like a number, dropdown, multichoice, or hidden whose value should decide the payment amount.":["Kies een veld uit uw formulier, zoals een nummer, dropdown, meerkeuze of verborgen veld, waarvan de waarde het betalingsbedrag moet bepalen."]}}} \ No newline at end of file diff --git a/languages/sureforms-nl_NL.mo b/languages/sureforms-nl_NL.mo index 7a8292f14..6f444983f 100644 Binary files a/languages/sureforms-nl_NL.mo and b/languages/sureforms-nl_NL.mo differ diff --git a/languages/sureforms-nl_NL.po b/languages/sureforms-nl_NL.po index 224cd9705..23c6f139c 100644 --- a/languages/sureforms-nl_NL.po +++ b/languages/sureforms-nl_NL.po @@ -106,13 +106,13 @@ msgstr "Bewerk %1$s" #: inc/ai-form-builder/ai-auth.php:93 #: inc/ai-form-builder/ai-auth.php:167 #: inc/background-process.php:112 -#: inc/create-new-form.php:101 +#: inc/create-new-form.php:102 #: inc/duplicate-form.php:176 #: inc/export.php:118 #: inc/export.php:176 #: inc/forms-data.php:88 #: inc/global-settings/global-settings.php:86 -#: inc/global-settings/global-settings.php:403 +#: inc/global-settings/global-settings.php:404 #: inc/rest-api.php:177 msgid "Nonce verification failed." msgstr "Verificatie van nonce mislukt." @@ -377,7 +377,7 @@ msgid "Selected radio option" msgstr "Geselecteerde radio-optie" #: inc/admin-ajax.php:341 -#: inc/create-new-form.php:63 +#: inc/create-new-form.php:64 #: assets/build/blocks.js:172 #: assets/build/formEditor.js:172 msgid "Submit" @@ -416,53 +416,53 @@ msgid "The message array was not supplied" msgstr "De berichtenreeks werd niet geleverd" #: inc/ai-form-builder/ai-form-builder.php:68 -#: inc/ai-form-builder/ai-form-builder.php:78 -#: inc/ai-form-builder/ai-helper.php:73 +#: inc/ai-form-builder/ai-form-builder.php:87 +#: inc/ai-form-builder/ai-helper.php:294 msgid "The SureForms AI Middleware encountered an error." msgstr "De SureForms AI Middleware heeft een fout ondervonden." -#: inc/ai-form-builder/ai-helper.php:95 +#: inc/ai-form-builder/ai-helper.php:91 msgid "Unable to get usage response." msgstr "Kan geen gebruiksantwoord krijgen." -#: inc/ai-form-builder/ai-helper.php:148 +#: inc/ai-form-builder/ai-helper.php:145 msgid "The SureForms API server encountered an error." msgstr "De SureForms API-server heeft een fout ondervonden." -#: inc/ai-form-builder/ai-helper.php:174 -#: inc/ai-form-builder/ai-helper.php:206 +#: inc/ai-form-builder/ai-helper.php:167 +#: inc/ai-form-builder/ai-helper.php:199 msgid "An unknown error occurred." msgstr "Er is een onbekende fout opgetreden." -#: inc/ai-form-builder/ai-helper.php:181 +#: inc/ai-form-builder/ai-helper.php:174 msgid "HTTP Request Failed" msgstr "HTTP-verzoek mislukt" -#: inc/ai-form-builder/ai-helper.php:185 +#: inc/ai-form-builder/ai-helper.php:178 msgid "License Verification Failed" msgstr "Licentiecontrole mislukt" -#: inc/ai-form-builder/ai-helper.php:189 +#: inc/ai-form-builder/ai-helper.php:182 msgid "User Verification Failed" msgstr "Gebruikersverificatie mislukt" -#: inc/ai-form-builder/ai-helper.php:193 +#: inc/ai-form-builder/ai-helper.php:186 msgid "Referer Mismatch" msgstr "Referer komt niet overeen" -#: inc/ai-form-builder/ai-helper.php:197 +#: inc/ai-form-builder/ai-helper.php:190 msgid "Invalid Website URL" msgstr "Ongeldige website-URL" -#: inc/ai-form-builder/ai-helper.php:198 +#: inc/ai-form-builder/ai-helper.php:191 msgid "AI Form Builder does not work on localhost. Please try on a live website." msgstr "AI Form Builder werkt niet op localhost. Probeer het alstublieft op een live website." -#: inc/ai-form-builder/ai-helper.php:201 +#: inc/ai-form-builder/ai-helper.php:194 msgid "Domain Verification Failed" msgstr "Domeinverificatie mislukt" -#: inc/ai-form-builder/ai-helper.php:205 +#: inc/ai-form-builder/ai-helper.php:198 msgid "Unknown Error" msgstr "Onbekende fout" @@ -470,22 +470,18 @@ msgstr "Onbekende fout" msgid "Submission id missing." msgstr "Inzendings-ID ontbreekt." -#: inc/create-new-form.php:113 +#: inc/create-new-form.php:114 msgid "Invalid JSON format." msgstr "Ongeldig JSON-formaat." -#: inc/create-new-form.php:125 +#: inc/create-new-form.php:126 msgid "Missing required properties in form info." msgstr "Ontbrekende vereiste eigenschappen in formulierinformatie." -#: inc/create-new-form.php:161 +#: inc/create-new-form.php:187 msgid "SureForms Form created successfully." msgstr "SureForms-formulier succesvol aangemaakt." -#: inc/create-new-form.php:168 -msgid "Error creating SureForms Form, " -msgstr "Fout bij het maken van SureForms-formulier," - #: inc/email/email-template.php:46 msgid "New form submission" msgstr "Nieuwe formulierinzending" @@ -547,7 +543,7 @@ msgstr "Nummer" msgid "Phone" msgstr "Telefoon" -#: inc/fields/textarea-markup.php:95 +#: inc/fields/textarea-markup.php:111 msgid "Textarea" msgstr "Tekstvak" @@ -590,8 +586,8 @@ msgstr "Geen formulieren gevonden." #: inc/abilities/settings/get-global-settings.php:192 #: inc/global-settings/email-summary.php:571 -#: inc/global-settings/global-settings.php:250 -#: inc/global-settings/global-settings.php:456 +#: inc/global-settings/global-settings.php:251 +#: inc/global-settings/global-settings.php:457 #: assets/build/settings.js:172 msgid "Monday" msgstr "Maandag" @@ -6994,7 +6990,7 @@ msgstr "Street View" msgid "Strikethrough" msgstr "Doorhalen" -#: inc/fields/payment-markup.php:412 +#: inc/fields/payment-markup.php:513 #: modules/gutenberg/icons/icons-v6-3.php:1812 #: assets/build/payments.js:172 msgid "Stripe" @@ -11593,6 +11589,7 @@ msgstr "Bouw je eerste formulier" msgid "Invalid nonce action or name." msgstr "Ongeldige nonce-actie of naam." +#: inc/admin/editor-nudge.php:216 #: inc/helper.php:2029 #: inc/helper.php:2037 msgid "Invalid security token." @@ -11776,7 +11773,7 @@ msgstr "Verken SureDash" msgid "Something went wrong. We have logged the error for further investigation" msgstr "Er is iets misgegaan. We hebben de fout geregistreerd voor verder onderzoek." -#: inc/field-validation.php:273 +#: inc/field-validation.php:276 msgid "Field is not valid." msgstr "Veld is niet geldig." @@ -11934,82 +11931,82 @@ msgstr "Geen formuliergegevens verstrekt voor import." msgid "Invalid form data structure provided." msgstr "Ongeldige gegevensstructuur van het formulier verstrekt." -#: inc/fields/payment-markup.php:249 +#: inc/fields/payment-markup.php:346 #: inc/payments/payment-helper.php:543 msgid "Subscription Plan" msgstr "Abonnementsplan" #. translators: 1: Amount with currency, 2: Interval (day/week/month/quarter/year) -#: inc/fields/payment-markup.php:288 +#: inc/fields/payment-markup.php:672 #, php-format msgid "%1$s per %2$s (until cancelled)" msgstr "%1$s per %2$s (totdat geannuleerd)" #. translators: 1: Amount with currency, 2: Interval (day/week/month/quarter/year), 3: Number of billing cycles -#: inc/fields/payment-markup.php:297 +#: inc/fields/payment-markup.php:681 #, php-format msgid "%1$s per %2$s (%3$s payments)" msgstr "%1$s per %2$s (%3$s betalingen)" #. translators: 1: Amount with currency, 2: Interval (day/week/month/quarter/year) -#: inc/fields/payment-markup.php:307 +#: inc/fields/payment-markup.php:691 #, php-format msgid "%1$s per %2$s" msgstr "%1$s per %2$s" #. translators: 1: Amount with currency placeholder, 2: Interval (day/week/month/quarter/year) -#: inc/fields/payment-markup.php:334 +#: inc/fields/payment-markup.php:714 #, php-format msgid "{amount} per %s (until cancelled)" msgstr "{amount} per %s (tot annulering)" #. translators: 1: Amount with currency placeholder, 2: Interval (day/week/month/quarter/year), 3: Number of billing cycles -#: inc/fields/payment-markup.php:337 +#: inc/fields/payment-markup.php:717 #, php-format msgid "{amount} per %1$s (%2$s payments)" msgstr "{amount} per %1$s (%2$s betalingen)" #. translators: 1: Amount with currency placeholder, 2: Interval (day/week/month/quarter/year) -#: inc/fields/payment-markup.php:340 +#: inc/fields/payment-markup.php:720 #, php-format msgid "{amount} per %s" msgstr "{amount} per %s" #. translators: %s: Minimum amount with currency -#: inc/fields/payment-markup.php:353 +#: inc/fields/payment-markup.php:740 #, php-format msgid "Minimum amount: %s" msgstr "Minimumbedrag: %s" -#: inc/fields/payment-markup.php:385 +#: inc/fields/payment-markup.php:486 msgid "Processing payment..." msgstr "Betaling verwerken..." -#: inc/fields/payment-markup.php:579 +#: inc/fields/payment-markup.php:906 msgid "day" msgstr "dag" -#: inc/fields/payment-markup.php:580 +#: inc/fields/payment-markup.php:907 msgid "week" msgstr "week" -#: inc/fields/payment-markup.php:581 +#: inc/fields/payment-markup.php:908 msgid "month" msgstr "maand" -#: inc/fields/payment-markup.php:582 +#: inc/fields/payment-markup.php:909 msgid "quarter" msgstr "kwart" -#: inc/fields/payment-markup.php:583 +#: inc/fields/payment-markup.php:910 msgid "year" msgstr "jaar" -#: inc/fields/payment-markup.php:608 +#: inc/fields/payment-markup.php:935 msgid "Test mode is enabled:" msgstr "Testmodus is ingeschakeld:" -#: inc/fields/payment-markup.php:610 +#: inc/fields/payment-markup.php:937 msgid "Click here to enable live mode and accept payment" msgstr "Klik hier om de live modus in te schakelen en betaling te accepteren" @@ -12192,6 +12189,7 @@ msgstr "Onbekend formulier" msgid "N/A" msgstr "N.v.t." +#: inc/fields/payment-markup.php:247 #: inc/payments/admin/admin-handler.php:975 #: inc/payments/payment-history-shortcode.php:306 #: assets/build/blocks.js:172 @@ -12220,21 +12218,21 @@ msgstr "Onbekend" #: inc/payments/admin/admin-handler.php:1468 #: inc/payments/admin/admin-handler.php:1472 #: inc/payments/admin/admin-handler.php:1476 -#: inc/payments/front-end.php:811 -#: inc/payments/front-end.php:1209 +#: inc/payments/front-end.php:854 +#: inc/payments/front-end.php:1253 msgid "Guest User" msgstr "Gastgebruiker" -#: inc/payments/front-end.php:91 +#: inc/payments/front-end.php:92 msgid "Invalid payment amount." msgstr "Ongeldig betalingsbedrag." -#: inc/payments/front-end.php:107 +#: inc/payments/front-end.php:109 msgid "Valid customer email is required for payments." msgstr "Een geldig klant-e-mailadres is vereist voor betalingen." -#: inc/payments/front-end.php:113 -#: inc/payments/front-end.php:320 +#: inc/payments/front-end.php:115 +#: inc/payments/front-end.php:340 #: inc/payments/stripe/admin-stripe-handler.php:877 #: inc/payments/stripe/payments-settings.php:349 #: inc/payments/stripe/payments-settings.php:474 @@ -12244,137 +12242,137 @@ msgstr "Een geldig klant-e-mailadres is vereist voor betalingen." msgid "Stripe is not connected." msgstr "Stripe is niet verbonden." -#: inc/payments/front-end.php:119 -#: inc/payments/front-end.php:326 -#: inc/payments/front-end.php:610 -#: inc/payments/front-end.php:1099 +#: inc/payments/front-end.php:121 +#: inc/payments/front-end.php:346 +#: inc/payments/front-end.php:634 +#: inc/payments/front-end.php:1142 msgid "Stripe secret key not found." msgstr "Stripe geheime sleutel niet gevonden." #. translators: %s: formatted payment amount -#: inc/payments/front-end.php:201 +#: inc/payments/front-end.php:203 #, php-format msgid "The payment amount (%s) is below the minimum allowed. Stripe only processes amounts above 50¢." msgstr "Het betalingsbedrag (%s) is lager dan het toegestane minimum. Stripe verwerkt alleen bedragen boven de 50¢." #. translators: %s: Field name -#: inc/payments/front-end.php:268 +#: inc/payments/front-end.php:273 #, php-format msgid "Missing required field: %s" msgstr "Ontbrekend verplicht veld: %s" -#: inc/payments/front-end.php:287 +#: inc/payments/front-end.php:292 msgid "Valid customer email is required for subscriptions." msgstr "Een geldig klant-e-mailadres is vereist voor abonnementen." -#: inc/payments/front-end.php:292 +#: inc/payments/front-end.php:297 msgid "Customer name is required for subscriptions." msgstr "Naam van de klant is vereist voor abonnementen." -#: inc/payments/front-end.php:308 +#: inc/payments/front-end.php:314 msgid "Amount must be greater than 0" msgstr "Bedrag moet groter zijn dan 0" -#: inc/payments/front-end.php:314 +#: inc/payments/front-end.php:322 msgid "Invalid billing interval" msgstr "Ongeldige factureringsinterval" -#: inc/payments/front-end.php:337 +#: inc/payments/front-end.php:357 msgid "Failed to create customer for subscription." msgstr "Het is niet gelukt om een klant aan te maken voor het abonnement." -#: inc/payments/front-end.php:370 -#: inc/payments/front-end.php:386 +#: inc/payments/front-end.php:390 +#: inc/payments/front-end.php:406 msgid "Failed to create subscription through middleware." msgstr "Het is niet gelukt om een abonnement via de middleware te maken." -#: inc/payments/front-end.php:391 +#: inc/payments/front-end.php:411 msgid "Empty response from subscription creation." msgstr "Lege reactie van abonnementscreatie." -#: inc/payments/front-end.php:396 +#: inc/payments/front-end.php:416 msgid "Invalid JSON response from subscription creation." msgstr "Ongeldige JSON-reactie van abonnementsaanmaak." -#: inc/payments/front-end.php:400 -#: inc/payments/front-end.php:404 +#: inc/payments/front-end.php:420 +#: inc/payments/front-end.php:424 msgid "Invalid subscription data." msgstr "Ongeldige abonnementsgegevens." -#: inc/payments/front-end.php:411 +#: inc/payments/front-end.php:431 msgid "Failed to create subscription." msgstr "Het is niet gelukt om het abonnement te maken." #. translators: %s: Error message -#: inc/payments/front-end.php:441 +#: inc/payments/front-end.php:464 #, php-format msgid "Unexpected error: %s" msgstr "Onverwachte fout: %s" -#: inc/payments/front-end.php:581 +#: inc/payments/front-end.php:604 #: inc/payments/stripe/admin-stripe-handler.php:103 #: inc/payments/stripe/admin-stripe-handler.php:184 #: inc/payments/stripe/admin-stripe-handler.php:489 msgid "Subscription ID not found." msgstr "Abonnement-ID niet gevonden." -#: inc/payments/front-end.php:599 +#: inc/payments/front-end.php:623 msgid "Customer ID not found for the payment." msgstr "Klant-ID niet gevonden voor de betaling." -#: inc/payments/front-end.php:627 +#: inc/payments/front-end.php:651 msgid "Failed to retrieve setup intent." msgstr "Het ophalen van de installatie-intentie is mislukt." -#: inc/payments/front-end.php:656 +#: inc/payments/front-end.php:699 msgid "Failed to update subscription." msgstr "Bijwerken van abonnement mislukt." -#: inc/payments/front-end.php:664 +#: inc/payments/front-end.php:707 msgid "Latest invoice not found on subscription." msgstr "Laatste factuur niet gevonden bij abonnement." -#: inc/payments/front-end.php:677 +#: inc/payments/front-end.php:720 msgid "Failed to retrieve invoice." msgstr "Het is niet gelukt om de factuur op te halen." -#: inc/payments/front-end.php:699 +#: inc/payments/front-end.php:742 msgid "Payment intent not found on invoice." msgstr "Betalingsintentie niet gevonden op factuur." -#: inc/payments/front-end.php:714 +#: inc/payments/front-end.php:757 msgid "Failed to confirm payment." msgstr "Betaling bevestigen is mislukt." -#: inc/payments/front-end.php:730 +#: inc/payments/front-end.php:773 msgid "Failed to retrieve subscription." msgstr "Ophalen van abonnement mislukt." -#: inc/payments/front-end.php:745 +#: inc/payments/front-end.php:788 msgid "Subscription not found for the payment." msgstr "Abonnement niet gevonden voor de betaling." #. translators: %d: User ID -#: inc/payments/front-end.php:809 -#: inc/payments/front-end.php:1209 +#: inc/payments/front-end.php:852 +#: inc/payments/front-end.php:1253 #, php-format msgid "User ID: %d" msgstr "Gebruikers-ID: %d" #. translators: %s: Invoice status -#: inc/payments/front-end.php:817 +#: inc/payments/front-end.php:860 #, php-format msgid "Invoice Status: %s" msgstr "Factuurstatus: %s" #. translators: Title for subscription verification log -#: inc/payments/front-end.php:824 +#: inc/payments/front-end.php:867 msgid "Subscription Verification" msgstr "Abonnementsverificatie" #. translators: %s: Subscription ID #. translators: %s: Stripe subscription ID -#: inc/payments/front-end.php:828 +#: inc/payments/front-end.php:871 #: inc/payments/stripe/admin-stripe-handler.php:119 #: inc/payments/stripe/admin-stripe-handler.php:204 #: inc/payments/stripe/admin-stripe-handler.php:505 @@ -12390,8 +12388,8 @@ msgstr "Abonnement-ID: %s" #. 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:830 -#: inc/payments/front-end.php:1220 +#: inc/payments/front-end.php:873 +#: inc/payments/front-end.php:1264 #: inc/payments/stripe/admin-stripe-handler.php:124 #: inc/payments/stripe/admin-stripe-handler.php:209 #: inc/payments/stripe/admin-stripe-handler.php:510 @@ -12406,13 +12404,13 @@ msgid "Payment Gateway: %s" msgstr "Betalingsgateway: %s" #. translators: %s: Payment Intent ID -#: inc/payments/front-end.php:832 +#: inc/payments/front-end.php:875 #, php-format msgid "Payment Intent ID: %s" msgstr "Betalingsintentie-ID: %s" #. translators: %s: Charge ID -#: inc/payments/front-end.php:834 +#: inc/payments/front-end.php:877 #: inc/payments/stripe/stripe-webhook.php:1048 #, php-format msgid "Charge ID: %s" @@ -12420,7 +12418,7 @@ msgstr "Betaal-ID: %s" #. translators: %s: Subscription Status #. translators: %s: subscription status -#: inc/payments/front-end.php:836 +#: inc/payments/front-end.php:879 #: inc/payments/stripe/admin-stripe-handler.php:129 #: inc/payments/stripe/admin-stripe-handler.php:214 #: inc/payments/stripe/admin-stripe-handler.php:515 @@ -12429,7 +12427,7 @@ msgid "Subscription Status: %s" msgstr "Abonnementsstatus: %s" #. translators: %s: Customer ID -#: inc/payments/front-end.php:838 +#: inc/payments/front-end.php:881 #: inc/payments/stripe/stripe-webhook.php:1122 #, php-format msgid "Customer ID: %s" @@ -12437,8 +12435,8 @@ msgstr "Klant-ID: %s" #. translators: 1: Amount, 2: Currency #. translators: %1$s: amount, %2$s: currency. -#: inc/payments/front-end.php:840 -#: inc/payments/front-end.php:1222 +#: inc/payments/front-end.php:883 +#: inc/payments/front-end.php:1266 #: inc/payments/stripe/stripe-webhook.php:1053 #: inc/payments/stripe/stripe-webhook.php:1114 #, php-format @@ -12447,34 +12445,34 @@ msgstr "Bedrag: %1$s %2$s" #. translators: %s: Payment mode (e.g. Live or Test) #. translators: %s: payment mode -#: inc/payments/front-end.php:843 -#: inc/payments/front-end.php:1227 +#: inc/payments/front-end.php:886 +#: inc/payments/front-end.php:1271 #, php-format msgid "Mode: %s" msgstr "Modus: %s" -#: inc/payments/front-end.php:877 +#: inc/payments/front-end.php:920 msgid "Failed to verify subscription." msgstr "Verificatie van abonnement mislukt." -#: inc/payments/front-end.php:1131 -#: inc/payments/front-end.php:1149 -#: inc/payments/front-end.php:1157 -#: inc/payments/front-end.php:1164 +#: inc/payments/front-end.php:1175 +#: inc/payments/front-end.php:1193 +#: inc/payments/front-end.php:1201 +#: inc/payments/front-end.php:1208 msgid "Failed to retrieve payment intent." msgstr "Het is niet gelukt om de betalingsintentie op te halen." -#: inc/payments/front-end.php:1172 +#: inc/payments/front-end.php:1216 msgid "Payment was not confirmed successfully." msgstr "Betaling werd niet succesvol bevestigd." -#: inc/payments/front-end.php:1214 +#: inc/payments/front-end.php:1258 msgid "Payment Verification" msgstr "Betalingsverificatie" #. translators: %s: Stripe transaction ID #. translators: %s: Charge ID -#: inc/payments/front-end.php:1218 +#: inc/payments/front-end.php:1262 #: inc/payments/stripe/stripe-webhook.php:1110 #, php-format msgid "Transaction ID: %s" @@ -12482,18 +12480,18 @@ msgstr "Transactie-ID: %s" #. translators: %s: payment status #. translators: %s: Status -#: inc/payments/front-end.php:1224 +#: inc/payments/front-end.php:1268 #: inc/payments/stripe/stripe-webhook.php:576 #: inc/payments/stripe/stripe-webhook.php:1116 #, php-format msgid "Status: %s" msgstr "Status: %s" -#: inc/payments/front-end.php:1330 +#: inc/payments/front-end.php:1374 msgid "Failed to create Stripe customer." msgstr "Het is niet gelukt om een Stripe-klant aan te maken." -#: inc/payments/front-end.php:1394 +#: inc/payments/front-end.php:1438 msgid "Failed to create Stripe guest customer." msgstr "Het is niet gelukt om een Stripe-gastklant aan te maken." @@ -12856,6 +12854,7 @@ msgstr "Onbekende fout" msgid "Missing payment ID." msgstr "Ontbrekend betalings-ID." +#: inc/admin/editor-nudge.php:209 #: inc/payments/stripe/admin-stripe-handler.php:84 #: inc/payments/stripe/admin-stripe-handler.php:470 msgid "You are not allowed to perform this action." @@ -13535,10 +13534,6 @@ msgstr "Kies bedragveld" msgid "Select a field…" msgstr "Selecteer een veld…" -#: assets/build/blocks.js:172 -msgid "Pick a field from your form like a number, dropdown, or multichoice whose value should decide the payment amount." -msgstr "Kies een veld uit uw formulier, zoals een nummer, dropdown of meerkeuze, waarvan de waarde het betalingsbedrag moet bepalen." - #: assets/build/blocks.js:172 msgid "Minimum Amount" msgstr "Minimumbedrag" @@ -14118,6 +14113,7 @@ msgstr "Gebruik AI om formulieren direct te genereren vanuit een eenvoudige prom msgid "Build engaging conversational, calculation, and multi-step forms." msgstr "Bouw boeiende conversatie-, berekenings- en meerstapsformulieren." +#: inc/admin/editor-nudge.php:192 #: assets/build/forms.js:172 msgid "Create Form" msgstr "Formulier maken" @@ -14976,76 +14972,78 @@ msgstr "Het opgegeven bericht is geen SureForms-formulier." msgid "Failed to create duplicate form." msgstr "Het is niet gelukt om een duplicaat van het formulier te maken." -#: inc/payments/front-end.php:97 -#: inc/payments/front-end.php:298 -#: inc/payments/payment-helper.php:594 +#: inc/payments/front-end.php:98 +#: inc/payments/front-end.php:303 +#: inc/payments/payment-helper.php:595 msgid "Invalid form configuration." msgstr "Ongeldige formulierconfiguratie." -#: inc/payments/payment-helper.php:602 +#: inc/payments/payment-helper.php:603 msgid "Payment configuration not found for this form." msgstr "Betalingsconfiguratie niet gevonden voor dit formulier." #. translators: 1: expected currency, 2: received currency -#: inc/payments/payment-helper.php:613 +#: inc/payments/payment-helper.php:614 #, php-format msgid "Currency mismatch: expected %1$s, received %2$s." msgstr "Valutaverschil: verwacht %1$s, ontvangen %2$s." #. translators: 1: expected amount with currency -#: inc/payments/payment-helper.php:630 +#: inc/payments/payment-helper.php:649 #, php-format msgid "Payment amount must be exactly %1$s." msgstr "Het betalingsbedrag moet exact %1$s zijn." #. translators: 1: minimum amount with currency -#: inc/payments/payment-helper.php:641 +#: inc/payments/payment-helper.php:660 #, php-format msgid "Payment amount must be at least %1$s." msgstr "Het betalingsbedrag moet minimaal %1$s zijn." -#: inc/payments/payment-helper.php:717 +#: inc/payments/payment-helper.php:737 msgid "Invalid payment verification parameters." msgstr "Ongeldige betalingsverificatieparameters." -#: inc/payments/payment-helper.php:728 +#: inc/payments/payment-helper.php:748 msgid "Payment verification failed. Invalid payment intent." msgstr "Betalingsverificatie mislukt. Ongeldige betalingsintentie." -#: inc/payments/payment-helper.php:814 -#: inc/payments/payment-helper.php:952 +#: inc/payments/payment-helper.php:903 +#: inc/payments/payment-helper.php:1043 msgid "Variable amount field configuration not found." msgstr "Configuratie van het veld voor variabele bedragen niet gevonden." -#: inc/payments/payment-helper.php:835 +#: inc/payments/payment-helper.php:924 msgid "No payment options are configured for this field." msgstr "Er zijn geen betalingsopties geconfigureerd voor dit veld." #. translators: %s: currency code -#: inc/payments/payment-helper.php:861 +#: inc/payments/payment-helper.php:950 msgid "Invalid payment amount. Please select a valid amount from the available options." msgstr "Ongeldig betalingsbedrag. Selecteer alstublieft een geldig bedrag uit de beschikbare opties." #. translators: %1$s: expected amount, %2$s: payment amount -#: inc/payments/payment-helper.php:896 +#: inc/payments/payment-helper.php:986 msgid "Payment configuration not found." msgstr "Betalingsconfiguratie niet gevonden." #. translators: %1$s: expected amount, %2$s: payment amount -#: inc/payments/payment-helper.php:912 -#: inc/payments/payment-helper.php:964 -#: inc/payments/payment-helper.php:1000 +#: inc/payments/payment-helper.php:1003 +#: inc/payments/payment-helper.php:1055 +#: inc/payments/payment-helper.php:1091 +#: inc/payments/payment-helper.php:1111 #, php-format msgid "Payment amount mismatch. Expected %1$s, received %2$s." msgstr "Betalingsbedrag komt niet overeen. Verwacht %1$s, ontvangen %2$s." -#: inc/payments/payment-helper.php:941 -#: inc/payments/payment-helper.php:991 +#: 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." msgstr "Waarde van het variabele bedrag veld is vereist." #. translators: %1$s: minimum amount, %2$s: payment amount -#: inc/payments/payment-helper.php:1012 +#: inc/payments/payment-helper.php:1125 #, php-format msgid "Payment amount below minimum. Minimum: %1$s, received %2$s." msgstr "Betalingsbedrag onder het minimum. Minimum: %1$s, ontvangen %2$s." @@ -15107,7 +15105,7 @@ msgstr "Er is een fout opgetreden bij het dupliceren van het formulier." msgid "This will create a copy of \"%s\" with all its settings." msgstr "Dit zal een kopie maken van \"%s\" met al zijn instellingen." -#: inc/fields/payment-markup.php:413 +#: inc/fields/payment-markup.php:514 msgid "Pay with credit or debit card" msgstr "Betalen met creditcard of betaalpas" @@ -15115,8 +15113,8 @@ msgstr "Betalen met creditcard of betaalpas" msgid "This form is not yet available. Please check back after the scheduled start time." msgstr "Dit formulier is nog niet beschikbaar. Kom na de geplande starttijd terug." -#: inc/form-restriction.php:165 -#: inc/form-restriction.php:166 +#: inc/form-restriction.php:187 +#: inc/form-restriction.php:188 #: assets/build/formEditor.js:172 msgid "This form is no longer accepting submissions. The submission period has ended." msgstr "Dit formulier accepteert geen inzendingen meer. De inzendperiode is afgelopen." @@ -15131,7 +15129,7 @@ msgstr "Betalingsgateway niet gevonden." msgid "Refund processing is not supported for %s gateway." msgstr "Terugbetalingsverwerking wordt niet ondersteund voor %s-gateway." -#: inc/payments/payment-helper.php:974 +#: inc/payments/payment-helper.php:1065 msgid "Number field configuration not found." msgstr "Configuratie van het nummer veld niet gevonden." @@ -15508,11 +15506,11 @@ msgstr "Formuliertitel is verplicht." msgid "At least one form field is required." msgstr "Er is ten minste één formulier veld vereist." -#: inc/abilities/forms/create-form.php:322 +#: inc/abilities/forms/create-form.php:326 msgid "Failed to generate form fields from the provided data." msgstr "Kan geen formuliervelden genereren uit de verstrekte gegevens." -#: inc/abilities/forms/create-form.php:372 +#: inc/abilities/forms/create-form.php:376 msgid "Failed to create the form." msgstr "Het is niet gelukt om het formulier te maken." @@ -15688,23 +15686,23 @@ msgstr "Authenticatiesessie verlopen. Probeer het opnieuw." msgid "Invalid access key format." msgstr "Ongeldig toegangssleutelformaat." -#: inc/ai-form-builder/ai-helper.php:182 +#: inc/ai-form-builder/ai-helper.php:175 msgid "Unable to connect to SureForms API. Please check your connection." msgstr "Kan geen verbinding maken met de SureForms API. Controleer uw verbinding." -#: inc/ai-form-builder/ai-helper.php:186 +#: inc/ai-form-builder/ai-helper.php:179 msgid "Unable to verify license. Please check your license key." msgstr "Kan licentie niet verifiëren. Controleer uw licentiesleutel." -#: inc/ai-form-builder/ai-helper.php:190 +#: inc/ai-form-builder/ai-helper.php:183 msgid "An error occurred while trying to verify your email. Please check your email you have used to log in or sign up on billing.sureforms.com." msgstr "Er is een fout opgetreden bij het proberen uw e-mail te verifiëren. Controleer de e-mail die u heeft gebruikt om in te loggen of aan te melden op billing.sureforms.com." -#: inc/ai-form-builder/ai-helper.php:194 +#: inc/ai-form-builder/ai-helper.php:187 msgid "Unable to verify referer. Please check your referer." msgstr "Kan referer niet verifiëren. Controleer uw referer." -#: inc/ai-form-builder/ai-helper.php:202 +#: inc/ai-form-builder/ai-helper.php:195 msgid "Domain Verification Failed on current site. Please try again on another website." msgstr "Domeinverificatie mislukt op de huidige site. Probeer het opnieuw op een andere website." @@ -15730,8 +15728,8 @@ msgstr "Ik geef toestemming aan deze website om mijn informatie op te slaan zoda msgid "Text field" msgstr "Tekstveld" -#: inc/form-restriction.php:160 -#: inc/form-restriction.php:161 +#: inc/form-restriction.php:182 +#: inc/form-restriction.php:183 #: inc/post-types.php:1203 #: inc/post-types.php:1243 msgid "This form is not yet available. Check back after the scheduled start time." @@ -15741,8 +15739,8 @@ msgstr "Dit formulier is nog niet beschikbaar. Kom terug na de geplande starttij #: inc/form-submit.php:400 #: inc/form-submit.php:445 #: inc/form-submit.php:968 -#: inc/payments/front-end.php:77 -#: inc/payments/front-end.php:258 +#: 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 @@ -16097,32 +16095,32 @@ msgid "Enter a valid email address." msgstr "Voer een geldig e-mailadres in." #. translators: %s represents the minimum acceptable value -#: inc/translatable.php:94 +#: inc/translatable.php:97 #, php-format msgid "Minimum value is %s." msgstr "Minimale waarde is %s." #. translators: %s represents the maximum acceptable value -#: inc/translatable.php:97 +#: inc/translatable.php:100 #, php-format msgid "Maximum value is %s." msgstr "Maximale waarde is %s." #. translators: %s represents the minimum number of options to select -#: inc/translatable.php:100 -#: inc/translatable.php:106 +#: inc/translatable.php:103 +#: inc/translatable.php:109 #, php-format msgid "Select at least %s options." msgstr "Selecteer ten minste %s opties." #. translators: %s represents the maximum number of options that can be selected -#: inc/translatable.php:103 -#: inc/translatable.php:109 +#: inc/translatable.php:106 +#: inc/translatable.php:112 #, php-format msgid "You can select up to %s options." msgstr "U kunt maximaal %s opties selecteren." -#: inc/translatable.php:120 +#: inc/translatable.php:123 msgid "This form is now closed as we have reached the maximum number of entries." msgstr "Dit formulier is nu gesloten omdat we het maximale aantal inzendingen hebben bereikt." @@ -16649,35 +16647,35 @@ msgstr "Haal de globale instellingen van SureForms op. Optioneel filteren op cat msgid "Setting categories to retrieve. Omit for all categories." msgstr "Categorieën instellen om op te halen. Laat weg voor alle categorieën." -#: inc/abilities/settings/update-global-settings.php:105 +#: inc/abilities/settings/update-global-settings.php:106 msgid "Update Global Settings" msgstr "Globale instellingen bijwerken" -#: inc/abilities/settings/update-global-settings.php:106 +#: inc/abilities/settings/update-global-settings.php:107 msgid "Update SureForms global settings for a specific category: general, validation-messages, email-summary, or security." msgstr "Werk de globale instellingen van SureForms bij voor een specifieke categorie: algemeen, validatieberichten, e-mailoverzicht of beveiliging." -#: inc/abilities/settings/update-global-settings.php:139 +#: inc/abilities/settings/update-global-settings.php:140 msgid "The settings category to update." msgstr "De instellingen categorie om bij te werken." -#: inc/abilities/settings/update-global-settings.php:144 +#: inc/abilities/settings/update-global-settings.php:145 msgid "Key-value pairs of settings to update." msgstr "Sleutel-waardeparen van instellingen om bij te werken." -#: inc/abilities/settings/update-global-settings.php:180 +#: inc/abilities/settings/update-global-settings.php:181 msgid "Settings category is required." msgstr "Categorie-instellingen zijn vereist." -#: inc/abilities/settings/update-global-settings.php:188 +#: inc/abilities/settings/update-global-settings.php:189 msgid "Settings data is required." msgstr "Instellingen gegevens zijn vereist." -#: inc/abilities/settings/update-global-settings.php:199 +#: inc/abilities/settings/update-global-settings.php:200 msgid "No valid settings keys provided for this category." msgstr "Geen geldige instellingssleutels opgegeven voor deze categorie." -#: inc/abilities/settings/update-global-settings.php:225 +#: inc/abilities/settings/update-global-settings.php:226 msgid "Invalid settings category." msgstr "Ongeldige instellingen categorie." @@ -17578,6 +17576,212 @@ msgstr "Poolse Złoty" msgid "Dynamic Default Value" msgstr "Dynamische Standaardwaarde" +#: inc/admin/editor-nudge.php:191 +msgid "Hey! It looks like you're creating a form. Build a ready-to-use form in under 30 seconds with SureForms AI, with no extra setup required." +msgstr "Hey! Het lijkt erop dat je een formulier aan het maken bent. Bouw een gebruiksklaar formulier in minder dan 30 seconden met SureForms AI, zonder extra installatie vereist." + +#: inc/admin/editor-nudge.php:228 +#: inc/admin/editor-nudge.php:237 +msgid "Invalid post." +msgstr "Ongeldige post." + +#: inc/admin/editor-nudge.php:246 +msgid "You cannot edit this post." +msgstr "Je kunt dit bericht niet bewerken." + +#: inc/ai-form-builder/ai-form-builder.php:96 +msgid "The AI did not return a form. Please refine your prompt and try again." +msgstr "De AI heeft geen formulier geretourneerd. Gelieve uw prompt te verfijnen en het opnieuw te proberen." + +#: inc/ai-form-builder/ai-form-builder.php:104 +msgid "The AI response is missing a form title. Please try again." +msgstr "De AI-reactie mist een formulier titel. Probeer het opnieuw." + +#: inc/ai-form-builder/ai-form-builder.php:115 +#: inc/ai-form-builder/field-mapping.php:69 +msgid "The AI was unable to generate form fields. Please try again." +msgstr "De AI kon geen formuliervelden genereren. Probeer het alstublieft opnieuw." + +#: inc/ai-form-builder/field-mapping.php:41 +msgid "The AI form data is missing. Please try again." +msgstr "De AI-formuliergegevens ontbreken. Probeer het alstublieft opnieuw." + +#: inc/ai-form-builder/field-mapping.php:51 +msgid "The AI form data is not in the expected format." +msgstr "De AI-formuliergegevens zijn niet in het verwachte formaat." + +#: inc/ai-form-builder/field-mapping.php:60 +msgid "The AI response did not include a form. Please try again." +msgstr "De AI-reactie bevatte geen formulier. Probeer het alstublieft opnieuw." + +#: inc/ai-form-builder/field-mapping.php:90 +msgid "The AI returned a malformed form field. Please try again." +msgstr "De AI gaf een onjuist ingevuld formulier terug. Probeer het alstublieft opnieuw." + +#: inc/create-new-form.php:160 +#: inc/create-new-form.php:173 +msgid "Error creating SureForms Form." +msgstr "Fout bij het maken van SureForms-formulier." + +#. translators: %s represents the minimum number of characters required +#: inc/field-validation.php:289 +#: inc/translatable.php:94 +#, php-format +msgid "Please enter at least %s characters." +msgstr "Voer alstublieft minimaal %s tekens in." + +#: inc/fields/payment-markup.php:246 +msgid "One-Time Payment" +msgstr "Eenmalige betaling" + +#: inc/fields/payment-markup.php:562 +msgid "Choose payment type" +msgstr "Kies betaalmethode" + +#: inc/payments/front-end.php:333 +msgid "Billing interval does not match the form configuration." +msgstr "Het factureringsinterval komt niet overeen met de formulierconfiguratie." + +#: inc/payments/payment-helper.php:627 +msgid "Payment type does not match the form configuration." +msgstr "Betalingstype komt niet overeen met de formulierconfiguratie." + +#: inc/payments/payment-helper.php:760 +msgid "Payment verification failed. Payment type mismatch." +msgstr "Verificatie van betaling mislukt. Type betaling komt niet overeen." + +#: assets/build/blocks.js:172 +msgid "Minimum Characters" +msgstr "Minimale tekens" + +#: assets/build/blocks.js:172 +msgid "Minimum characters cannot exceed Maximum characters." +msgstr "Minimumtekens kunnen niet groter zijn dan maximumtekens." + +#: assets/build/blocks.js:172 +msgid "Both" +msgstr "Beide" + +#: assets/build/blocks.js:172 +msgid "One-Time Label" +msgstr "Eenmalig label" + +#: assets/build/blocks.js:172 +msgid "Label shown to users for the one-time payment option." +msgstr "Label getoond aan gebruikers voor de eenmalige betalingsoptie." + +#: assets/build/blocks.js:172 +msgid "Subscription Label" +msgstr "Abonnementslabel" + +#: assets/build/blocks.js:172 +msgid "Label shown to users for the subscription option." +msgstr "Label getoond aan gebruikers voor de abonnementsoptie." + +#: assets/build/blocks.js:172 +msgid "Default Selection" +msgstr "Standaardselectie" + +#: assets/build/blocks.js:172 +msgid "Which option is pre-selected when the form loads." +msgstr "Welke optie is vooraf geselecteerd wanneer het formulier wordt geladen." + +#: assets/build/blocks.js:172 +msgid "One-Time Amount Type" +msgstr "Eenmalig Bedragstype" + +#: assets/build/blocks.js:172 +msgid "Set how the one-time payment amount is determined." +msgstr "Stel in hoe het bedrag van de eenmalige betaling wordt bepaald." + +#: assets/build/blocks.js:172 +msgid "One-Time Fixed Amount" +msgstr "Eenmalig vast bedrag" + +#: assets/build/blocks.js:172 +msgid "Amount charged for a one-time payment." +msgstr "Bedrag in rekening gebracht voor een eenmalige betaling." + +#: assets/build/blocks.js:172 +msgid "One-Time Amount Field" +msgstr "Eenmalig Bedrag Veld" + +#: assets/build/blocks.js:172 +msgid "Pick a form field whose value determines the one-time payment amount." +msgstr "Kies een formulier veld waarvan de waarde het eenmalige betalingsbedrag bepaalt." + +#: assets/build/blocks.js:172 +msgid "One-Time Minimum Amount" +msgstr "Eenmalig Minimum Bedrag" + +#: assets/build/blocks.js:172 +msgid "Minimum amount users can enter for one-time payment (0 for no minimum)." +msgstr "Minimumbedrag dat gebruikers kunnen invoeren voor een eenmalige betaling (0 voor geen minimum)." + +#: assets/build/blocks.js:172 +msgid "Subscription Amount Type" +msgstr "Type abonnementsbedrag" + +#: assets/build/blocks.js:172 +msgid "Set how the subscription amount is determined." +msgstr "Stel in hoe het abonnementsbedrag wordt bepaald." + +#: assets/build/blocks.js:172 +msgid "Subscription Fixed Amount" +msgstr "Vast bedrag voor abonnement" + +#: assets/build/blocks.js:172 +msgid "Recurring amount charged per billing interval." +msgstr "Terugkerend bedrag dat per factureringsinterval in rekening wordt gebracht." + +#: assets/build/blocks.js:172 +msgid "Subscription Amount Field" +msgstr "Veld Abonnementsbedrag" + +#: assets/build/blocks.js:172 +msgid "Pick a form field whose value determines the subscription amount." +msgstr "Kies een formulier veld waarvan de waarde het abonnementsbedrag bepaalt." + +#: assets/build/blocks.js:172 +msgid "Subscription Minimum Amount" +msgstr "Minimumbedrag voor abonnement" + +#: assets/build/blocks.js:172 +msgid "Minimum amount users can enter for subscription (0 for no minimum)." +msgstr "Minimumbedrag dat gebruikers kunnen invoeren voor abonnement (0 voor geen minimum)." + +#: 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 "Kies een veld uit uw formulier, zoals een nummer, dropdown, meerkeuze of verborgen veld, waarvan de waarde het betalingsbedrag moet bepalen." + +#: assets/build/templatePicker.js:172 +msgid "You do not have permission to create forms." +msgstr "Je hebt geen toestemming om formulieren te maken." + +#: assets/build/templatePicker.js:172 +msgid "The form could not be saved. Please try again." +msgstr "Het formulier kon niet worden opgeslagen. Probeer het alstublieft opnieuw." + +#: assets/build/templatePicker.js:172 +msgid "Unable to reach the SureForms AI service. Please check your connection and try again." +msgstr "Kan geen verbinding maken met de SureForms AI-service. Controleer uw verbinding en probeer het opnieuw." + +#: assets/build/templatePicker.js:172 +msgid "The AI service did not return a response. Please try again." +msgstr "De AI-service gaf geen reactie. Probeer het alstublieft opnieuw." + +#: assets/build/templatePicker.js:172 +msgid "Form generation failed. Please try again." +msgstr "Het genereren van het formulier is mislukt. Probeer het alstublieft opnieuw." + +#: assets/build/templatePicker.js:172 +msgid "The AI response was empty. Please refine your prompt and try again." +msgstr "De AI-reactie was leeg. Gelieve uw prompt te verfijnen en het opnieuw te proberen." + +#: assets/build/templatePicker.js:172 +msgid "Unable to build form fields from the AI response." +msgstr "Kan formuliervelden niet opbouwen vanuit de AI-reactie." + #: inc/post-types.php:205 msgctxt "post type general name" msgid "Forms" diff --git a/languages/sureforms-pl_PL-120a6dad015d3891c70f578c2251576b.json b/languages/sureforms-pl_PL-120a6dad015d3891c70f578c2251576b.json index 4394fbcc1..1120901e6 100644 --- a/languages/sureforms-pl_PL-120a6dad015d3891c70f578c2251576b.json +++ b/languages/sureforms-pl_PL-120a6dad015d3891c70f578c2251576b.json @@ -1 +1 @@ -{"translation-revision-date":"2025-01-02T08:44:41+00:00","generator":"WP-CLI\/2.12.0","source":"assets\/build\/templatePicker.js","domain":"messages","locale_data":{"messages":{"":{"domain":"messages","lang":"en","plural-forms":"nplurals=2; plural=(n != 1);"},"Dashboard":["Panel sterowania"],"Connect Now":["Po\u0142\u0105cz teraz"],"Authentication Failed":["Uwierzytelnianie nie powiod\u0142o si\u0119"],"Contact Support":["Skontaktuj si\u0119 z pomoc\u0105 techniczn\u0105"],"Click Here to Retry":["Kliknij tutaj, aby spr\u00f3bowa\u0107 ponownie"],"Exit to Dashboard":["Wyjd\u017a do pulpitu nawigacyjnego"],"AI Form Builder":["Kreator Formularzy AI"],"Speech recognition is not supported in your current browser. Please use Google Chrome \/ Safari.":["Rozpoznawanie mowy nie jest obs\u0142ugiwane w Twojej obecnej przegl\u0105darce. Prosz\u0119 u\u017cy\u0107 Google Chrome \/ Safari."],"Please allow microphone access to use voice input.":["Prosz\u0119 zezwoli\u0107 na dost\u0119p do mikrofonu, aby korzysta\u0107 z wprowadzania g\u0142osowego."],"Voice Input":["Wprowadzanie g\u0142osowe"],"Try Again":["Spr\u00f3buj ponownie"],"Please try again after %s.":["Prosz\u0119 spr\u00f3bowa\u0107 ponownie za %s."],"You have reached the maximum number of form generations in your Free Plan.":["Osi\u0105gn\u0105\u0142e\u015b maksymaln\u0105 liczb\u0119 generacji formularzy w swoim darmowym planie."],"Unlock Conversational Forms":["Odblokuj formularze konwersacyjne"],"Simple":["Proste"],"Upgrade Now":["Zaktualizuj teraz"],"Generate with AI":["Generuj za pomoc\u0105 AI"],"Please check your username and password for the account, and try to reconnect again. Need help?":["Prosz\u0119 sprawdzi\u0107 swoj\u0105 nazw\u0119 u\u017cytkownika i has\u0142o do konta, a nast\u0119pnie spr\u00f3bowa\u0107 ponownie po\u0142\u0105czy\u0107 si\u0119. Potrzebujesz pomocy?"],"Describe the form you want to create":["Opisz formularz, kt\u00f3ry chcesz utworzy\u0107"],"We are building your form\u2026":["Budujemy Tw\u00f3j formularz\u2026"],"Payment":["P\u0142atno\u015b\u0107"],"and ":["i"],"more\u2026":["wi\u0119cej\u2026"],"Calculations":["Obliczenia"],"Unlock Calculator Forms":["Odblokuj formularze kalkulatora"],"Build Smart Forms That Calculate Instantly":["Tw\u00f3rz inteligentne formularze, kt\u00f3re obliczaj\u0105 natychmiast"],"Empower your forms with advanced calculations. From loan calculators to BMI checkers - create interactive forms that give real-time results.":["Wzmacniaj swoje formularze zaawansowanymi obliczeniami. Od kalkulator\u00f3w kredytowych po wska\u017aniki BMI - tw\u00f3rz interaktywne formularze, kt\u00f3re dostarczaj\u0105 wynik\u00f3w w czasie rzeczywistym."],"Add complex formulas with ease":["Dodawaj z\u0142o\u017cone formu\u0142y z \u0142atwo\u015bci\u0105"],"Provide instant answers to users":["Zapewnij natychmiastowe odpowiedzi u\u017cytkownikom"],"Perfect for finance, health, and pricing forms":["Idealne do formularzy finansowych, zdrowotnych i cenowych"],"Conversational":["Konwersacyjny"],"Turn Simple Forms Into Conversations":["Zamie\u0144 proste formularze w rozmowy"],"Transform boring forms into friendly, chat-like experiences. Ask one question at a time, just like a real conversation, and see higher engagement.":["Przekszta\u0142\u0107 nudne formularze w przyjazne, przypominaj\u0105ce czat do\u015bwiadczenia. Zadawaj jedno pytanie na raz, tak jak w prawdziwej rozmowie, i obserwuj wi\u0119ksze zaanga\u017cowanie."],"One question at a time, in chat flow":["Jedno pytanie na raz, w przep\u0142ywie czatu"],"More engaging than traditional forms":["Bardziej anga\u017cuj\u0105ce ni\u017c tradycyjne formy"],"Boosts completion rates with a friendly interface":["Zwi\u0119ksza wska\u017aniki uko\u0144czenia dzi\u0119ki przyjaznemu interfejsowi"],"Select this if you need calculations in your form. For example: Loan interest calculator.":["Wybierz to, je\u015bli potrzebujesz oblicze\u0144 w swoim formularzu. Na przyk\u0142ad: Kalkulator odsetek od po\u017cyczki."],"Select this if you want your form to display one question at a time, like a chat.":["Wybierz to, je\u015bli chcesz, aby formularz wy\u015bwietla\u0142 jedno pytanie na raz, jak w czacie."],"Select this if you want to collect payments through your form.":["Wybierz to, je\u015bli chcesz zbiera\u0107 p\u0142atno\u015bci za pomoc\u0105 swojego formularza."],"%d AI Generations Left. SureForms Premium allows:":["%d Generacji AI pozosta\u0142o. SureForms Premium umo\u017cliwia:"],"%d AI Generations Left, Connect to SureForms AI to Get 10 More":["%d generacji AI pozosta\u0142o, po\u0142\u0105cz si\u0119 z SureForms AI, aby uzyska\u0107 10 wi\u0119cej"],"%d AI Generations Left. Upgrade to SureForms Premium":["%d generacji AI pozosta\u0142o. Ulepsz do SureForms Premium"],"Contact form to collect name, email, and message from visitors":["Formularz kontaktowy do zbierania imienia, adresu e-mail i wiadomo\u015bci od odwiedzaj\u0105cych"],"Job application form for \"Marketing Manager\" with resume upload":["Formularz aplikacyjny na stanowisko \u201eMarketing Manager\u201d z mo\u017cliwo\u015bci\u0105 przes\u0142ania CV"],"Feedback form to ask customers: \"How would you rate our product and what should we improve?\"":["Formularz opinii do klient\u00f3w: \"Jak oceni\u0142by\u015b nasz produkt i co powinni\u015bmy poprawi\u0107?\""],"Event registration form for \"Photography Workshop\" with date and seat selection":["Formularz rejestracji na wydarzenie \u201eWarsztaty Fotograficzne\u201d z wyborem daty i miejsca"],"Newsletter signup form with name and email to join mailing list":["Formularz zapisu do newslettera z imieniem i adresem e-mail, aby do\u0142\u0105czy\u0107 do listy mailingowej"],"Order form for \"Custom T-Shirt\" with size, color, and quantity options":["Formularz zam\u00f3wienia na \"Koszulk\u0119 na zam\u00f3wienie\" z opcjami rozmiaru, koloru i ilo\u015bci"],"Survey form: \"How satisfied are you with our service? (1\u20135 stars)\"":["Formularz ankiety: \"Jak bardzo jeste\u015b zadowolony z naszej us\u0142ugi? (1\u20135 gwiazdek)\""],"Appointment booking form for \"Consultation Call\" with preferred time":["Formularz rezerwacji wizyty na \"Rozmow\u0119 konsultacyjn\u0105\" z preferowanym czasem"],"Describe the form that you want":["Opisz form\u0119, kt\u00f3r\u0105 chcesz"],"Generate":["Generuj"],"Create Unlimited Forms with AI":["Tw\u00f3rz nieograniczone formularze z AI"],"Add Advanced Field Types":["Dodaj zaawansowane typy p\u00f3l"],"Create Calculators, Surveys, etc.":["Tw\u00f3rz kalkulatory, ankiety itp."],"Form Generation Limit Reached":["Osi\u0105gni\u0119to limit generowania formularzy"],"You have reached the maximum number of form generations in your Free Plan. SureForms Premium allows:":["Osi\u0105gn\u0105\u0142e\u015b maksymaln\u0105 liczb\u0119 generacji formularzy w swoim darmowym planie. SureForms Premium pozwala na:"],"%s AI Generations Left.":["%s generacji AI pozosta\u0142o."],"Unlock Unlimited Generations":["Odblokuj Nieograniczone Generacje"],"Connect to SureForms AI":["Po\u0142\u0105cz si\u0119 z SureForms AI"],"You Have Hit Your Free Limit.":["Osi\u0105gn\u0105\u0142e\u015b sw\u00f3j darmowy limit."],"Connect to SureForms AI to Get 10 More.":["Po\u0142\u0105cz si\u0119 z SureForms AI, aby uzyska\u0107 10 wi\u0119cej."],"Or create it yourself":["Lub stw\u00f3rz to sam"],"Unable to create form":["Nie mo\u017cna utworzy\u0107 formularza"],"Something went wrong. Please try again.":["Co\u015b posz\u0142o nie tak. Prosz\u0119 spr\u00f3buj ponownie."],"Describe what kind of form you want":["Opisz, jaki rodzaj formularza chcesz"],"Click to generate the form":["Kliknij, aby wygenerowa\u0107 formularz"],"Connecting to AI service":["\u0141\u0105czenie z us\u0142ug\u0105 AI"],"Generating fields":["Generowanie p\u00f3l"],"Finalizing your form":["Ko\u0144czenie formularza"],"Opening form editor":["Otwieranie edytora formularzy"],"Design Multistep Forms":["Zaprojektuj formularze wieloetapowe"],"Send Form Entries to Your CRM or Any App":["Wy\u015blij wpisy formularza do swojego CRM lub dowolnej aplikacji"],"You've reached your daily generation limit.":["Osi\u0105gn\u0105\u0142e\u015b sw\u00f3j dzienny limit generacji."],"You've reached your daily limit for AI form generations.":["Osi\u0105gn\u0105\u0142e\u015b dzienny limit generacji formularzy AI."],"Quiz":["Quiz"],"Unlock Quiz Forms":["Odblokuj formularze quizu"],"Create Engaging Quizzes That Score Automatically":["Tw\u00f3rz anga\u017cuj\u0105ce quizy, kt\u00f3re s\u0105 oceniane automatycznie"],"Build interactive quizzes with scored questions and graded results. Perfect for assessments, trivia, and educational content.":["Tw\u00f3rz interaktywne quizy z punktowanymi pytaniami i ocenianymi wynikami. Idealne do ocen, quiz\u00f3w i tre\u015bci edukacyjnych."],"Auto-score responses instantly":["Natychmiastowe automatyczne ocenianie odpowiedzi"],"Display graded results to users":["Wy\u015bwietl ocenione wyniki u\u017cytkownikom"],"Perfect for education, training, and fun trivia":["Idealne do edukacji, szkole\u0144 i zabawnych ciekawostek"],"Select this to create a quiz with scored questions and graded results.":["Wybierz to, aby utworzy\u0107 quiz z punktowanymi pytaniami i ocenianymi wynikami."],"Select this to create a survey to collect responses and opinions.":["Wybierz to, aby utworzy\u0107 ankiet\u0119 do zbierania odpowiedzi i opinii."],"Survey":["Ankieta"],"Unlock Survey Forms":["Odblokuj formularze ankiety"],"Collect Insights with Powerful Surveys":["Zbieraj informacje dzi\u0119ki pot\u0119\u017cnym ankietom"],"Create surveys to collect responses and opinions. Visualize results with charts and share aggregated insights with your audience.":["Tw\u00f3rz ankiety, aby zbiera\u0107 odpowiedzi i opinie. Wizualizuj wyniki za pomoc\u0105 wykres\u00f3w i dziel si\u0119 zbiorczymi spostrze\u017ceniami ze swoj\u0105 publiczno\u015bci\u0105."],"Aggregate and visualize responses":["Zbieraj i wizualizuj odpowiedzi"],"Show live results to respondents":["Poka\u017c respondentom wyniki na \u017cywo"],"Perfect for feedback, polls, and research":["Idealne do opinii, ankiet i bada\u0144"]}}} \ No newline at end of file +{"translation-revision-date":"2025-01-02T08:44:41+00:00","generator":"WP-CLI\/2.12.0","source":"assets\/build\/templatePicker.js","domain":"messages","locale_data":{"messages":{"":{"domain":"messages","lang":"en","plural-forms":"nplurals=2; plural=(n != 1);"},"Dashboard":["Panel sterowania"],"Connect Now":["Po\u0142\u0105cz teraz"],"Authentication Failed":["Uwierzytelnianie nie powiod\u0142o si\u0119"],"Contact Support":["Skontaktuj si\u0119 z pomoc\u0105 techniczn\u0105"],"Click Here to Retry":["Kliknij tutaj, aby spr\u00f3bowa\u0107 ponownie"],"Exit to Dashboard":["Wyjd\u017a do pulpitu nawigacyjnego"],"AI Form Builder":["Kreator Formularzy AI"],"Speech recognition is not supported in your current browser. Please use Google Chrome \/ Safari.":["Rozpoznawanie mowy nie jest obs\u0142ugiwane w Twojej obecnej przegl\u0105darce. Prosz\u0119 u\u017cy\u0107 Google Chrome \/ Safari."],"Please allow microphone access to use voice input.":["Prosz\u0119 zezwoli\u0107 na dost\u0119p do mikrofonu, aby korzysta\u0107 z wprowadzania g\u0142osowego."],"Voice Input":["Wprowadzanie g\u0142osowe"],"Try Again":["Spr\u00f3buj ponownie"],"Please try again after %s.":["Prosz\u0119 spr\u00f3bowa\u0107 ponownie za %s."],"You have reached the maximum number of form generations in your Free Plan.":["Osi\u0105gn\u0105\u0142e\u015b maksymaln\u0105 liczb\u0119 generacji formularzy w swoim darmowym planie."],"Unlock Conversational Forms":["Odblokuj formularze konwersacyjne"],"Simple":["Proste"],"Upgrade Now":["Zaktualizuj teraz"],"Generate with AI":["Generuj za pomoc\u0105 AI"],"Please check your username and password for the account, and try to reconnect again. Need help?":["Prosz\u0119 sprawdzi\u0107 swoj\u0105 nazw\u0119 u\u017cytkownika i has\u0142o do konta, a nast\u0119pnie spr\u00f3bowa\u0107 ponownie po\u0142\u0105czy\u0107 si\u0119. Potrzebujesz pomocy?"],"Describe the form you want to create":["Opisz formularz, kt\u00f3ry chcesz utworzy\u0107"],"We are building your form\u2026":["Budujemy Tw\u00f3j formularz\u2026"],"Payment":["P\u0142atno\u015b\u0107"],"and ":["i"],"more\u2026":["wi\u0119cej\u2026"],"Calculations":["Obliczenia"],"Unlock Calculator Forms":["Odblokuj formularze kalkulatora"],"Build Smart Forms That Calculate Instantly":["Tw\u00f3rz inteligentne formularze, kt\u00f3re obliczaj\u0105 natychmiast"],"Empower your forms with advanced calculations. From loan calculators to BMI checkers - create interactive forms that give real-time results.":["Wzmacniaj swoje formularze zaawansowanymi obliczeniami. Od kalkulator\u00f3w kredytowych po wska\u017aniki BMI - tw\u00f3rz interaktywne formularze, kt\u00f3re dostarczaj\u0105 wynik\u00f3w w czasie rzeczywistym."],"Add complex formulas with ease":["Dodawaj z\u0142o\u017cone formu\u0142y z \u0142atwo\u015bci\u0105"],"Provide instant answers to users":["Zapewnij natychmiastowe odpowiedzi u\u017cytkownikom"],"Perfect for finance, health, and pricing forms":["Idealne do formularzy finansowych, zdrowotnych i cenowych"],"Conversational":["Konwersacyjny"],"Turn Simple Forms Into Conversations":["Zamie\u0144 proste formularze w rozmowy"],"Transform boring forms into friendly, chat-like experiences. Ask one question at a time, just like a real conversation, and see higher engagement.":["Przekszta\u0142\u0107 nudne formularze w przyjazne, przypominaj\u0105ce czat do\u015bwiadczenia. Zadawaj jedno pytanie na raz, tak jak w prawdziwej rozmowie, i obserwuj wi\u0119ksze zaanga\u017cowanie."],"One question at a time, in chat flow":["Jedno pytanie na raz, w przep\u0142ywie czatu"],"More engaging than traditional forms":["Bardziej anga\u017cuj\u0105ce ni\u017c tradycyjne formy"],"Boosts completion rates with a friendly interface":["Zwi\u0119ksza wska\u017aniki uko\u0144czenia dzi\u0119ki przyjaznemu interfejsowi"],"Select this if you need calculations in your form. For example: Loan interest calculator.":["Wybierz to, je\u015bli potrzebujesz oblicze\u0144 w swoim formularzu. Na przyk\u0142ad: Kalkulator odsetek od po\u017cyczki."],"Select this if you want your form to display one question at a time, like a chat.":["Wybierz to, je\u015bli chcesz, aby formularz wy\u015bwietla\u0142 jedno pytanie na raz, jak w czacie."],"Select this if you want to collect payments through your form.":["Wybierz to, je\u015bli chcesz zbiera\u0107 p\u0142atno\u015bci za pomoc\u0105 swojego formularza."],"%d AI Generations Left. SureForms Premium allows:":["%d Generacji AI pozosta\u0142o. SureForms Premium umo\u017cliwia:"],"%d AI Generations Left, Connect to SureForms AI to Get 10 More":["%d generacji AI pozosta\u0142o, po\u0142\u0105cz si\u0119 z SureForms AI, aby uzyska\u0107 10 wi\u0119cej"],"%d AI Generations Left. Upgrade to SureForms Premium":["%d generacji AI pozosta\u0142o. Ulepsz do SureForms Premium"],"Contact form to collect name, email, and message from visitors":["Formularz kontaktowy do zbierania imienia, adresu e-mail i wiadomo\u015bci od odwiedzaj\u0105cych"],"Job application form for \"Marketing Manager\" with resume upload":["Formularz aplikacyjny na stanowisko \u201eMarketing Manager\u201d z mo\u017cliwo\u015bci\u0105 przes\u0142ania CV"],"Feedback form to ask customers: \"How would you rate our product and what should we improve?\"":["Formularz opinii do klient\u00f3w: \"Jak oceni\u0142by\u015b nasz produkt i co powinni\u015bmy poprawi\u0107?\""],"Event registration form for \"Photography Workshop\" with date and seat selection":["Formularz rejestracji na wydarzenie \u201eWarsztaty Fotograficzne\u201d z wyborem daty i miejsca"],"Newsletter signup form with name and email to join mailing list":["Formularz zapisu do newslettera z imieniem i adresem e-mail, aby do\u0142\u0105czy\u0107 do listy mailingowej"],"Order form for \"Custom T-Shirt\" with size, color, and quantity options":["Formularz zam\u00f3wienia na \"Koszulk\u0119 na zam\u00f3wienie\" z opcjami rozmiaru, koloru i ilo\u015bci"],"Survey form: \"How satisfied are you with our service? (1\u20135 stars)\"":["Formularz ankiety: \"Jak bardzo jeste\u015b zadowolony z naszej us\u0142ugi? (1\u20135 gwiazdek)\""],"Appointment booking form for \"Consultation Call\" with preferred time":["Formularz rezerwacji wizyty na \"Rozmow\u0119 konsultacyjn\u0105\" z preferowanym czasem"],"Describe the form that you want":["Opisz form\u0119, kt\u00f3r\u0105 chcesz"],"Generate":["Generuj"],"Create Unlimited Forms with AI":["Tw\u00f3rz nieograniczone formularze z AI"],"Add Advanced Field Types":["Dodaj zaawansowane typy p\u00f3l"],"Create Calculators, Surveys, etc.":["Tw\u00f3rz kalkulatory, ankiety itp."],"Form Generation Limit Reached":["Osi\u0105gni\u0119to limit generowania formularzy"],"You have reached the maximum number of form generations in your Free Plan. SureForms Premium allows:":["Osi\u0105gn\u0105\u0142e\u015b maksymaln\u0105 liczb\u0119 generacji formularzy w swoim darmowym planie. SureForms Premium pozwala na:"],"%s AI Generations Left.":["%s generacji AI pozosta\u0142o."],"Unlock Unlimited Generations":["Odblokuj Nieograniczone Generacje"],"Connect to SureForms AI":["Po\u0142\u0105cz si\u0119 z SureForms AI"],"You Have Hit Your Free Limit.":["Osi\u0105gn\u0105\u0142e\u015b sw\u00f3j darmowy limit."],"Connect to SureForms AI to Get 10 More.":["Po\u0142\u0105cz si\u0119 z SureForms AI, aby uzyska\u0107 10 wi\u0119cej."],"Or create it yourself":["Lub stw\u00f3rz to sam"],"Unable to create form":["Nie mo\u017cna utworzy\u0107 formularza"],"Something went wrong. Please try again.":["Co\u015b posz\u0142o nie tak. Prosz\u0119 spr\u00f3buj ponownie."],"Describe what kind of form you want":["Opisz, jaki rodzaj formularza chcesz"],"Click to generate the form":["Kliknij, aby wygenerowa\u0107 formularz"],"Connecting to AI service":["\u0141\u0105czenie z us\u0142ug\u0105 AI"],"Generating fields":["Generowanie p\u00f3l"],"Finalizing your form":["Ko\u0144czenie formularza"],"Opening form editor":["Otwieranie edytora formularzy"],"Design Multistep Forms":["Zaprojektuj formularze wieloetapowe"],"Send Form Entries to Your CRM or Any App":["Wy\u015blij wpisy formularza do swojego CRM lub dowolnej aplikacji"],"You've reached your daily generation limit.":["Osi\u0105gn\u0105\u0142e\u015b sw\u00f3j dzienny limit generacji."],"You've reached your daily limit for AI form generations.":["Osi\u0105gn\u0105\u0142e\u015b dzienny limit generacji formularzy AI."],"Quiz":["Quiz"],"Unlock Quiz Forms":["Odblokuj formularze quizu"],"Create Engaging Quizzes That Score Automatically":["Tw\u00f3rz anga\u017cuj\u0105ce quizy, kt\u00f3re s\u0105 oceniane automatycznie"],"Build interactive quizzes with scored questions and graded results. Perfect for assessments, trivia, and educational content.":["Tw\u00f3rz interaktywne quizy z punktowanymi pytaniami i ocenianymi wynikami. Idealne do ocen, quiz\u00f3w i tre\u015bci edukacyjnych."],"Auto-score responses instantly":["Natychmiastowe automatyczne ocenianie odpowiedzi"],"Display graded results to users":["Wy\u015bwietl ocenione wyniki u\u017cytkownikom"],"Perfect for education, training, and fun trivia":["Idealne do edukacji, szkole\u0144 i zabawnych ciekawostek"],"Select this to create a quiz with scored questions and graded results.":["Wybierz to, aby utworzy\u0107 quiz z punktowanymi pytaniami i ocenianymi wynikami."],"Select this to create a survey to collect responses and opinions.":["Wybierz to, aby utworzy\u0107 ankiet\u0119 do zbierania odpowiedzi i opinii."],"Survey":["Ankieta"],"Unlock Survey Forms":["Odblokuj formularze ankiety"],"Collect Insights with Powerful Surveys":["Zbieraj informacje dzi\u0119ki pot\u0119\u017cnym ankietom"],"Create surveys to collect responses and opinions. Visualize results with charts and share aggregated insights with your audience.":["Tw\u00f3rz ankiety, aby zbiera\u0107 odpowiedzi i opinie. Wizualizuj wyniki za pomoc\u0105 wykres\u00f3w i dziel si\u0119 zbiorczymi spostrze\u017ceniami ze swoj\u0105 publiczno\u015bci\u0105."],"Aggregate and visualize responses":["Zbieraj i wizualizuj odpowiedzi"],"Show live results to respondents":["Poka\u017c respondentom wyniki na \u017cywo"],"Perfect for feedback, polls, and research":["Idealne do opinii, ankiet i bada\u0144"],"You do not have permission to create forms.":["Nie masz uprawnie\u0144 do tworzenia formularzy."],"The form could not be saved. Please try again.":["Nie mo\u017cna by\u0142o zapisa\u0107 formularza. Prosz\u0119 spr\u00f3bowa\u0107 ponownie."],"Unable to reach the SureForms AI service. Please check your connection and try again.":["Nie mo\u017cna po\u0142\u0105czy\u0107 si\u0119 z us\u0142ug\u0105 SureForms AI. Prosz\u0119 sprawdzi\u0107 po\u0142\u0105czenie i spr\u00f3bowa\u0107 ponownie."],"The AI service did not return a response. Please try again.":["Us\u0142uga AI nie zwr\u00f3ci\u0142a odpowiedzi. Prosz\u0119 spr\u00f3bowa\u0107 ponownie."],"Form generation failed. Please try again.":["Generowanie formularza nie powiod\u0142o si\u0119. Prosz\u0119 spr\u00f3bowa\u0107 ponownie."],"The AI response was empty. Please refine your prompt and try again.":["Odpowied\u017a AI by\u0142a pusta. Prosz\u0119 dopracowa\u0107 sw\u00f3j prompt i spr\u00f3bowa\u0107 ponownie."],"Unable to build form fields from the AI response.":["Nie mo\u017cna utworzy\u0107 p\u00f3l formularza z odpowiedzi AI."]}}} \ No newline at end of file diff --git a/languages/sureforms-pl_PL-4b62e3f004dea2c587b5a3069263d994.json b/languages/sureforms-pl_PL-4b62e3f004dea2c587b5a3069263d994.json index 41d2308dc..f533819fe 100644 --- a/languages/sureforms-pl_PL-4b62e3f004dea2c587b5a3069263d994.json +++ b/languages/sureforms-pl_PL-4b62e3f004dea2c587b5a3069263d994.json @@ -1 +1 @@ -{"translation-revision-date":"2025-01-02T08:44:41+00:00","generator":"WP-CLI\/2.12.0","source":"assets\/build\/blocks.js","domain":"messages","locale_data":{"messages":{"":{"domain":"messages","lang":"en","plural-forms":"nplurals=2; plural=(n != 1);"},"Settings":["Ustawienia"],"Search":["Szukaj"],"Fields":["Pola"],"Image":["Obraz"],"Submit":["Prze\u015blij"],"Required":["Wymagane"],"Form Title":["Tytu\u0142 formularza"],"Show":["Poka\u017c"],"Hide":["Ukryj"],"Edit Form":["Edytuj formularz"],"Icon":["Ikona"],"Desktop":["Pulpit"],"Medium":["\u015aredni"],"Mobile":["Telefon kom\u00f3rkowy"],"Repeat":["Powt\u00f3rz"],"Scroll":["Przewi\u0144"],"Tablet":["Tablet"],"Basic":["Podstawowy"],"(no title)":["(brak tytu\u0142u)"],"Select a Form":["Wybierz formularz"],"No forms found\u2026":["Nie znaleziono formularzy\u2026"],"Choose":["Wybierz"],"Create New":["Utw\u00f3rz nowe"],"Change Form":["Zmie\u0144 formularz"],"This form has been deleted or is unavailable.":["Ten formularz zosta\u0142 usuni\u0119ty lub jest niedost\u0119pny."],"Form Settings":["Ustawienia formularza"],"Show Form Title on this Page":["Poka\u017c tytu\u0142 formularza na tej stronie"],"Note: For editing SureForms, please refer to the SureForms Editor - ":["Uwaga: Aby edytowa\u0107 SureForms, prosz\u0119 odnie\u015b\u0107 si\u0119 do SureForms Editor -"],"Field preview":["Podgl\u0105d pola"],"General":["Og\u00f3lny"],"Style":["Styl"],"Advanced":["Zaawansowany"],"No tags available":["Brak dost\u0119pnych tag\u00f3w"],"Device":["Urz\u0105dzenie"],"Select Shortcodes":["Wybierz skr\u00f3ty"],"Page Break Label":["Etykieta podzia\u0142u strony"],"Next":["Dalej"],"Back":["Wstecz"],"Reset":["Resetuj"],"Generic tags":["Og\u00f3lne tagi"],"Pixel":["Piksel"],"Em":["Em"],"Select Units":["Wybierz jednostki"],"%s units":["%s jednostki"],"Margin":["Margines"],"Attributes":["Atrybuty"],"Input Pattern":["Wzorzec wej\u015bciowy"],"None":["Brak"],"(###) ###-####":["(###) ###-####"],"(##) ####-####":["(##) ####-####"],"27\/08\/2024":["27\/08\/2024"],"23:59:59":["23:59:59"],"27\/08\/2024 23:59:59":["27\/08\/2024 23:59:59"],"Custom":["Niestandardowy"],"Custom Mask":["Maska niestandardowa"],"Please check the documentation to manage custom input pattern ":["Prosz\u0119 sprawdzi\u0107 dokumentacj\u0119, aby zarz\u0105dza\u0107 niestandardowym wzorcem wej\u015bciowym"],"here":["tutaj"],"Default Value":["Warto\u015b\u0107 domy\u015blna"],"Error Message":["Komunikat o b\u0142\u0119dzie"],"Help Text":["Tekst pomocy"],"Number Format":["Format liczb"],"US Style (Eg: 9,999.99)":["Styl ameryka\u0144ski (np. 9,999.99)"],"EU Style (Eg: 9.999,99)":["Styl UE (np.: 9.999,99)"],"Minimum Value":["Warto\u015b\u0107 minimalna"],"Maximum Value":["Maksymalna warto\u015b\u0107"],"Please check the Minimum and Maximum value":["Prosz\u0119 sprawdzi\u0107 warto\u015b\u0107 minimaln\u0105 i maksymaln\u0105"],"Enable Email Confirmation":["W\u0142\u0105cz potwierdzenie e-mail"],"Checked by Default":["Zaznaczone domy\u015blnie"],"Error message":["Komunikat o b\u0142\u0119dzie"],"Checked by default":["Domy\u015blnie zaznaczone"],"Please add a option props to MultiButtonsControl":["Prosz\u0119 doda\u0107 opcj\u0119 props do MultiButtonsControl"],"Icon Library":["Biblioteka ikon"],"Close":["Zamknij"],"All Icons":["Wszystkie ikony"],"Other":["Inne"],"No Icons Found":["Nie znaleziono ikon"],"Insert Icon":["Wstaw ikon\u0119"],"Change Icon":["Zmie\u0144 ikon\u0119"],"Choose Icon":["Wybierz ikon\u0119"],"Confirm":["Potwierd\u017a"],"Cancel":["Anuluj"],"Processing\u2026":["Przetwarzanie\u2026"],"Select Video":["Wybierz wideo"],"Change Video":["Zmie\u0144 wideo"],"Select Lottie Animation":["Wybierz animacj\u0119 Lottie"],"Change Lottie Animation":["Zmie\u0144 animacj\u0119 Lottie"],"Upload SVG":["Prze\u015blij SVG"],"Change SVG":["Zmie\u0144 SVG"],"Select Image":["Wybierz obraz"],"Change Image":["Zmie\u0144 obraz"],"Upload SVG?":["Przes\u0142a\u0107 SVG?"],"Upload SVG can be potentially risky. Are you sure?":["Przesy\u0142anie plik\u00f3w SVG mo\u017ce by\u0107 potencjalnie ryzykowne. Czy jeste\u015b pewien?"],"Upload Anyway":["Prze\u015blij mimo to"],"Bulk Add":["Dodaj masowo"],"Bulk Add Options":["Opcje masowego dodawania"],"Enter each option on a new line.":["Wprowad\u017a ka\u017cd\u0105 opcj\u0119 w nowej linii."],"Insert Options":["Opcje wstawiania"],"Full Width":["Pe\u0142na szeroko\u015b\u0107"],"Option Type":["Typ opcji"],"Edit Options":["Edytuj opcje"],"Add New Option":["Dodaj now\u0105 opcj\u0119"],"ADD":["DODAJ"],"Enable Auto Country Detection":["W\u0142\u0105cz automatyczne wykrywanie kraju"],"%s Width":["Szeroko\u015b\u0107 %s"],"Upgrade":["Aktualizacja"],"Clear":["Wyczy\u015b\u0107"],"Select Color":["Wybierz kolor"],"Primary Color":["Kolor podstawowy"],"Text Color":["Kolor tekstu"],"Field Spacing":["Odst\u0119py mi\u0119dzy polami"],"Small":["Ma\u0142y"],"Large":["Du\u017cy"],"Left":["Lewo"],"Center":["Centrum"],"Right":["Prawo"],"Color":["Kolor"],"Background Color":["Kolor t\u0142a"],"Auto":["Samoch\u00f3d"],"Default":["Domy\u015blny"],"Normal":["Normalny"],"%":["%"],"Top":["G\u00f3ra"],"Bottom":["D\u00f3\u0142"],"Width":["Szeroko\u015b\u0107"],"Size":["Rozmiar"],"EM":["EM"],"Padding":["Wype\u0142nienie"],"Color 1":["Kolor 1"],"Color 2":["Kolor 2"],"Type":["Rodzaj"],"Linear":["Liniowy"],"Radial":["Promieniowy"],"Location 1":["Lokalizacja 1"],"Location 2":["Lokalizacja 2"],"Angle":["K\u0105t"],"Classic":["Klasyczny"],"Gradient":["Gradient"],"Horizontal":["Poziomy"],"Vertical":["Pionowy"],"Background":["T\u0142o"],"Cover":["Ok\u0142adka"],"Contain":["Zawiera\u0107"],"Layout":["Uk\u0142ad"],"Overlay":["Nak\u0142adka"],"No Repeat":["Bez powt\u00f3rki"],"Overlay Opacity":["Przezroczysto\u015b\u0107 nak\u0142adki"],"Conditional Logic":["Logika warunkowa"],"Upgrade to the SureForms Starter Plan to create dynamic forms that adapt based on user input, offering a personalised and efficient form experience.":["Ulepsz do planu SureForms Starter, aby tworzy\u0107 dynamiczne formularze, kt\u00f3re dostosowuj\u0105 si\u0119 na podstawie danych wprowadzonych przez u\u017cytkownika, oferuj\u0105c spersonalizowane i efektywne do\u015bwiadczenie formularza."],"Enable Conditional Logic":["W\u0142\u0105cz logik\u0119 warunkow\u0105"],"this field if":["to pole, je\u015bli"],"Configure Conditions":["Skonfiguruj warunki"],"Premium":["Premium"],"Overlay Type":["Typ nak\u0142adki"],"Image Overlay Color":["Kolor nak\u0142adki obrazu"],"Image Position":["Pozycja obrazu"],"Attachment":["Za\u0142\u0105cznik"],"Fixed":["Naprawione"],"Blend Mode":["Tryb mieszania"],"Multiply":["Mno\u017cenie"],"Screen":["Ekran"],"Darken":["Przyciemnij"],"Lighten":["Rozja\u015bnij"],"Color Dodge":["Rozja\u015bnianie koloru"],"Saturation":["Nasycenie"],"Repeat-x":["Powt\u00f3rz-x"],"Repeat-y":["Powt\u00f3rz-y"],"PX":["PX"],"Button":["Przycisk"],"Prefix Label":["Etykieta prefiksu"],"Suffix Label":["Etykieta sufiksu"],"Border Radius":["Promie\u0144 obramowania"],"Form Theme":["Motyw formularza"],"Select Gradient":["Wybierz gradient"],"Unlock Conditional Logic Editor":["Odblokuj edytor logiki warunkowej"],"Rich Text Editor":["Edytor tekstu sformatowanego"],"Read Only":["Tylko do odczytu"],"Select Country":["Wybierz kraj"],"Default Country":["Domy\u015blny kraj"],"Subscription":["Subskrypcja"],"One Time":["Jeden raz"],"Unique Entry":["Unikalny wpis"],"Maximum Characters":["Maksymalna liczba znak\u00f3w"],"Textarea Height":["Wysoko\u015b\u0107 pola tekstowego"],"Minimum Selections":["Minimalna liczba wybor\u00f3w"],"Maximum Selections":["Maksymalna liczba wybor\u00f3w"],"Add Numeric Values to Options":["Dodaj warto\u015bci numeryczne do opcji"],"Single Choice Only":["Tylko jeden wyb\u00f3r"],"Enable Dropdown Search":["W\u0142\u0105cz wyszukiwanie w rozwijanym menu"],"Allow Multiple":["Zezw\u00f3l na wiele"],"%1$s fields are required. Please configure these fields in the block settings.":["Wymagane s\u0105 pola %1$s. Prosz\u0119 skonfigurowa\u0107 te pola w ustawieniach bloku."],"%1$s field is required. Please configure this field in the block settings.":["Pole %1$s jest wymagane. Prosz\u0119 skonfigurowa\u0107 to pole w ustawieniach bloku."],"You need to configure a payment account to collect payments from this form. Please configure your payment provider to proceed.":["Musisz skonfigurowa\u0107 konto p\u0142atnicze, aby zbiera\u0107 p\u0142atno\u015bci z tego formularza. Prosz\u0119 skonfigurowa\u0107 swojego dostawc\u0119 p\u0142atno\u015bci, aby kontynuowa\u0107."],"Configure Payment Account":["Skonfiguruj konto p\u0142atnicze"],"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.":["To jest symbol zast\u0119pczy dla bloku p\u0142atno\u015bci. Rzeczywiste pola p\u0142atno\u015bci dla skonfigurowanego dostawcy p\u0142atno\u015bci pojawi\u0105 si\u0119 dopiero po podgl\u0105dzie lub opublikowaniu formularza."],"2 Payments":["2 P\u0142atno\u015bci"],"3 Payments":["3 P\u0142atno\u015bci"],"4 Payments":["4 P\u0142atno\u015bci"],"5 Payments":["5 P\u0142atno\u015bci"],"Never":["Nigdy"],"Stop Subscription After":["Zatrzymaj subskrypcj\u0119 po"],"Choose when to automatically stop the subscription":["Wybierz, kiedy automatycznie zako\u0144czy\u0107 subskrypcj\u0119"],"Number of Payments":["Liczba p\u0142atno\u015bci"],"Enter a number between 1 to 100":["Wprowad\u017a liczb\u0119 od 1 do 100"],"Form Field":["Pole formularza"],"Payment Type":["Typ p\u0142atno\u015bci"],"Subscription Plan Name":["Nazwa Planu Subskrypcji"],"Billing Interval":["Okres rozliczeniowy"],"Daily":["Codziennie"],"Weekly":["Tygodniowo"],"Monthly":["Miesi\u0119cznie"],"Quarterly":["Kwartalnie"],"Yearly":["Rocznie"],"Amount Type":["Typ kwoty"],"Fixed Amount":["Sta\u0142a kwota"],"Dynamic Amount":["Dynamiczna kwota"],"Choose whether to charge a fixed amount or charge the amount based on user input in other form fields.":["Wybierz, czy naliczy\u0107 sta\u0142\u0105 kwot\u0119, czy naliczy\u0107 kwot\u0119 na podstawie danych wprowadzonych przez u\u017cytkownika w innych polach formularza."],"Set the exact amount you want to charge. Users won\u2019t be able to change it":["Ustaw dok\u0142adn\u0105 kwot\u0119, kt\u00f3r\u0105 chcesz pobra\u0107. U\u017cytkownicy nie b\u0119d\u0105 mogli jej zmieni\u0107"],"Choose Amount Field":["Wybierz pole kwoty"],"Select a field\u2026":["Wybierz pole\u2026"],"Pick a field from your form like a number, dropdown, or multichoice whose value should decide the payment amount.":["Wybierz pole z formularza, takie jak liczba, lista rozwijana lub wielokrotny wyb\u00f3r, kt\u00f3rego warto\u015b\u0107 powinna decydowa\u0107 o kwocie p\u0142atno\u015bci."],"Minimum Amount":["Minimalna kwota"],"Set the minimum amount users can enter (0 for no minimum)":["Ustaw minimaln\u0105 kwot\u0119, jak\u0105 u\u017cytkownicy mog\u0105 wprowadzi\u0107 (0 dla braku minimum)"],"Customer Name Field (Required)":["Pole Nazwa Klienta (Wymagane)"],"Customer Name Field (Optional)":["Pole Nazwa Klienta (Opcjonalne)"],"Select the input field that contains the customer name (Required for subscriptions)":["Wybierz pole wej\u015bciowe, kt\u00f3re zawiera nazwisko klienta (Wymagane dla subskrypcji)"],"Select the input field that contains the customer name":["Wybierz pole wej\u015bciowe, kt\u00f3re zawiera nazwisko klienta"],"Customer Email Field (Required)":["Pole e-mail klienta (wymagane)"],"Select the email field that contains the customer email":["Wybierz pole e-mail, kt\u00f3re zawiera adres e-mail klienta"],"Payment":["P\u0142atno\u015b\u0107"],"%s - Order ID":["%s - Identyfikator zam\u00f3wienia"],"%s - Amount":["%s - Kwota"],"%s - Customer Email":["%s - E-mail klienta"],"%s - Customer Name":["%s - Nazwa klienta"],"%s - Status":["%s - Status"],"Button Alignment":["Wyr\u00f3wnanie przycisku"],"Placeholder":["Symbol zast\u0119pczy"],"Preselect this option":["Wst\u0119pnie wybierz t\u0119 opcj\u0119"],"Restrict Country Codes":["Ogranicz kody kraj\u00f3w"],"Restriction Type":["Typ ograniczenia"],"Allow":["Zezw\u00f3l"],"Block":["Blok"],"Select Allowed Countries":["Wybierz dozwolone kraje"],"Choose countries\u2026":["Wybierz kraje\u2026"],"Choose which country codes users can select in the phone number field. Leave empty to allow all country codes.":["Wybierz, kt\u00f3re kody kraj\u00f3w u\u017cytkownicy mog\u0105 wybra\u0107 w polu numeru telefonu. Pozostaw puste, aby zezwoli\u0107 na wszystkie kody kraj\u00f3w."],"Select Blocked Countries":["Wybierz zablokowane kraje"],"These countries will be hidden from the dropdown.":["Te kraje b\u0119d\u0105 ukryte w rozwijanym menu."],"Bulk Edit":["Masowa edycja"],"Select Layout":["Wybierz uk\u0142ad"],"Number of Columns":["Liczba kolumn"],"Validation Message for Duplicate":["Komunikat walidacyjny dla duplikatu"],"Click here to insert a form":["Kliknij tutaj, aby wstawi\u0107 formularz"],"Inherit Form's Original Style":["Odziedzicz oryginalny styl formularza"],"Text on Primary":["Tekst na g\u0142\u00f3wnym"],"%s - Description":["%s - Opis"],"Upgrade to Unlock":["Uaktualnij, aby odblokowa\u0107"],"Custom (Premium)":["Niestandardowy (Premium)"],"Select a theme style for this form embed.":["Wybierz styl motywu dla tego osadzenia formularza."],"Colors":["Kolory"],"Advanced Styling":["Zaawansowane stylizowanie"],"Unlock Custom Styling":["Odblokuj niestandardowe stylizacje"],"Switch to Custom Mode to take full control of your form's design and spacing.":["Prze\u0142\u0105cz si\u0119 na tryb niestandardowy, aby przej\u0105\u0107 pe\u0142n\u0105 kontrol\u0119 nad projektem i odst\u0119pami formularza."],"Full color control (buttons, fields, text)":["Pe\u0142na kontrola koloru (przyciski, pola, tekst)"],"Row and column gap control":["Kontrola odst\u0119p\u00f3w mi\u0119dzy wierszami i kolumnami"],"Field spacing and layout precision":["Precyzja rozmieszczenia i odst\u0119p\u00f3w p\u00f3l"],"Complete button styling":["Kompletne stylizowanie przycisku"],"Payment Description":["Opis p\u0142atno\u015bci"],"Shown on payment receipts and in your payment dashboard (Stripe and PayPal). Leave blank to use the default.":["Pokazywane na paragonach p\u0142atno\u015bci i w panelu p\u0142atno\u015bci (Stripe i PayPal). Pozostaw puste, aby u\u017cy\u0107 domy\u015blnego."],"Slug":["\u015alimak"],"Auto-generated on save":["Automatycznie generowane przy zapisie"],"This slug is already used by another field. It will revert to the previous value.":["Ten slug jest ju\u017c u\u017cywany przez inne pole. Zostanie przywr\u00f3cony do poprzedniej warto\u015bci."],"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.":["Zmiana slug mo\u017ce spowodowa\u0107 problemy z przesy\u0142aniem formularzy, logik\u0105 warunkow\u0105, integracjami lub innymi funkcjami, kt\u00f3re obecnie odwo\u0142uj\u0105 si\u0119 do tego slug. B\u0119dziesz musia\u0142 r\u0119cznie zaktualizowa\u0107 wszystkie takie odwo\u0142ania."],"Field Slug":["Slug pola"],"Location Services":["Us\u0142ugi lokalizacyjne"],"Unlock Address Autocomplete":["Odblokuj autouzupe\u0142nianie adresu"],"Upgrade to enable Google Address Autocomplete with interactive map preview, making address entry faster and more accurate for your users.":["Ulepsz, aby w\u0142\u0105czy\u0107 funkcj\u0119 autouzupe\u0142niania adres\u00f3w Google z interaktywnym podgl\u0105dem mapy, co przyspieszy i zwi\u0119kszy dok\u0142adno\u015b\u0107 wprowadzania adres\u00f3w dla Twoich u\u017cytkownik\u00f3w."],"Enable Google Autocomplete":["W\u0142\u0105cz autouzupe\u0142nianie Google"],"Show Interactive Map":["Poka\u017c interaktywn\u0105 map\u0119"],"Payments Per Page":["P\u0142atno\u015bci za stron\u0119"],"Show Subscriptions Section":["Poka\u017c sekcj\u0119 subskrypcji"],"Show a dedicated subscriptions section above payment history.":["Poka\u017c dedykowan\u0105 sekcj\u0119 subskrypcji nad histori\u0105 p\u0142atno\u015bci."],"Payment Dashboard":["Panel P\u0142atno\u015bci"],"View your payments and manage subscriptions in a single dashboard.":["Przegl\u0105daj swoje p\u0142atno\u015bci i zarz\u0105dzaj subskrypcjami w jednym panelu."],"Dynamic Default Value":["Dynamiczna warto\u015b\u0107 domy\u015blna"]}}} \ No newline at end of file +{"translation-revision-date":"2025-01-02T08:44:41+00:00","generator":"WP-CLI\/2.12.0","source":"assets\/build\/blocks.js","domain":"messages","locale_data":{"messages":{"":{"domain":"messages","lang":"en","plural-forms":"nplurals=2; plural=(n != 1);"},"Settings":["Ustawienia"],"Search":["Szukaj"],"Fields":["Pola"],"Image":["Obraz"],"Submit":["Prze\u015blij"],"Required":["Wymagane"],"Form Title":["Tytu\u0142 formularza"],"Show":["Poka\u017c"],"Hide":["Ukryj"],"Edit Form":["Edytuj formularz"],"Icon":["Ikona"],"Desktop":["Pulpit"],"Medium":["\u015aredni"],"Mobile":["Telefon kom\u00f3rkowy"],"Repeat":["Powt\u00f3rz"],"Scroll":["Przewi\u0144"],"Tablet":["Tablet"],"Basic":["Podstawowy"],"(no title)":["(brak tytu\u0142u)"],"Select a Form":["Wybierz formularz"],"No forms found\u2026":["Nie znaleziono formularzy\u2026"],"Choose":["Wybierz"],"Create New":["Utw\u00f3rz nowe"],"Change Form":["Zmie\u0144 formularz"],"This form has been deleted or is unavailable.":["Ten formularz zosta\u0142 usuni\u0119ty lub jest niedost\u0119pny."],"Form Settings":["Ustawienia formularza"],"Show Form Title on this Page":["Poka\u017c tytu\u0142 formularza na tej stronie"],"Note: For editing SureForms, please refer to the SureForms Editor - ":["Uwaga: Aby edytowa\u0107 SureForms, prosz\u0119 odnie\u015b\u0107 si\u0119 do SureForms Editor -"],"Field preview":["Podgl\u0105d pola"],"General":["Og\u00f3lny"],"Style":["Styl"],"Advanced":["Zaawansowany"],"No tags available":["Brak dost\u0119pnych tag\u00f3w"],"Device":["Urz\u0105dzenie"],"Select Shortcodes":["Wybierz skr\u00f3ty"],"Page Break Label":["Etykieta podzia\u0142u strony"],"Next":["Dalej"],"Back":["Wstecz"],"Reset":["Resetuj"],"Generic tags":["Og\u00f3lne tagi"],"Pixel":["Piksel"],"Em":["Em"],"Select Units":["Wybierz jednostki"],"%s units":["%s jednostki"],"Margin":["Margines"],"Attributes":["Atrybuty"],"Input Pattern":["Wzorzec wej\u015bciowy"],"None":["Brak"],"(###) ###-####":["(###) ###-####"],"(##) ####-####":["(##) ####-####"],"27\/08\/2024":["27\/08\/2024"],"23:59:59":["23:59:59"],"27\/08\/2024 23:59:59":["27\/08\/2024 23:59:59"],"Custom":["Niestandardowy"],"Custom Mask":["Maska niestandardowa"],"Please check the documentation to manage custom input pattern ":["Prosz\u0119 sprawdzi\u0107 dokumentacj\u0119, aby zarz\u0105dza\u0107 niestandardowym wzorcem wej\u015bciowym"],"here":["tutaj"],"Default Value":["Warto\u015b\u0107 domy\u015blna"],"Error Message":["Komunikat o b\u0142\u0119dzie"],"Help Text":["Tekst pomocy"],"Number Format":["Format liczb"],"US Style (Eg: 9,999.99)":["Styl ameryka\u0144ski (np. 9,999.99)"],"EU Style (Eg: 9.999,99)":["Styl UE (np.: 9.999,99)"],"Minimum Value":["Warto\u015b\u0107 minimalna"],"Maximum Value":["Maksymalna warto\u015b\u0107"],"Please check the Minimum and Maximum value":["Prosz\u0119 sprawdzi\u0107 warto\u015b\u0107 minimaln\u0105 i maksymaln\u0105"],"Enable Email Confirmation":["W\u0142\u0105cz potwierdzenie e-mail"],"Checked by Default":["Zaznaczone domy\u015blnie"],"Error message":["Komunikat o b\u0142\u0119dzie"],"Checked by default":["Domy\u015blnie zaznaczone"],"Please add a option props to MultiButtonsControl":["Prosz\u0119 doda\u0107 opcj\u0119 props do MultiButtonsControl"],"Icon Library":["Biblioteka ikon"],"Close":["Zamknij"],"All Icons":["Wszystkie ikony"],"Other":["Inne"],"No Icons Found":["Nie znaleziono ikon"],"Insert Icon":["Wstaw ikon\u0119"],"Change Icon":["Zmie\u0144 ikon\u0119"],"Choose Icon":["Wybierz ikon\u0119"],"Confirm":["Potwierd\u017a"],"Cancel":["Anuluj"],"Processing\u2026":["Przetwarzanie\u2026"],"Select Video":["Wybierz wideo"],"Change Video":["Zmie\u0144 wideo"],"Select Lottie Animation":["Wybierz animacj\u0119 Lottie"],"Change Lottie Animation":["Zmie\u0144 animacj\u0119 Lottie"],"Upload SVG":["Prze\u015blij SVG"],"Change SVG":["Zmie\u0144 SVG"],"Select Image":["Wybierz obraz"],"Change Image":["Zmie\u0144 obraz"],"Upload SVG?":["Przes\u0142a\u0107 SVG?"],"Upload SVG can be potentially risky. Are you sure?":["Przesy\u0142anie plik\u00f3w SVG mo\u017ce by\u0107 potencjalnie ryzykowne. Czy jeste\u015b pewien?"],"Upload Anyway":["Prze\u015blij mimo to"],"Bulk Add":["Dodaj masowo"],"Bulk Add Options":["Opcje masowego dodawania"],"Enter each option on a new line.":["Wprowad\u017a ka\u017cd\u0105 opcj\u0119 w nowej linii."],"Insert Options":["Opcje wstawiania"],"Full Width":["Pe\u0142na szeroko\u015b\u0107"],"Option Type":["Typ opcji"],"Edit Options":["Edytuj opcje"],"Add New Option":["Dodaj now\u0105 opcj\u0119"],"ADD":["DODAJ"],"Enable Auto Country Detection":["W\u0142\u0105cz automatyczne wykrywanie kraju"],"%s Width":["Szeroko\u015b\u0107 %s"],"Upgrade":["Aktualizacja"],"Clear":["Wyczy\u015b\u0107"],"Select Color":["Wybierz kolor"],"Primary Color":["Kolor podstawowy"],"Text Color":["Kolor tekstu"],"Field Spacing":["Odst\u0119py mi\u0119dzy polami"],"Small":["Ma\u0142y"],"Large":["Du\u017cy"],"Left":["Lewo"],"Center":["Centrum"],"Right":["Prawo"],"Color":["Kolor"],"Background Color":["Kolor t\u0142a"],"Auto":["Samoch\u00f3d"],"Default":["Domy\u015blny"],"Normal":["Normalny"],"%":["%"],"Top":["G\u00f3ra"],"Bottom":["D\u00f3\u0142"],"Width":["Szeroko\u015b\u0107"],"Size":["Rozmiar"],"EM":["EM"],"Padding":["Wype\u0142nienie"],"Color 1":["Kolor 1"],"Color 2":["Kolor 2"],"Type":["Rodzaj"],"Linear":["Liniowy"],"Radial":["Promieniowy"],"Location 1":["Lokalizacja 1"],"Location 2":["Lokalizacja 2"],"Angle":["K\u0105t"],"Classic":["Klasyczny"],"Gradient":["Gradient"],"Horizontal":["Poziomy"],"Vertical":["Pionowy"],"Background":["T\u0142o"],"Cover":["Ok\u0142adka"],"Contain":["Zawiera\u0107"],"Layout":["Uk\u0142ad"],"Overlay":["Nak\u0142adka"],"No Repeat":["Bez powt\u00f3rki"],"Overlay Opacity":["Przezroczysto\u015b\u0107 nak\u0142adki"],"Conditional Logic":["Logika warunkowa"],"Upgrade to the SureForms Starter Plan to create dynamic forms that adapt based on user input, offering a personalised and efficient form experience.":["Ulepsz do planu SureForms Starter, aby tworzy\u0107 dynamiczne formularze, kt\u00f3re dostosowuj\u0105 si\u0119 na podstawie danych wprowadzonych przez u\u017cytkownika, oferuj\u0105c spersonalizowane i efektywne do\u015bwiadczenie formularza."],"Enable Conditional Logic":["W\u0142\u0105cz logik\u0119 warunkow\u0105"],"this field if":["to pole, je\u015bli"],"Configure Conditions":["Skonfiguruj warunki"],"Premium":["Premium"],"Overlay Type":["Typ nak\u0142adki"],"Image Overlay Color":["Kolor nak\u0142adki obrazu"],"Image Position":["Pozycja obrazu"],"Attachment":["Za\u0142\u0105cznik"],"Fixed":["Naprawione"],"Blend Mode":["Tryb mieszania"],"Multiply":["Mno\u017cenie"],"Screen":["Ekran"],"Darken":["Przyciemnij"],"Lighten":["Rozja\u015bnij"],"Color Dodge":["Rozja\u015bnianie koloru"],"Saturation":["Nasycenie"],"Repeat-x":["Powt\u00f3rz-x"],"Repeat-y":["Powt\u00f3rz-y"],"PX":["PX"],"Button":["Przycisk"],"Prefix Label":["Etykieta prefiksu"],"Suffix Label":["Etykieta sufiksu"],"Border Radius":["Promie\u0144 obramowania"],"Form Theme":["Motyw formularza"],"Select Gradient":["Wybierz gradient"],"Unlock Conditional Logic Editor":["Odblokuj edytor logiki warunkowej"],"Rich Text Editor":["Edytor tekstu sformatowanego"],"Read Only":["Tylko do odczytu"],"Select Country":["Wybierz kraj"],"Default Country":["Domy\u015blny kraj"],"Subscription":["Subskrypcja"],"One Time":["Jeden raz"],"Unique Entry":["Unikalny wpis"],"Maximum Characters":["Maksymalna liczba znak\u00f3w"],"Textarea Height":["Wysoko\u015b\u0107 pola tekstowego"],"Minimum Selections":["Minimalna liczba wybor\u00f3w"],"Maximum Selections":["Maksymalna liczba wybor\u00f3w"],"Add Numeric Values to Options":["Dodaj warto\u015bci numeryczne do opcji"],"Single Choice Only":["Tylko jeden wyb\u00f3r"],"Enable Dropdown Search":["W\u0142\u0105cz wyszukiwanie w rozwijanym menu"],"Allow Multiple":["Zezw\u00f3l na wiele"],"%1$s fields are required. Please configure these fields in the block settings.":["Wymagane s\u0105 pola %1$s. Prosz\u0119 skonfigurowa\u0107 te pola w ustawieniach bloku."],"%1$s field is required. Please configure this field in the block settings.":["Pole %1$s jest wymagane. Prosz\u0119 skonfigurowa\u0107 to pole w ustawieniach bloku."],"You need to configure a payment account to collect payments from this form. Please configure your payment provider to proceed.":["Musisz skonfigurowa\u0107 konto p\u0142atnicze, aby zbiera\u0107 p\u0142atno\u015bci z tego formularza. Prosz\u0119 skonfigurowa\u0107 swojego dostawc\u0119 p\u0142atno\u015bci, aby kontynuowa\u0107."],"Configure Payment Account":["Skonfiguruj konto p\u0142atnicze"],"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.":["To jest symbol zast\u0119pczy dla bloku p\u0142atno\u015bci. Rzeczywiste pola p\u0142atno\u015bci dla skonfigurowanego dostawcy p\u0142atno\u015bci pojawi\u0105 si\u0119 dopiero po podgl\u0105dzie lub opublikowaniu formularza."],"2 Payments":["2 P\u0142atno\u015bci"],"3 Payments":["3 P\u0142atno\u015bci"],"4 Payments":["4 P\u0142atno\u015bci"],"5 Payments":["5 P\u0142atno\u015bci"],"Never":["Nigdy"],"Stop Subscription After":["Zatrzymaj subskrypcj\u0119 po"],"Choose when to automatically stop the subscription":["Wybierz, kiedy automatycznie zako\u0144czy\u0107 subskrypcj\u0119"],"Number of Payments":["Liczba p\u0142atno\u015bci"],"Enter a number between 1 to 100":["Wprowad\u017a liczb\u0119 od 1 do 100"],"Form Field":["Pole formularza"],"Payment Type":["Typ p\u0142atno\u015bci"],"Subscription Plan Name":["Nazwa Planu Subskrypcji"],"Billing Interval":["Okres rozliczeniowy"],"Daily":["Codziennie"],"Weekly":["Tygodniowo"],"Monthly":["Miesi\u0119cznie"],"Quarterly":["Kwartalnie"],"Yearly":["Rocznie"],"Amount Type":["Typ kwoty"],"Fixed Amount":["Sta\u0142a kwota"],"Dynamic Amount":["Dynamiczna kwota"],"Choose whether to charge a fixed amount or charge the amount based on user input in other form fields.":["Wybierz, czy naliczy\u0107 sta\u0142\u0105 kwot\u0119, czy naliczy\u0107 kwot\u0119 na podstawie danych wprowadzonych przez u\u017cytkownika w innych polach formularza."],"Set the exact amount you want to charge. Users won\u2019t be able to change it":["Ustaw dok\u0142adn\u0105 kwot\u0119, kt\u00f3r\u0105 chcesz pobra\u0107. U\u017cytkownicy nie b\u0119d\u0105 mogli jej zmieni\u0107"],"Choose Amount Field":["Wybierz pole kwoty"],"Select a field\u2026":["Wybierz pole\u2026"],"Minimum Amount":["Minimalna kwota"],"Set the minimum amount users can enter (0 for no minimum)":["Ustaw minimaln\u0105 kwot\u0119, jak\u0105 u\u017cytkownicy mog\u0105 wprowadzi\u0107 (0 dla braku minimum)"],"Customer Name Field (Required)":["Pole Nazwa Klienta (Wymagane)"],"Customer Name Field (Optional)":["Pole Nazwa Klienta (Opcjonalne)"],"Select the input field that contains the customer name (Required for subscriptions)":["Wybierz pole wej\u015bciowe, kt\u00f3re zawiera nazwisko klienta (Wymagane dla subskrypcji)"],"Select the input field that contains the customer name":["Wybierz pole wej\u015bciowe, kt\u00f3re zawiera nazwisko klienta"],"Customer Email Field (Required)":["Pole e-mail klienta (wymagane)"],"Select the email field that contains the customer email":["Wybierz pole e-mail, kt\u00f3re zawiera adres e-mail klienta"],"Payment":["P\u0142atno\u015b\u0107"],"%s - Order ID":["%s - Identyfikator zam\u00f3wienia"],"%s - Amount":["%s - Kwota"],"%s - Customer Email":["%s - E-mail klienta"],"%s - Customer Name":["%s - Nazwa klienta"],"%s - Status":["%s - Status"],"Button Alignment":["Wyr\u00f3wnanie przycisku"],"Placeholder":["Symbol zast\u0119pczy"],"Preselect this option":["Wst\u0119pnie wybierz t\u0119 opcj\u0119"],"Restrict Country Codes":["Ogranicz kody kraj\u00f3w"],"Restriction Type":["Typ ograniczenia"],"Allow":["Zezw\u00f3l"],"Block":["Blok"],"Select Allowed Countries":["Wybierz dozwolone kraje"],"Choose countries\u2026":["Wybierz kraje\u2026"],"Choose which country codes users can select in the phone number field. Leave empty to allow all country codes.":["Wybierz, kt\u00f3re kody kraj\u00f3w u\u017cytkownicy mog\u0105 wybra\u0107 w polu numeru telefonu. Pozostaw puste, aby zezwoli\u0107 na wszystkie kody kraj\u00f3w."],"Select Blocked Countries":["Wybierz zablokowane kraje"],"These countries will be hidden from the dropdown.":["Te kraje b\u0119d\u0105 ukryte w rozwijanym menu."],"Bulk Edit":["Masowa edycja"],"Select Layout":["Wybierz uk\u0142ad"],"Number of Columns":["Liczba kolumn"],"Validation Message for Duplicate":["Komunikat walidacyjny dla duplikatu"],"Click here to insert a form":["Kliknij tutaj, aby wstawi\u0107 formularz"],"Inherit Form's Original Style":["Odziedzicz oryginalny styl formularza"],"Text on Primary":["Tekst na g\u0142\u00f3wnym"],"%s - Description":["%s - Opis"],"Upgrade to Unlock":["Uaktualnij, aby odblokowa\u0107"],"Custom (Premium)":["Niestandardowy (Premium)"],"Select a theme style for this form embed.":["Wybierz styl motywu dla tego osadzenia formularza."],"Colors":["Kolory"],"Advanced Styling":["Zaawansowane stylizowanie"],"Unlock Custom Styling":["Odblokuj niestandardowe stylizacje"],"Switch to Custom Mode to take full control of your form's design and spacing.":["Prze\u0142\u0105cz si\u0119 na tryb niestandardowy, aby przej\u0105\u0107 pe\u0142n\u0105 kontrol\u0119 nad projektem i odst\u0119pami formularza."],"Full color control (buttons, fields, text)":["Pe\u0142na kontrola koloru (przyciski, pola, tekst)"],"Row and column gap control":["Kontrola odst\u0119p\u00f3w mi\u0119dzy wierszami i kolumnami"],"Field spacing and layout precision":["Precyzja rozmieszczenia i odst\u0119p\u00f3w p\u00f3l"],"Complete button styling":["Kompletne stylizowanie przycisku"],"Payment Description":["Opis p\u0142atno\u015bci"],"Shown on payment receipts and in your payment dashboard (Stripe and PayPal). Leave blank to use the default.":["Pokazywane na paragonach p\u0142atno\u015bci i w panelu p\u0142atno\u015bci (Stripe i PayPal). Pozostaw puste, aby u\u017cy\u0107 domy\u015blnego."],"Slug":["\u015alimak"],"Auto-generated on save":["Automatycznie generowane przy zapisie"],"This slug is already used by another field. It will revert to the previous value.":["Ten slug jest ju\u017c u\u017cywany przez inne pole. Zostanie przywr\u00f3cony do poprzedniej warto\u015bci."],"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.":["Zmiana slug mo\u017ce spowodowa\u0107 problemy z przesy\u0142aniem formularzy, logik\u0105 warunkow\u0105, integracjami lub innymi funkcjami, kt\u00f3re obecnie odwo\u0142uj\u0105 si\u0119 do tego slug. B\u0119dziesz musia\u0142 r\u0119cznie zaktualizowa\u0107 wszystkie takie odwo\u0142ania."],"Field Slug":["Slug pola"],"Location Services":["Us\u0142ugi lokalizacyjne"],"Unlock Address Autocomplete":["Odblokuj autouzupe\u0142nianie adresu"],"Upgrade to enable Google Address Autocomplete with interactive map preview, making address entry faster and more accurate for your users.":["Ulepsz, aby w\u0142\u0105czy\u0107 funkcj\u0119 autouzupe\u0142niania adres\u00f3w Google z interaktywnym podgl\u0105dem mapy, co przyspieszy i zwi\u0119kszy dok\u0142adno\u015b\u0107 wprowadzania adres\u00f3w dla Twoich u\u017cytkownik\u00f3w."],"Enable Google Autocomplete":["W\u0142\u0105cz autouzupe\u0142nianie Google"],"Show Interactive Map":["Poka\u017c interaktywn\u0105 map\u0119"],"Payments Per Page":["P\u0142atno\u015bci za stron\u0119"],"Show Subscriptions Section":["Poka\u017c sekcj\u0119 subskrypcji"],"Show a dedicated subscriptions section above payment history.":["Poka\u017c dedykowan\u0105 sekcj\u0119 subskrypcji nad histori\u0105 p\u0142atno\u015bci."],"Payment Dashboard":["Panel P\u0142atno\u015bci"],"View your payments and manage subscriptions in a single dashboard.":["Przegl\u0105daj swoje p\u0142atno\u015bci i zarz\u0105dzaj subskrypcjami w jednym panelu."],"Dynamic Default Value":["Dynamiczna warto\u015b\u0107 domy\u015blna"],"Minimum Characters":["Minimalna liczba znak\u00f3w"],"Minimum characters cannot exceed Maximum characters.":["Minimalna liczba znak\u00f3w nie mo\u017ce przekracza\u0107 maksymalnej liczby znak\u00f3w."],"Both":["Oba"],"One-Time Label":["Etykieta jednorazowa"],"Label shown to users for the one-time payment option.":["Etykieta pokazywana u\u017cytkownikom dla opcji jednorazowej p\u0142atno\u015bci."],"Subscription Label":["Etykieta subskrypcji"],"Label shown to users for the subscription option.":["Etykieta pokazywana u\u017cytkownikom dla opcji subskrypcji."],"Default Selection":["Domy\u015blny wyb\u00f3r"],"Which option is pre-selected when the form loads.":["Kt\u00f3ra opcja jest wst\u0119pnie wybrana po za\u0142adowaniu formularza."],"One-Time Amount Type":["Rodzaj kwoty jednorazowej"],"Set how the one-time payment amount is determined.":["Ustaw, jak jest okre\u015blana kwota jednorazowej p\u0142atno\u015bci."],"One-Time Fixed Amount":["Jednorazowa sta\u0142a kwota"],"Amount charged for a one-time payment.":["Kwota pobrana za jednorazow\u0105 p\u0142atno\u015b\u0107."],"One-Time Amount Field":["Pole kwoty jednorazowej"],"Pick a form field whose value determines the one-time payment amount.":["Wybierz pole formularza, kt\u00f3rego warto\u015b\u0107 okre\u015bla kwot\u0119 jednorazowej p\u0142atno\u015bci."],"One-Time Minimum Amount":["Jednorazowa minimalna kwota"],"Minimum amount users can enter for one-time payment (0 for no minimum).":["Minimalna kwota, jak\u0105 u\u017cytkownicy mog\u0105 wprowadzi\u0107 dla jednorazowej p\u0142atno\u015bci (0, je\u015bli brak minimum)."],"Subscription Amount Type":["Typ kwoty subskrypcji"],"Set how the subscription amount is determined.":["Ustaw, jak jest okre\u015blana kwota subskrypcji."],"Subscription Fixed Amount":["Sta\u0142a kwota subskrypcji"],"Recurring amount charged per billing interval.":["Powtarzaj\u0105ca si\u0119 kwota pobierana za ka\u017cdy okres rozliczeniowy."],"Subscription Amount Field":["Pole kwoty subskrypcji"],"Pick a form field whose value determines the subscription amount.":["Wybierz pole formularza, kt\u00f3rego warto\u015b\u0107 okre\u015bla kwot\u0119 subskrypcji."],"Subscription Minimum Amount":["Minimalna kwota subskrypcji"],"Minimum amount users can enter for subscription (0 for no minimum).":["Minimalna kwota, jak\u0105 u\u017cytkownicy mog\u0105 wpisa\u0107 na subskrypcj\u0119 (0 oznacza brak minimum)."],"Pick a field from your form like a number, dropdown, multichoice, or hidden whose value should decide the payment amount.":["Wybierz pole z formularza, takie jak liczba, lista rozwijana, wielokrotny wyb\u00f3r lub ukryte, kt\u00f3rego warto\u015b\u0107 powinna decydowa\u0107 o kwocie p\u0142atno\u015bci."]}}} \ No newline at end of file diff --git a/languages/sureforms-pl_PL.mo b/languages/sureforms-pl_PL.mo index 0f5cf13aa..840030fa4 100644 Binary files a/languages/sureforms-pl_PL.mo and b/languages/sureforms-pl_PL.mo differ diff --git a/languages/sureforms-pl_PL.po b/languages/sureforms-pl_PL.po index bb95475d6..c0d94b529 100644 --- a/languages/sureforms-pl_PL.po +++ b/languages/sureforms-pl_PL.po @@ -106,13 +106,13 @@ msgstr "Edytuj %1$s" #: inc/ai-form-builder/ai-auth.php:93 #: inc/ai-form-builder/ai-auth.php:167 #: inc/background-process.php:112 -#: inc/create-new-form.php:101 +#: inc/create-new-form.php:102 #: inc/duplicate-form.php:176 #: inc/export.php:118 #: inc/export.php:176 #: inc/forms-data.php:88 #: inc/global-settings/global-settings.php:86 -#: inc/global-settings/global-settings.php:403 +#: inc/global-settings/global-settings.php:404 #: inc/rest-api.php:177 msgid "Nonce verification failed." msgstr "Weryfikacja nonce nie powiodła się." @@ -388,7 +388,7 @@ msgid "Selected radio option" msgstr "Wybrana opcja radiowa" #: inc/admin-ajax.php:341 -#: inc/create-new-form.php:63 +#: inc/create-new-form.php:64 #: assets/build/blocks.js:172 #: assets/build/formEditor.js:172 msgid "Submit" @@ -427,53 +427,53 @@ msgid "The message array was not supplied" msgstr "Tablica wiadomości nie została dostarczona" #: inc/ai-form-builder/ai-form-builder.php:68 -#: inc/ai-form-builder/ai-form-builder.php:78 -#: inc/ai-form-builder/ai-helper.php:73 +#: inc/ai-form-builder/ai-form-builder.php:87 +#: inc/ai-form-builder/ai-helper.php:294 msgid "The SureForms AI Middleware encountered an error." msgstr "Oprogramowanie pośredniczące SureForms AI napotkało błąd." -#: inc/ai-form-builder/ai-helper.php:95 +#: inc/ai-form-builder/ai-helper.php:91 msgid "Unable to get usage response." msgstr "Nie można uzyskać odpowiedzi dotyczącej użycia." -#: inc/ai-form-builder/ai-helper.php:148 +#: inc/ai-form-builder/ai-helper.php:145 msgid "The SureForms API server encountered an error." msgstr "Serwer API SureForms napotkał błąd." -#: inc/ai-form-builder/ai-helper.php:174 -#: inc/ai-form-builder/ai-helper.php:206 +#: inc/ai-form-builder/ai-helper.php:167 +#: inc/ai-form-builder/ai-helper.php:199 msgid "An unknown error occurred." msgstr "Wystąpił nieznany błąd." -#: inc/ai-form-builder/ai-helper.php:181 +#: inc/ai-form-builder/ai-helper.php:174 msgid "HTTP Request Failed" msgstr "Żądanie HTTP nie powiodło się" -#: inc/ai-form-builder/ai-helper.php:185 +#: inc/ai-form-builder/ai-helper.php:178 msgid "License Verification Failed" msgstr "Weryfikacja licencji nie powiodła się" -#: inc/ai-form-builder/ai-helper.php:189 +#: inc/ai-form-builder/ai-helper.php:182 msgid "User Verification Failed" msgstr "Weryfikacja użytkownika nie powiodła się" -#: inc/ai-form-builder/ai-helper.php:193 +#: inc/ai-form-builder/ai-helper.php:186 msgid "Referer Mismatch" msgstr "Niezgodność odsyłacza" -#: inc/ai-form-builder/ai-helper.php:197 +#: inc/ai-form-builder/ai-helper.php:190 msgid "Invalid Website URL" msgstr "Nieprawidłowy adres URL strony internetowej" -#: inc/ai-form-builder/ai-helper.php:198 +#: inc/ai-form-builder/ai-helper.php:191 msgid "AI Form Builder does not work on localhost. Please try on a live website." msgstr "Kreator formularzy AI nie działa na localhost. Proszę spróbować na działającej stronie internetowej." -#: inc/ai-form-builder/ai-helper.php:201 +#: inc/ai-form-builder/ai-helper.php:194 msgid "Domain Verification Failed" msgstr "Weryfikacja domeny nie powiodła się" -#: inc/ai-form-builder/ai-helper.php:205 +#: inc/ai-form-builder/ai-helper.php:198 msgid "Unknown Error" msgstr "Nieznany błąd" @@ -481,22 +481,18 @@ msgstr "Nieznany błąd" msgid "Submission id missing." msgstr "Brakuje identyfikatora zgłoszenia." -#: inc/create-new-form.php:113 +#: inc/create-new-form.php:114 msgid "Invalid JSON format." msgstr "Nieprawidłowy format JSON." -#: inc/create-new-form.php:125 +#: inc/create-new-form.php:126 msgid "Missing required properties in form info." msgstr "Brak wymaganych właściwości w informacjach formularza." -#: inc/create-new-form.php:161 +#: inc/create-new-form.php:187 msgid "SureForms Form created successfully." msgstr "Formularz SureForms został pomyślnie utworzony." -#: inc/create-new-form.php:168 -msgid "Error creating SureForms Form, " -msgstr "Błąd podczas tworzenia formularza SureForms," - #: inc/email/email-template.php:46 msgid "New form submission" msgstr "Nowe zgłoszenie formularza" @@ -558,7 +554,7 @@ msgstr "Numer" msgid "Phone" msgstr "Telefon" -#: inc/fields/textarea-markup.php:95 +#: inc/fields/textarea-markup.php:111 msgid "Textarea" msgstr "Pole tekstowe" @@ -601,8 +597,8 @@ msgstr "Nie znaleziono formularzy." #: inc/abilities/settings/get-global-settings.php:192 #: inc/global-settings/email-summary.php:571 -#: inc/global-settings/global-settings.php:250 -#: inc/global-settings/global-settings.php:456 +#: inc/global-settings/global-settings.php:251 +#: inc/global-settings/global-settings.php:457 #: assets/build/settings.js:172 msgid "Monday" msgstr "Poniedziałek" @@ -7009,7 +7005,7 @@ msgstr "Widok ulicy" msgid "Strikethrough" msgstr "Przekreślenie" -#: inc/fields/payment-markup.php:412 +#: inc/fields/payment-markup.php:513 #: modules/gutenberg/icons/icons-v6-3.php:1812 #: assets/build/payments.js:172 msgid "Stripe" @@ -11593,6 +11589,7 @@ msgstr "Zbuduj swój pierwszy formularz" msgid "Invalid nonce action or name." msgstr "Nieprawidłowa akcja lub nazwa nonce." +#: inc/admin/editor-nudge.php:216 #: inc/helper.php:2029 #: inc/helper.php:2037 msgid "Invalid security token." @@ -11776,7 +11773,7 @@ msgstr "Odkryj SureDash" msgid "Something went wrong. We have logged the error for further investigation" msgstr "Coś poszło nie tak. Zarejestrowaliśmy błąd do dalszego zbadania" -#: inc/field-validation.php:273 +#: inc/field-validation.php:276 msgid "Field is not valid." msgstr "Pole jest nieprawidłowe." @@ -11934,82 +11931,82 @@ msgstr "Nie dostarczono danych formularzy do importu." msgid "Invalid form data structure provided." msgstr "Podano nieprawidłową strukturę danych formularza." -#: inc/fields/payment-markup.php:249 +#: inc/fields/payment-markup.php:346 #: inc/payments/payment-helper.php:543 msgid "Subscription Plan" msgstr "Plan subskrypcji" #. translators: 1: Amount with currency, 2: Interval (day/week/month/quarter/year) -#: inc/fields/payment-markup.php:288 +#: inc/fields/payment-markup.php:672 #, php-format msgid "%1$s per %2$s (until cancelled)" msgstr "%1$s na %2$s (do odwołania)" #. translators: 1: Amount with currency, 2: Interval (day/week/month/quarter/year), 3: Number of billing cycles -#: inc/fields/payment-markup.php:297 +#: inc/fields/payment-markup.php:681 #, php-format msgid "%1$s per %2$s (%3$s payments)" msgstr "%1$s na %2$s (%3$s płatności)" #. translators: 1: Amount with currency, 2: Interval (day/week/month/quarter/year) -#: inc/fields/payment-markup.php:307 +#: inc/fields/payment-markup.php:691 #, php-format msgid "%1$s per %2$s" msgstr "%1$s na %2$s" #. translators: 1: Amount with currency placeholder, 2: Interval (day/week/month/quarter/year) -#: inc/fields/payment-markup.php:334 +#: inc/fields/payment-markup.php:714 #, php-format msgid "{amount} per %s (until cancelled)" msgstr "{amount} na %s (do odwołania)" #. translators: 1: Amount with currency placeholder, 2: Interval (day/week/month/quarter/year), 3: Number of billing cycles -#: inc/fields/payment-markup.php:337 +#: inc/fields/payment-markup.php:717 #, php-format msgid "{amount} per %1$s (%2$s payments)" msgstr "{amount} na %1$s (%2$s płatności)" #. translators: 1: Amount with currency placeholder, 2: Interval (day/week/month/quarter/year) -#: inc/fields/payment-markup.php:340 +#: inc/fields/payment-markup.php:720 #, php-format msgid "{amount} per %s" msgstr "{amount} na %s" #. translators: %s: Minimum amount with currency -#: inc/fields/payment-markup.php:353 +#: inc/fields/payment-markup.php:740 #, php-format msgid "Minimum amount: %s" msgstr "Minimalna kwota: %s" -#: inc/fields/payment-markup.php:385 +#: inc/fields/payment-markup.php:486 msgid "Processing payment..." msgstr "Przetwarzanie płatności..." -#: inc/fields/payment-markup.php:579 +#: inc/fields/payment-markup.php:906 msgid "day" msgstr "dzień" -#: inc/fields/payment-markup.php:580 +#: inc/fields/payment-markup.php:907 msgid "week" msgstr "tydzień" -#: inc/fields/payment-markup.php:581 +#: inc/fields/payment-markup.php:908 msgid "month" msgstr "miesiąc" -#: inc/fields/payment-markup.php:582 +#: inc/fields/payment-markup.php:909 msgid "quarter" msgstr "kwartał" -#: inc/fields/payment-markup.php:583 +#: inc/fields/payment-markup.php:910 msgid "year" msgstr "rok" -#: inc/fields/payment-markup.php:608 +#: inc/fields/payment-markup.php:935 msgid "Test mode is enabled:" msgstr "Tryb testowy jest włączony:" -#: inc/fields/payment-markup.php:610 +#: inc/fields/payment-markup.php:937 msgid "Click here to enable live mode and accept payment" msgstr "Kliknij tutaj, aby włączyć tryb na żywo i zaakceptować płatność" @@ -12192,6 +12189,7 @@ msgstr "Nieznana forma" msgid "N/A" msgstr "Nie dotyczy" +#: inc/fields/payment-markup.php:247 #: inc/payments/admin/admin-handler.php:975 #: inc/payments/payment-history-shortcode.php:306 #: assets/build/blocks.js:172 @@ -12220,21 +12218,21 @@ msgstr "Nieznany" #: inc/payments/admin/admin-handler.php:1468 #: inc/payments/admin/admin-handler.php:1472 #: inc/payments/admin/admin-handler.php:1476 -#: inc/payments/front-end.php:811 -#: inc/payments/front-end.php:1209 +#: inc/payments/front-end.php:854 +#: inc/payments/front-end.php:1253 msgid "Guest User" msgstr "Użytkownik gościnny" -#: inc/payments/front-end.php:91 +#: inc/payments/front-end.php:92 msgid "Invalid payment amount." msgstr "Nieprawidłowa kwota płatności." -#: inc/payments/front-end.php:107 +#: inc/payments/front-end.php:109 msgid "Valid customer email is required for payments." msgstr "Ważny adres e-mail klienta jest wymagany do płatności." -#: inc/payments/front-end.php:113 -#: inc/payments/front-end.php:320 +#: inc/payments/front-end.php:115 +#: inc/payments/front-end.php:340 #: inc/payments/stripe/admin-stripe-handler.php:877 #: inc/payments/stripe/payments-settings.php:349 #: inc/payments/stripe/payments-settings.php:474 @@ -12244,137 +12242,137 @@ msgstr "Ważny adres e-mail klienta jest wymagany do płatności." msgid "Stripe is not connected." msgstr "Stripe nie jest połączony." -#: inc/payments/front-end.php:119 -#: inc/payments/front-end.php:326 -#: inc/payments/front-end.php:610 -#: inc/payments/front-end.php:1099 +#: inc/payments/front-end.php:121 +#: inc/payments/front-end.php:346 +#: inc/payments/front-end.php:634 +#: inc/payments/front-end.php:1142 msgid "Stripe secret key not found." msgstr "Nie znaleziono tajnego klucza Stripe." #. translators: %s: formatted payment amount -#: inc/payments/front-end.php:201 +#: inc/payments/front-end.php:203 #, php-format msgid "The payment amount (%s) is below the minimum allowed. Stripe only processes amounts above 50¢." msgstr "Kwota płatności (%s) jest poniżej dozwolonego minimum. Stripe przetwarza tylko kwoty powyżej 50¢." #. translators: %s: Field name -#: inc/payments/front-end.php:268 +#: inc/payments/front-end.php:273 #, php-format msgid "Missing required field: %s" msgstr "Brak wymaganego pola: %s" -#: inc/payments/front-end.php:287 +#: inc/payments/front-end.php:292 msgid "Valid customer email is required for subscriptions." msgstr "Ważny adres e-mail klienta jest wymagany do subskrypcji." -#: inc/payments/front-end.php:292 +#: inc/payments/front-end.php:297 msgid "Customer name is required for subscriptions." msgstr "Nazwa klienta jest wymagana do subskrypcji." -#: inc/payments/front-end.php:308 +#: inc/payments/front-end.php:314 msgid "Amount must be greater than 0" msgstr "Kwota musi być większa niż 0" -#: inc/payments/front-end.php:314 +#: inc/payments/front-end.php:322 msgid "Invalid billing interval" msgstr "Nieprawidłowy interwał rozliczeniowy" -#: inc/payments/front-end.php:337 +#: inc/payments/front-end.php:357 msgid "Failed to create customer for subscription." msgstr "Nie udało się utworzyć klienta dla subskrypcji." -#: inc/payments/front-end.php:370 -#: inc/payments/front-end.php:386 +#: inc/payments/front-end.php:390 +#: inc/payments/front-end.php:406 msgid "Failed to create subscription through middleware." msgstr "Nie udało się utworzyć subskrypcji za pośrednictwem oprogramowania pośredniczącego." -#: inc/payments/front-end.php:391 +#: inc/payments/front-end.php:411 msgid "Empty response from subscription creation." msgstr "Pusta odpowiedź z tworzenia subskrypcji." -#: inc/payments/front-end.php:396 +#: inc/payments/front-end.php:416 msgid "Invalid JSON response from subscription creation." msgstr "Nieprawidłowa odpowiedź JSON z tworzenia subskrypcji." -#: inc/payments/front-end.php:400 -#: inc/payments/front-end.php:404 +#: inc/payments/front-end.php:420 +#: inc/payments/front-end.php:424 msgid "Invalid subscription data." msgstr "Nieprawidłowe dane subskrypcji." -#: inc/payments/front-end.php:411 +#: inc/payments/front-end.php:431 msgid "Failed to create subscription." msgstr "Nie udało się utworzyć subskrypcji." #. translators: %s: Error message -#: inc/payments/front-end.php:441 +#: inc/payments/front-end.php:464 #, php-format msgid "Unexpected error: %s" msgstr "Nieoczekiwany błąd: %s" -#: inc/payments/front-end.php:581 +#: inc/payments/front-end.php:604 #: inc/payments/stripe/admin-stripe-handler.php:103 #: inc/payments/stripe/admin-stripe-handler.php:184 #: inc/payments/stripe/admin-stripe-handler.php:489 msgid "Subscription ID not found." msgstr "Nie znaleziono identyfikatora subskrypcji." -#: inc/payments/front-end.php:599 +#: inc/payments/front-end.php:623 msgid "Customer ID not found for the payment." msgstr "Nie znaleziono identyfikatora klienta dla płatności." -#: inc/payments/front-end.php:627 +#: inc/payments/front-end.php:651 msgid "Failed to retrieve setup intent." msgstr "Nie udało się pobrać intencji konfiguracji." -#: inc/payments/front-end.php:656 +#: inc/payments/front-end.php:699 msgid "Failed to update subscription." msgstr "Nie udało się zaktualizować subskrypcji." -#: inc/payments/front-end.php:664 +#: inc/payments/front-end.php:707 msgid "Latest invoice not found on subscription." msgstr "Nie znaleziono najnowszej faktury w subskrypcji." -#: inc/payments/front-end.php:677 +#: inc/payments/front-end.php:720 msgid "Failed to retrieve invoice." msgstr "Nie udało się pobrać faktury." -#: inc/payments/front-end.php:699 +#: inc/payments/front-end.php:742 msgid "Payment intent not found on invoice." msgstr "Nie znaleziono zamiaru płatności na fakturze." -#: inc/payments/front-end.php:714 +#: inc/payments/front-end.php:757 msgid "Failed to confirm payment." msgstr "Nie udało się potwierdzić płatności." -#: inc/payments/front-end.php:730 +#: inc/payments/front-end.php:773 msgid "Failed to retrieve subscription." msgstr "Nie udało się pobrać subskrypcji." -#: inc/payments/front-end.php:745 +#: inc/payments/front-end.php:788 msgid "Subscription not found for the payment." msgstr "Nie znaleziono subskrypcji dla płatności." #. translators: %d: User ID -#: inc/payments/front-end.php:809 -#: inc/payments/front-end.php:1209 +#: inc/payments/front-end.php:852 +#: inc/payments/front-end.php:1253 #, php-format msgid "User ID: %d" msgstr "ID użytkownika: %d" #. translators: %s: Invoice status -#: inc/payments/front-end.php:817 +#: inc/payments/front-end.php:860 #, php-format msgid "Invoice Status: %s" msgstr "Status faktury: %s" #. translators: Title for subscription verification log -#: inc/payments/front-end.php:824 +#: inc/payments/front-end.php:867 msgid "Subscription Verification" msgstr "Weryfikacja subskrypcji" #. translators: %s: Subscription ID #. translators: %s: Stripe subscription ID -#: inc/payments/front-end.php:828 +#: inc/payments/front-end.php:871 #: inc/payments/stripe/admin-stripe-handler.php:119 #: inc/payments/stripe/admin-stripe-handler.php:204 #: inc/payments/stripe/admin-stripe-handler.php:505 @@ -12390,8 +12388,8 @@ msgstr "Identyfikator subskrypcji: %s" #. 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:830 -#: inc/payments/front-end.php:1220 +#: inc/payments/front-end.php:873 +#: inc/payments/front-end.php:1264 #: inc/payments/stripe/admin-stripe-handler.php:124 #: inc/payments/stripe/admin-stripe-handler.php:209 #: inc/payments/stripe/admin-stripe-handler.php:510 @@ -12406,13 +12404,13 @@ msgid "Payment Gateway: %s" msgstr "Bramka płatnicza: %s" #. translators: %s: Payment Intent ID -#: inc/payments/front-end.php:832 +#: inc/payments/front-end.php:875 #, php-format msgid "Payment Intent ID: %s" msgstr "Identyfikator intencji płatności: %s" #. translators: %s: Charge ID -#: inc/payments/front-end.php:834 +#: inc/payments/front-end.php:877 #: inc/payments/stripe/stripe-webhook.php:1048 #, php-format msgid "Charge ID: %s" @@ -12420,7 +12418,7 @@ msgstr "Identyfikator opłaty: %s" #. translators: %s: Subscription Status #. translators: %s: subscription status -#: inc/payments/front-end.php:836 +#: inc/payments/front-end.php:879 #: inc/payments/stripe/admin-stripe-handler.php:129 #: inc/payments/stripe/admin-stripe-handler.php:214 #: inc/payments/stripe/admin-stripe-handler.php:515 @@ -12429,7 +12427,7 @@ msgid "Subscription Status: %s" msgstr "Status subskrypcji: %s" #. translators: %s: Customer ID -#: inc/payments/front-end.php:838 +#: inc/payments/front-end.php:881 #: inc/payments/stripe/stripe-webhook.php:1122 #, php-format msgid "Customer ID: %s" @@ -12437,8 +12435,8 @@ msgstr "ID klienta: %s" #. translators: 1: Amount, 2: Currency #. translators: %1$s: amount, %2$s: currency. -#: inc/payments/front-end.php:840 -#: inc/payments/front-end.php:1222 +#: inc/payments/front-end.php:883 +#: inc/payments/front-end.php:1266 #: inc/payments/stripe/stripe-webhook.php:1053 #: inc/payments/stripe/stripe-webhook.php:1114 #, php-format @@ -12447,34 +12445,34 @@ msgstr "Kwota: %1$s %2$s" #. translators: %s: Payment mode (e.g. Live or Test) #. translators: %s: payment mode -#: inc/payments/front-end.php:843 -#: inc/payments/front-end.php:1227 +#: inc/payments/front-end.php:886 +#: inc/payments/front-end.php:1271 #, php-format msgid "Mode: %s" msgstr "Tryb: %s" -#: inc/payments/front-end.php:877 +#: inc/payments/front-end.php:920 msgid "Failed to verify subscription." msgstr "Nie udało się zweryfikować subskrypcji." -#: inc/payments/front-end.php:1131 -#: inc/payments/front-end.php:1149 -#: inc/payments/front-end.php:1157 -#: inc/payments/front-end.php:1164 +#: inc/payments/front-end.php:1175 +#: inc/payments/front-end.php:1193 +#: inc/payments/front-end.php:1201 +#: inc/payments/front-end.php:1208 msgid "Failed to retrieve payment intent." msgstr "Nie udało się pobrać intencji płatności." -#: inc/payments/front-end.php:1172 +#: inc/payments/front-end.php:1216 msgid "Payment was not confirmed successfully." msgstr "Płatność nie została pomyślnie potwierdzona." -#: inc/payments/front-end.php:1214 +#: inc/payments/front-end.php:1258 msgid "Payment Verification" msgstr "Weryfikacja płatności" #. translators: %s: Stripe transaction ID #. translators: %s: Charge ID -#: inc/payments/front-end.php:1218 +#: inc/payments/front-end.php:1262 #: inc/payments/stripe/stripe-webhook.php:1110 #, php-format msgid "Transaction ID: %s" @@ -12482,18 +12480,18 @@ msgstr "ID transakcji: %s" #. translators: %s: payment status #. translators: %s: Status -#: inc/payments/front-end.php:1224 +#: inc/payments/front-end.php:1268 #: inc/payments/stripe/stripe-webhook.php:576 #: inc/payments/stripe/stripe-webhook.php:1116 #, php-format msgid "Status: %s" msgstr "Status: %s" -#: inc/payments/front-end.php:1330 +#: inc/payments/front-end.php:1374 msgid "Failed to create Stripe customer." msgstr "Nie udało się utworzyć klienta Stripe." -#: inc/payments/front-end.php:1394 +#: inc/payments/front-end.php:1438 msgid "Failed to create Stripe guest customer." msgstr "Nie udało się utworzyć gościa klienta Stripe." @@ -12856,6 +12854,7 @@ msgstr "Nieznany błąd" msgid "Missing payment ID." msgstr "Brakuje identyfikatora płatności." +#: inc/admin/editor-nudge.php:209 #: inc/payments/stripe/admin-stripe-handler.php:84 #: inc/payments/stripe/admin-stripe-handler.php:470 msgid "You are not allowed to perform this action." @@ -13535,10 +13534,6 @@ msgstr "Wybierz pole kwoty" msgid "Select a field…" msgstr "Wybierz pole…" -#: assets/build/blocks.js:172 -msgid "Pick a field from your form like a number, dropdown, or multichoice whose value should decide the payment amount." -msgstr "Wybierz pole z formularza, takie jak liczba, lista rozwijana lub wielokrotny wybór, którego wartość powinna decydować o kwocie płatności." - #: assets/build/blocks.js:172 msgid "Minimum Amount" msgstr "Minimalna kwota" @@ -14118,6 +14113,7 @@ msgstr "Użyj AI, aby natychmiast generować formularze z prostego polecenia." msgid "Build engaging conversational, calculation, and multi-step forms." msgstr "Twórz angażujące formularze konwersacyjne, obliczeniowe i wieloetapowe." +#: inc/admin/editor-nudge.php:192 #: assets/build/forms.js:172 msgid "Create Form" msgstr "Utwórz formularz" @@ -14976,76 +14972,78 @@ msgstr "Określony post nie jest formularzem SureForms." msgid "Failed to create duplicate form." msgstr "Nie udało się utworzyć duplikatu formularza." -#: inc/payments/front-end.php:97 -#: inc/payments/front-end.php:298 -#: inc/payments/payment-helper.php:594 +#: inc/payments/front-end.php:98 +#: inc/payments/front-end.php:303 +#: inc/payments/payment-helper.php:595 msgid "Invalid form configuration." msgstr "Nieprawidłowa konfiguracja formularza." -#: inc/payments/payment-helper.php:602 +#: inc/payments/payment-helper.php:603 msgid "Payment configuration not found for this form." msgstr "Nie znaleziono konfiguracji płatności dla tego formularza." #. translators: 1: expected currency, 2: received currency -#: inc/payments/payment-helper.php:613 +#: inc/payments/payment-helper.php:614 #, php-format msgid "Currency mismatch: expected %1$s, received %2$s." msgstr "Niezgodność waluty: oczekiwano %1$s, otrzymano %2$s." #. translators: 1: expected amount with currency -#: inc/payments/payment-helper.php:630 +#: inc/payments/payment-helper.php:649 #, php-format msgid "Payment amount must be exactly %1$s." msgstr "Kwota płatności musi wynosić dokładnie %1$s." #. translators: 1: minimum amount with currency -#: inc/payments/payment-helper.php:641 +#: inc/payments/payment-helper.php:660 #, php-format msgid "Payment amount must be at least %1$s." msgstr "Kwota płatności musi wynosić co najmniej %1$s." -#: inc/payments/payment-helper.php:717 +#: inc/payments/payment-helper.php:737 msgid "Invalid payment verification parameters." msgstr "Nieprawidłowe parametry weryfikacji płatności." -#: inc/payments/payment-helper.php:728 +#: inc/payments/payment-helper.php:748 msgid "Payment verification failed. Invalid payment intent." msgstr "Weryfikacja płatności nie powiodła się. Nieprawidłowy zamiar płatności." -#: inc/payments/payment-helper.php:814 -#: inc/payments/payment-helper.php:952 +#: inc/payments/payment-helper.php:903 +#: inc/payments/payment-helper.php:1043 msgid "Variable amount field configuration not found." msgstr "Nie znaleziono konfiguracji pola zmiennej kwoty." -#: inc/payments/payment-helper.php:835 +#: inc/payments/payment-helper.php:924 msgid "No payment options are configured for this field." msgstr "Nie skonfigurowano opcji płatności dla tego pola." #. translators: %s: currency code -#: inc/payments/payment-helper.php:861 +#: inc/payments/payment-helper.php:950 msgid "Invalid payment amount. Please select a valid amount from the available options." msgstr "Nieprawidłowa kwota płatności. Proszę wybrać prawidłową kwotę z dostępnych opcji." #. translators: %1$s: expected amount, %2$s: payment amount -#: inc/payments/payment-helper.php:896 +#: inc/payments/payment-helper.php:986 msgid "Payment configuration not found." msgstr "Nie znaleziono konfiguracji płatności." #. translators: %1$s: expected amount, %2$s: payment amount -#: inc/payments/payment-helper.php:912 -#: inc/payments/payment-helper.php:964 -#: inc/payments/payment-helper.php:1000 +#: inc/payments/payment-helper.php:1003 +#: inc/payments/payment-helper.php:1055 +#: inc/payments/payment-helper.php:1091 +#: inc/payments/payment-helper.php:1111 #, php-format msgid "Payment amount mismatch. Expected %1$s, received %2$s." msgstr "Kwota płatności niezgodna. Oczekiwano %1$s, otrzymano %2$s." -#: inc/payments/payment-helper.php:941 -#: inc/payments/payment-helper.php:991 +#: 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." msgstr "Wartość pola zmiennej kwoty jest wymagana." #. translators: %1$s: minimum amount, %2$s: payment amount -#: inc/payments/payment-helper.php:1012 +#: inc/payments/payment-helper.php:1125 #, php-format msgid "Payment amount below minimum. Minimum: %1$s, received %2$s." msgstr "Kwota płatności poniżej minimum. Minimum: %1$s, otrzymano %2$s." @@ -15107,7 +15105,7 @@ msgstr "Wystąpił błąd podczas duplikowania formularza." msgid "This will create a copy of \"%s\" with all its settings." msgstr "To utworzy kopię „%s” ze wszystkimi jego ustawieniami." -#: inc/fields/payment-markup.php:413 +#: inc/fields/payment-markup.php:514 msgid "Pay with credit or debit card" msgstr "Zapłać kartą kredytową lub debetową" @@ -15115,8 +15113,8 @@ msgstr "Zapłać kartą kredytową lub debetową" msgid "This form is not yet available. Please check back after the scheduled start time." msgstr "Ten formularz nie jest jeszcze dostępny. Proszę sprawdzić ponownie po zaplanowanym czasie rozpoczęcia." -#: inc/form-restriction.php:165 -#: inc/form-restriction.php:166 +#: inc/form-restriction.php:187 +#: inc/form-restriction.php:188 #: assets/build/formEditor.js:172 msgid "This form is no longer accepting submissions. The submission period has ended." msgstr "Formularz ten nie przyjmuje już zgłoszeń. Okres składania zgłoszeń dobiegł końca." @@ -15131,7 +15129,7 @@ msgstr "Bramka płatności nie została znaleziona." msgid "Refund processing is not supported for %s gateway." msgstr "Przetwarzanie zwrotów nie jest obsługiwane dla bramki %s." -#: inc/payments/payment-helper.php:974 +#: inc/payments/payment-helper.php:1065 msgid "Number field configuration not found." msgstr "Nie znaleziono konfiguracji pola liczbowego." @@ -15508,11 +15506,11 @@ msgstr "Tytuł formularza jest wymagany." msgid "At least one form field is required." msgstr "Wymagane jest co najmniej jedno pole formularza." -#: inc/abilities/forms/create-form.php:322 +#: inc/abilities/forms/create-form.php:326 msgid "Failed to generate form fields from the provided data." msgstr "Nie udało się wygenerować pól formularza z dostarczonych danych." -#: inc/abilities/forms/create-form.php:372 +#: inc/abilities/forms/create-form.php:376 msgid "Failed to create the form." msgstr "Nie udało się utworzyć formularza." @@ -15688,23 +15686,23 @@ msgstr "Sesja uwierzytelniania wygasła. Proszę spróbować ponownie." msgid "Invalid access key format." msgstr "Nieprawidłowy format klucza dostępu." -#: inc/ai-form-builder/ai-helper.php:182 +#: inc/ai-form-builder/ai-helper.php:175 msgid "Unable to connect to SureForms API. Please check your connection." msgstr "Nie można połączyć się z API SureForms. Proszę sprawdzić swoje połączenie." -#: inc/ai-form-builder/ai-helper.php:186 +#: inc/ai-form-builder/ai-helper.php:179 msgid "Unable to verify license. Please check your license key." msgstr "Nie można zweryfikować licencji. Proszę sprawdzić swój klucz licencyjny." -#: inc/ai-form-builder/ai-helper.php:190 +#: inc/ai-form-builder/ai-helper.php:183 msgid "An error occurred while trying to verify your email. Please check your email you have used to log in or sign up on billing.sureforms.com." msgstr "Wystąpił błąd podczas próby weryfikacji Twojego adresu e-mail. Sprawdź adres e-mail, którego użyłeś do logowania lub rejestracji na billing.sureforms.com." -#: inc/ai-form-builder/ai-helper.php:194 +#: inc/ai-form-builder/ai-helper.php:187 msgid "Unable to verify referer. Please check your referer." msgstr "Nie można zweryfikować referera. Proszę sprawdzić swojego referera." -#: inc/ai-form-builder/ai-helper.php:202 +#: inc/ai-form-builder/ai-helper.php:195 msgid "Domain Verification Failed on current site. Please try again on another website." msgstr "Weryfikacja domeny nie powiodła się na bieżącej stronie. Proszę spróbować ponownie na innej stronie internetowej." @@ -15730,8 +15728,8 @@ msgstr "Wyrażam zgodę na przechowywanie moich informacji przez tę stronę int msgid "Text field" msgstr "Pole tekstowe" -#: inc/form-restriction.php:160 -#: inc/form-restriction.php:161 +#: inc/form-restriction.php:182 +#: inc/form-restriction.php:183 #: inc/post-types.php:1203 #: inc/post-types.php:1243 msgid "This form is not yet available. Check back after the scheduled start time." @@ -15741,8 +15739,8 @@ msgstr "Ten formularz nie jest jeszcze dostępny. Sprawdź ponownie po zaplanowa #: inc/form-submit.php:400 #: inc/form-submit.php:445 #: inc/form-submit.php:968 -#: inc/payments/front-end.php:77 -#: inc/payments/front-end.php:258 +#: 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 @@ -16097,32 +16095,32 @@ msgid "Enter a valid email address." msgstr "Wprowadź prawidłowy adres e-mail." #. translators: %s represents the minimum acceptable value -#: inc/translatable.php:94 +#: inc/translatable.php:97 #, php-format msgid "Minimum value is %s." msgstr "Minimalna wartość to %s." #. translators: %s represents the maximum acceptable value -#: inc/translatable.php:97 +#: inc/translatable.php:100 #, php-format msgid "Maximum value is %s." msgstr "Maksymalna wartość to %s." #. translators: %s represents the minimum number of options to select -#: inc/translatable.php:100 -#: inc/translatable.php:106 +#: inc/translatable.php:103 +#: inc/translatable.php:109 #, php-format msgid "Select at least %s options." msgstr "Wybierz co najmniej %s opcje." #. translators: %s represents the maximum number of options that can be selected -#: inc/translatable.php:103 -#: inc/translatable.php:109 +#: inc/translatable.php:106 +#: inc/translatable.php:112 #, php-format msgid "You can select up to %s options." msgstr "Możesz wybrać maksymalnie %s opcji." -#: inc/translatable.php:120 +#: inc/translatable.php:123 msgid "This form is now closed as we have reached the maximum number of entries." msgstr "Formularz został zamknięty, ponieważ osiągnęliśmy maksymalną liczbę zgłoszeń." @@ -16649,35 +16647,35 @@ msgstr "Pobierz globalne ustawienia SureForms. Opcjonalnie filtruj według kateg msgid "Setting categories to retrieve. Omit for all categories." msgstr "Ustawianie kategorii do pobrania. Pomiń, aby pobrać wszystkie kategorie." -#: inc/abilities/settings/update-global-settings.php:105 +#: inc/abilities/settings/update-global-settings.php:106 msgid "Update Global Settings" msgstr "Zaktualizuj ustawienia globalne" -#: inc/abilities/settings/update-global-settings.php:106 +#: inc/abilities/settings/update-global-settings.php:107 msgid "Update SureForms global settings for a specific category: general, validation-messages, email-summary, or security." msgstr "Zaktualizuj globalne ustawienia SureForms dla określonej kategorii: ogólne, komunikaty walidacyjne, podsumowanie e-mail lub bezpieczeństwo." -#: inc/abilities/settings/update-global-settings.php:139 +#: inc/abilities/settings/update-global-settings.php:140 msgid "The settings category to update." msgstr "Kategoria ustawień do zaktualizowania." -#: inc/abilities/settings/update-global-settings.php:144 +#: inc/abilities/settings/update-global-settings.php:145 msgid "Key-value pairs of settings to update." msgstr "Pary klucz-wartość ustawień do zaktualizowania." -#: inc/abilities/settings/update-global-settings.php:180 +#: inc/abilities/settings/update-global-settings.php:181 msgid "Settings category is required." msgstr "Kategoria ustawień jest wymagana." -#: inc/abilities/settings/update-global-settings.php:188 +#: inc/abilities/settings/update-global-settings.php:189 msgid "Settings data is required." msgstr "Wymagane są dane ustawień." -#: inc/abilities/settings/update-global-settings.php:199 +#: inc/abilities/settings/update-global-settings.php:200 msgid "No valid settings keys provided for this category." msgstr "Nie podano prawidłowych kluczy ustawień dla tej kategorii." -#: inc/abilities/settings/update-global-settings.php:225 +#: inc/abilities/settings/update-global-settings.php:226 msgid "Invalid settings category." msgstr "Nieprawidłowa kategoria ustawień." @@ -17578,6 +17576,212 @@ msgstr "Polski Złoty" msgid "Dynamic Default Value" msgstr "Dynamiczna wartość domyślna" +#: inc/admin/editor-nudge.php:191 +msgid "Hey! It looks like you're creating a form. Build a ready-to-use form in under 30 seconds with SureForms AI, with no extra setup required." +msgstr "Hej! Wygląda na to, że tworzysz formularz. Zbuduj gotowy do użycia formularz w mniej niż 30 sekund z SureForms AI, bez dodatkowej konfiguracji." + +#: inc/admin/editor-nudge.php:228 +#: inc/admin/editor-nudge.php:237 +msgid "Invalid post." +msgstr "Nieprawidłowy post." + +#: inc/admin/editor-nudge.php:246 +msgid "You cannot edit this post." +msgstr "Nie możesz edytować tego posta." + +#: inc/ai-form-builder/ai-form-builder.php:96 +msgid "The AI did not return a form. Please refine your prompt and try again." +msgstr "Sztuczna inteligencja nie zwróciła formularza. Proszę dopracować swój prompt i spróbować ponownie." + +#: inc/ai-form-builder/ai-form-builder.php:104 +msgid "The AI response is missing a form title. Please try again." +msgstr "Odpowiedź AI nie zawiera tytułu formularza. Proszę spróbować ponownie." + +#: inc/ai-form-builder/ai-form-builder.php:115 +#: inc/ai-form-builder/field-mapping.php:69 +msgid "The AI was unable to generate form fields. Please try again." +msgstr "Sztuczna inteligencja nie była w stanie wygenerować pól formularza. Proszę spróbować ponownie." + +#: inc/ai-form-builder/field-mapping.php:41 +msgid "The AI form data is missing. Please try again." +msgstr "Dane formularza AI są brakujące. Proszę spróbować ponownie." + +#: inc/ai-form-builder/field-mapping.php:51 +msgid "The AI form data is not in the expected format." +msgstr "Dane formularza AI nie są w oczekiwanym formacie." + +#: inc/ai-form-builder/field-mapping.php:60 +msgid "The AI response did not include a form. Please try again." +msgstr "Odpowiedź AI nie zawierała formularza. Proszę spróbować ponownie." + +#: inc/ai-form-builder/field-mapping.php:90 +msgid "The AI returned a malformed form field. Please try again." +msgstr "Sztuczna inteligencja zwróciła nieprawidłowe pole formularza. Proszę spróbować ponownie." + +#: inc/create-new-form.php:160 +#: inc/create-new-form.php:173 +msgid "Error creating SureForms Form." +msgstr "Błąd podczas tworzenia formularza SureForms." + +#. translators: %s represents the minimum number of characters required +#: inc/field-validation.php:289 +#: inc/translatable.php:94 +#, php-format +msgid "Please enter at least %s characters." +msgstr "Proszę wprowadzić co najmniej %s znaków." + +#: inc/fields/payment-markup.php:246 +msgid "One-Time Payment" +msgstr "Płatność jednorazowa" + +#: inc/fields/payment-markup.php:562 +msgid "Choose payment type" +msgstr "Wybierz rodzaj płatności" + +#: inc/payments/front-end.php:333 +msgid "Billing interval does not match the form configuration." +msgstr "Okres rozliczeniowy nie pasuje do konfiguracji formularza." + +#: inc/payments/payment-helper.php:627 +msgid "Payment type does not match the form configuration." +msgstr "Typ płatności nie pasuje do konfiguracji formularza." + +#: inc/payments/payment-helper.php:760 +msgid "Payment verification failed. Payment type mismatch." +msgstr "Weryfikacja płatności nie powiodła się. Nieprawidłowy typ płatności." + +#: assets/build/blocks.js:172 +msgid "Minimum Characters" +msgstr "Minimalna liczba znaków" + +#: assets/build/blocks.js:172 +msgid "Minimum characters cannot exceed Maximum characters." +msgstr "Minimalna liczba znaków nie może przekraczać maksymalnej liczby znaków." + +#: assets/build/blocks.js:172 +msgid "Both" +msgstr "Oba" + +#: assets/build/blocks.js:172 +msgid "One-Time Label" +msgstr "Etykieta jednorazowa" + +#: assets/build/blocks.js:172 +msgid "Label shown to users for the one-time payment option." +msgstr "Etykieta pokazywana użytkownikom dla opcji jednorazowej płatności." + +#: assets/build/blocks.js:172 +msgid "Subscription Label" +msgstr "Etykieta subskrypcji" + +#: assets/build/blocks.js:172 +msgid "Label shown to users for the subscription option." +msgstr "Etykieta pokazywana użytkownikom dla opcji subskrypcji." + +#: assets/build/blocks.js:172 +msgid "Default Selection" +msgstr "Domyślny wybór" + +#: assets/build/blocks.js:172 +msgid "Which option is pre-selected when the form loads." +msgstr "Która opcja jest wstępnie wybrana po załadowaniu formularza." + +#: assets/build/blocks.js:172 +msgid "One-Time Amount Type" +msgstr "Rodzaj kwoty jednorazowej" + +#: assets/build/blocks.js:172 +msgid "Set how the one-time payment amount is determined." +msgstr "Ustaw, jak jest określana kwota jednorazowej płatności." + +#: assets/build/blocks.js:172 +msgid "One-Time Fixed Amount" +msgstr "Jednorazowa stała kwota" + +#: assets/build/blocks.js:172 +msgid "Amount charged for a one-time payment." +msgstr "Kwota pobrana za jednorazową płatność." + +#: assets/build/blocks.js:172 +msgid "One-Time Amount Field" +msgstr "Pole kwoty jednorazowej" + +#: assets/build/blocks.js:172 +msgid "Pick a form field whose value determines the one-time payment amount." +msgstr "Wybierz pole formularza, którego wartość określa kwotę jednorazowej płatności." + +#: assets/build/blocks.js:172 +msgid "One-Time Minimum Amount" +msgstr "Jednorazowa minimalna kwota" + +#: assets/build/blocks.js:172 +msgid "Minimum amount users can enter for one-time payment (0 for no minimum)." +msgstr "Minimalna kwota, jaką użytkownicy mogą wprowadzić dla jednorazowej płatności (0, jeśli brak minimum)." + +#: assets/build/blocks.js:172 +msgid "Subscription Amount Type" +msgstr "Typ kwoty subskrypcji" + +#: assets/build/blocks.js:172 +msgid "Set how the subscription amount is determined." +msgstr "Ustaw, jak jest określana kwota subskrypcji." + +#: assets/build/blocks.js:172 +msgid "Subscription Fixed Amount" +msgstr "Stała kwota subskrypcji" + +#: assets/build/blocks.js:172 +msgid "Recurring amount charged per billing interval." +msgstr "Powtarzająca się kwota pobierana za każdy okres rozliczeniowy." + +#: assets/build/blocks.js:172 +msgid "Subscription Amount Field" +msgstr "Pole kwoty subskrypcji" + +#: assets/build/blocks.js:172 +msgid "Pick a form field whose value determines the subscription amount." +msgstr "Wybierz pole formularza, którego wartość określa kwotę subskrypcji." + +#: assets/build/blocks.js:172 +msgid "Subscription Minimum Amount" +msgstr "Minimalna kwota subskrypcji" + +#: assets/build/blocks.js:172 +msgid "Minimum amount users can enter for subscription (0 for no minimum)." +msgstr "Minimalna kwota, jaką użytkownicy mogą wpisać na subskrypcję (0 oznacza brak minimum)." + +#: 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 "Wybierz pole z formularza, takie jak liczba, lista rozwijana, wielokrotny wybór lub ukryte, którego wartość powinna decydować o kwocie płatności." + +#: assets/build/templatePicker.js:172 +msgid "You do not have permission to create forms." +msgstr "Nie masz uprawnień do tworzenia formularzy." + +#: assets/build/templatePicker.js:172 +msgid "The form could not be saved. Please try again." +msgstr "Nie można było zapisać formularza. Proszę spróbować ponownie." + +#: assets/build/templatePicker.js:172 +msgid "Unable to reach the SureForms AI service. Please check your connection and try again." +msgstr "Nie można połączyć się z usługą SureForms AI. Proszę sprawdzić połączenie i spróbować ponownie." + +#: assets/build/templatePicker.js:172 +msgid "The AI service did not return a response. Please try again." +msgstr "Usługa AI nie zwróciła odpowiedzi. Proszę spróbować ponownie." + +#: assets/build/templatePicker.js:172 +msgid "Form generation failed. Please try again." +msgstr "Generowanie formularza nie powiodło się. Proszę spróbować ponownie." + +#: assets/build/templatePicker.js:172 +msgid "The AI response was empty. Please refine your prompt and try again." +msgstr "Odpowiedź AI była pusta. Proszę dopracować swój prompt i spróbować ponownie." + +#: assets/build/templatePicker.js:172 +msgid "Unable to build form fields from the AI response." +msgstr "Nie można utworzyć pól formularza z odpowiedzi AI." + #: inc/post-types.php:205 msgctxt "post type general name" msgid "Forms" diff --git a/languages/sureforms-pt_PT-120a6dad015d3891c70f578c2251576b.json b/languages/sureforms-pt_PT-120a6dad015d3891c70f578c2251576b.json index fde77080d..2a9823cc8 100644 --- a/languages/sureforms-pt_PT-120a6dad015d3891c70f578c2251576b.json +++ b/languages/sureforms-pt_PT-120a6dad015d3891c70f578c2251576b.json @@ -1 +1 @@ -{"translation-revision-date":"2025-01-02T08:44:42+00:00","generator":"WP-CLI\/2.12.0","source":"assets\/build\/templatePicker.js","domain":"messages","locale_data":{"messages":{"":{"domain":"messages","lang":"en","plural-forms":"nplurals=2; plural=(n != 1);"},"Dashboard":["Painel de Controle"],"Connect Now":["Conectar agora"],"Authentication Failed":["Falha na autentica\u00e7\u00e3o"],"Contact Support":["Contactar Suporte"],"Click Here to Retry":["Clique aqui para tentar novamente"],"Exit to Dashboard":["Sair para o Painel de Controle"],"AI Form Builder":["Construtor de Formul\u00e1rios de IA"],"Speech recognition is not supported in your current browser. Please use Google Chrome \/ Safari.":["O reconhecimento de fala n\u00e3o \u00e9 suportado no seu navegador atual. Por favor, use o Google Chrome \/ Safari."],"Please allow microphone access to use voice input.":["Por favor, permita o acesso ao microfone para usar a entrada de voz."],"Voice Input":["Entrada de voz"],"Try Again":["Tente novamente"],"Please try again after %s.":["Por favor, tente novamente ap\u00f3s %s."],"You have reached the maximum number of form generations in your Free Plan.":["Voc\u00ea atingiu o n\u00famero m\u00e1ximo de gera\u00e7\u00f5es de formul\u00e1rios no seu Plano Gratuito."],"Unlock Conversational Forms":["Desbloquear Formul\u00e1rios Conversacionais"],"Simple":["Simples"],"Upgrade Now":["Atualize agora"],"Generate with AI":["Gerar com IA"],"Please check your username and password for the account, and try to reconnect again. Need help?":["Por favor, verifique seu nome de usu\u00e1rio e senha para a conta e tente reconectar novamente. Precisa de ajuda?"],"Describe the form you want to create":["Descreva o formul\u00e1rio que voc\u00ea deseja criar"],"We are building your form\u2026":["Estamos construindo seu formul\u00e1rio\u2026"],"Payment":["Pagamento"],"and ":["e"],"more\u2026":["mais\u2026"],"Calculations":["C\u00e1lculos"],"Unlock Calculator Forms":["Desbloquear Formul\u00e1rios de Calculadora"],"Build Smart Forms That Calculate Instantly":["Crie Formul\u00e1rios Inteligentes Que Calculam Instantaneamente"],"Empower your forms with advanced calculations. From loan calculators to BMI checkers - create interactive forms that give real-time results.":["Capacite seus formul\u00e1rios com c\u00e1lculos avan\u00e7ados. De calculadoras de empr\u00e9stimo a verificadores de IMC - crie formul\u00e1rios interativos que fornecem resultados em tempo real."],"Add complex formulas with ease":["Adicione f\u00f3rmulas complexas com facilidade"],"Provide instant answers to users":["Forne\u00e7a respostas instant\u00e2neas aos usu\u00e1rios"],"Perfect for finance, health, and pricing forms":["Perfeito para formul\u00e1rios de finan\u00e7as, sa\u00fade e pre\u00e7os"],"Conversational":["Conversacional"],"Turn Simple Forms Into Conversations":["Transforme Formul\u00e1rios Simples em Conversas"],"Transform boring forms into friendly, chat-like experiences. Ask one question at a time, just like a real conversation, and see higher engagement.":["Transforme formul\u00e1rios entediantes em experi\u00eancias amig\u00e1veis, semelhantes a um bate-papo. Fa\u00e7a uma pergunta de cada vez, como em uma conversa real, e veja um maior engajamento."],"One question at a time, in chat flow":["Uma pergunta de cada vez, no fluxo de chat"],"More engaging than traditional forms":["Mais envolvente do que as formas tradicionais"],"Boosts completion rates with a friendly interface":["Aumenta as taxas de conclus\u00e3o com uma interface amig\u00e1vel"],"Select this if you need calculations in your form. For example: Loan interest calculator.":["Selecione isto se precisar de c\u00e1lculos no seu formul\u00e1rio. Por exemplo: Calculadora de juros de empr\u00e9stimo."],"Select this if you want your form to display one question at a time, like a chat.":["Selecione isto se quiser que o seu formul\u00e1rio exiba uma pergunta de cada vez, como um chat."],"Select this if you want to collect payments through your form.":["Selecione isto se voc\u00ea quiser coletar pagamentos atrav\u00e9s do seu formul\u00e1rio."],"%d AI Generations Left. SureForms Premium allows:":["%d Gera\u00e7\u00f5es de IA Restantes. O SureForms Premium permite:"],"%d AI Generations Left, Connect to SureForms AI to Get 10 More":["%d Gera\u00e7\u00f5es de IA Restantes, Conecte-se ao SureForms AI para Obter Mais 10"],"%d AI Generations Left. Upgrade to SureForms Premium":["%d Gera\u00e7\u00f5es de IA Restantes. Fa\u00e7a upgrade para o SureForms Premium"],"Contact form to collect name, email, and message from visitors":["Formul\u00e1rio de contato para coletar nome, email e mensagem dos visitantes"],"Job application form for \"Marketing Manager\" with resume upload":["Formul\u00e1rio de candidatura para \"Gerente de Marketing\" com upload de curr\u00edculo"],"Feedback form to ask customers: \"How would you rate our product and what should we improve?\"":["Formul\u00e1rio de feedback para perguntar aos clientes: \"Como voc\u00ea classificaria nosso produto e o que devemos melhorar?\""],"Event registration form for \"Photography Workshop\" with date and seat selection":["Formul\u00e1rio de inscri\u00e7\u00e3o para o evento \"Workshop de Fotografia\" com sele\u00e7\u00e3o de data e assento"],"Newsletter signup form with name and email to join mailing list":["Formul\u00e1rio de inscri\u00e7\u00e3o para newsletter com nome e email para entrar na lista de correio"],"Order form for \"Custom T-Shirt\" with size, color, and quantity options":["Formul\u00e1rio de pedido para \"Camiseta Personalizada\" com op\u00e7\u00f5es de tamanho, cor e quantidade"],"Survey form: \"How satisfied are you with our service? (1\u20135 stars)\"":["Formul\u00e1rio de pesquisa: \"Qu\u00e3o satisfeito est\u00e1 com o nosso servi\u00e7o? (1\u20135 estrelas)\""],"Appointment booking form for \"Consultation Call\" with preferred time":["Formul\u00e1rio de agendamento para \"Chamada de Consulta\" com hor\u00e1rio preferido"],"Describe the form that you want":["Descreva o formul\u00e1rio que voc\u00ea deseja"],"Generate":["Gerar"],"Create Unlimited Forms with AI":["Crie Formul\u00e1rios Ilimitados com IA"],"Add Advanced Field Types":["Adicionar Tipos de Campos Avan\u00e7ados"],"Create Calculators, Surveys, etc.":["Criar Calculadoras, Pesquisas, etc."],"Form Generation Limit Reached":["Limite de Gera\u00e7\u00e3o de Formul\u00e1rio Atingido"],"You have reached the maximum number of form generations in your Free Plan. SureForms Premium allows:":["Voc\u00ea atingiu o n\u00famero m\u00e1ximo de gera\u00e7\u00f5es de formul\u00e1rios no seu Plano Gratuito. O SureForms Premium permite:"],"%s AI Generations Left.":["%s Gera\u00e7\u00f5es de IA Restantes."],"Unlock Unlimited Generations":["Desbloqueie Gera\u00e7\u00f5es Ilimitadas"],"Connect to SureForms AI":["Conectar ao SureForms AI"],"You Have Hit Your Free Limit.":["Voc\u00ea atingiu o seu limite gratuito."],"Connect to SureForms AI to Get 10 More.":["Conecte-se ao SureForms AI para obter mais 10."],"Or create it yourself":["Ou crie voc\u00ea mesmo"],"Unable to create form":["N\u00e3o foi poss\u00edvel criar o formul\u00e1rio"],"Something went wrong. Please try again.":["Algo deu errado. Por favor, tente novamente."],"Describe what kind of form you want":["Descreva que tipo de formul\u00e1rio voc\u00ea deseja"],"Click to generate the form":["Clique para gerar o formul\u00e1rio"],"Connecting to AI service":["Conectando ao servi\u00e7o de IA"],"Generating fields":["Gerando campos"],"Finalizing your form":["Finalizando seu formul\u00e1rio"],"Opening form editor":["Abrindo o editor de formul\u00e1rios"],"Design Multistep Forms":["Projetar Formul\u00e1rios Multietapas"],"Send Form Entries to Your CRM or Any App":["Envie entradas de formul\u00e1rio para o seu CRM ou qualquer aplicativo"],"You've reached your daily generation limit.":["Voc\u00ea atingiu o seu limite di\u00e1rio de gera\u00e7\u00e3o."],"You've reached your daily limit for AI form generations.":["Voc\u00ea atingiu seu limite di\u00e1rio para gera\u00e7\u00f5es de formul\u00e1rios de IA."],"Quiz":["Question\u00e1rio"],"Unlock Quiz Forms":["Desbloquear Formul\u00e1rios de Question\u00e1rio"],"Create Engaging Quizzes That Score Automatically":["Crie question\u00e1rios envolventes que pontuam automaticamente"],"Build interactive quizzes with scored questions and graded results. Perfect for assessments, trivia, and educational content.":["Crie question\u00e1rios interativos com perguntas pontuadas e resultados avaliados. Perfeito para avalia\u00e7\u00f5es, curiosidades e conte\u00fado educacional."],"Auto-score responses instantly":["Avaliar respostas instantaneamente"],"Display graded results to users":["Exibir resultados avaliados para os usu\u00e1rios"],"Perfect for education, training, and fun trivia":["Perfeito para educa\u00e7\u00e3o, treinamento e curiosidades divertidas"],"Select this to create a quiz with scored questions and graded results.":["Selecione isto para criar um question\u00e1rio com perguntas pontuadas e resultados avaliados."],"Select this to create a survey to collect responses and opinions.":["Selecione isto para criar uma pesquisa para coletar respostas e opini\u00f5es."],"Survey":["Pesquisa"],"Unlock Survey Forms":["Desbloquear Formul\u00e1rios de Pesquisa"],"Collect Insights with Powerful Surveys":["Recolha insights com pesquisas poderosas"],"Create surveys to collect responses and opinions. Visualize results with charts and share aggregated insights with your audience.":["Crie pesquisas para coletar respostas e opini\u00f5es. Visualize os resultados com gr\u00e1ficos e compartilhe insights agregados com seu p\u00fablico."],"Aggregate and visualize responses":["Agregue e visualize respostas"],"Show live results to respondents":["Mostrar resultados ao vivo aos respondentes"],"Perfect for feedback, polls, and research":["Perfeito para feedback, pesquisas e sondagens"]}}} \ No newline at end of file +{"translation-revision-date":"2025-01-02T08:44:42+00:00","generator":"WP-CLI\/2.12.0","source":"assets\/build\/templatePicker.js","domain":"messages","locale_data":{"messages":{"":{"domain":"messages","lang":"en","plural-forms":"nplurals=2; plural=(n != 1);"},"Dashboard":["Painel de Controle"],"Connect Now":["Conectar agora"],"Authentication Failed":["Falha na autentica\u00e7\u00e3o"],"Contact Support":["Contactar Suporte"],"Click Here to Retry":["Clique aqui para tentar novamente"],"Exit to Dashboard":["Sair para o Painel de Controle"],"AI Form Builder":["Construtor de Formul\u00e1rios de IA"],"Speech recognition is not supported in your current browser. Please use Google Chrome \/ Safari.":["O reconhecimento de fala n\u00e3o \u00e9 suportado no seu navegador atual. Por favor, use o Google Chrome \/ Safari."],"Please allow microphone access to use voice input.":["Por favor, permita o acesso ao microfone para usar a entrada de voz."],"Voice Input":["Entrada de voz"],"Try Again":["Tente novamente"],"Please try again after %s.":["Por favor, tente novamente ap\u00f3s %s."],"You have reached the maximum number of form generations in your Free Plan.":["Voc\u00ea atingiu o n\u00famero m\u00e1ximo de gera\u00e7\u00f5es de formul\u00e1rios no seu Plano Gratuito."],"Unlock Conversational Forms":["Desbloquear Formul\u00e1rios Conversacionais"],"Simple":["Simples"],"Upgrade Now":["Atualize agora"],"Generate with AI":["Gerar com IA"],"Please check your username and password for the account, and try to reconnect again. Need help?":["Por favor, verifique seu nome de usu\u00e1rio e senha para a conta e tente reconectar novamente. Precisa de ajuda?"],"Describe the form you want to create":["Descreva o formul\u00e1rio que voc\u00ea deseja criar"],"We are building your form\u2026":["Estamos construindo seu formul\u00e1rio\u2026"],"Payment":["Pagamento"],"and ":["e"],"more\u2026":["mais\u2026"],"Calculations":["C\u00e1lculos"],"Unlock Calculator Forms":["Desbloquear Formul\u00e1rios de Calculadora"],"Build Smart Forms That Calculate Instantly":["Crie Formul\u00e1rios Inteligentes Que Calculam Instantaneamente"],"Empower your forms with advanced calculations. From loan calculators to BMI checkers - create interactive forms that give real-time results.":["Capacite seus formul\u00e1rios com c\u00e1lculos avan\u00e7ados. De calculadoras de empr\u00e9stimo a verificadores de IMC - crie formul\u00e1rios interativos que fornecem resultados em tempo real."],"Add complex formulas with ease":["Adicione f\u00f3rmulas complexas com facilidade"],"Provide instant answers to users":["Forne\u00e7a respostas instant\u00e2neas aos usu\u00e1rios"],"Perfect for finance, health, and pricing forms":["Perfeito para formul\u00e1rios de finan\u00e7as, sa\u00fade e pre\u00e7os"],"Conversational":["Conversacional"],"Turn Simple Forms Into Conversations":["Transforme Formul\u00e1rios Simples em Conversas"],"Transform boring forms into friendly, chat-like experiences. Ask one question at a time, just like a real conversation, and see higher engagement.":["Transforme formul\u00e1rios entediantes em experi\u00eancias amig\u00e1veis, semelhantes a um bate-papo. Fa\u00e7a uma pergunta de cada vez, como em uma conversa real, e veja um maior engajamento."],"One question at a time, in chat flow":["Uma pergunta de cada vez, no fluxo de chat"],"More engaging than traditional forms":["Mais envolvente do que as formas tradicionais"],"Boosts completion rates with a friendly interface":["Aumenta as taxas de conclus\u00e3o com uma interface amig\u00e1vel"],"Select this if you need calculations in your form. For example: Loan interest calculator.":["Selecione isto se precisar de c\u00e1lculos no seu formul\u00e1rio. Por exemplo: Calculadora de juros de empr\u00e9stimo."],"Select this if you want your form to display one question at a time, like a chat.":["Selecione isto se quiser que o seu formul\u00e1rio exiba uma pergunta de cada vez, como um chat."],"Select this if you want to collect payments through your form.":["Selecione isto se voc\u00ea quiser coletar pagamentos atrav\u00e9s do seu formul\u00e1rio."],"%d AI Generations Left. SureForms Premium allows:":["%d Gera\u00e7\u00f5es de IA Restantes. O SureForms Premium permite:"],"%d AI Generations Left, Connect to SureForms AI to Get 10 More":["%d Gera\u00e7\u00f5es de IA Restantes, Conecte-se ao SureForms AI para Obter Mais 10"],"%d AI Generations Left. Upgrade to SureForms Premium":["%d Gera\u00e7\u00f5es de IA Restantes. Fa\u00e7a upgrade para o SureForms Premium"],"Contact form to collect name, email, and message from visitors":["Formul\u00e1rio de contato para coletar nome, email e mensagem dos visitantes"],"Job application form for \"Marketing Manager\" with resume upload":["Formul\u00e1rio de candidatura para \"Gerente de Marketing\" com upload de curr\u00edculo"],"Feedback form to ask customers: \"How would you rate our product and what should we improve?\"":["Formul\u00e1rio de feedback para perguntar aos clientes: \"Como voc\u00ea classificaria nosso produto e o que devemos melhorar?\""],"Event registration form for \"Photography Workshop\" with date and seat selection":["Formul\u00e1rio de inscri\u00e7\u00e3o para o evento \"Workshop de Fotografia\" com sele\u00e7\u00e3o de data e assento"],"Newsletter signup form with name and email to join mailing list":["Formul\u00e1rio de inscri\u00e7\u00e3o para newsletter com nome e email para entrar na lista de correio"],"Order form for \"Custom T-Shirt\" with size, color, and quantity options":["Formul\u00e1rio de pedido para \"Camiseta Personalizada\" com op\u00e7\u00f5es de tamanho, cor e quantidade"],"Survey form: \"How satisfied are you with our service? (1\u20135 stars)\"":["Formul\u00e1rio de pesquisa: \"Qu\u00e3o satisfeito est\u00e1 com o nosso servi\u00e7o? (1\u20135 estrelas)\""],"Appointment booking form for \"Consultation Call\" with preferred time":["Formul\u00e1rio de agendamento para \"Chamada de Consulta\" com hor\u00e1rio preferido"],"Describe the form that you want":["Descreva o formul\u00e1rio que voc\u00ea deseja"],"Generate":["Gerar"],"Create Unlimited Forms with AI":["Crie Formul\u00e1rios Ilimitados com IA"],"Add Advanced Field Types":["Adicionar Tipos de Campos Avan\u00e7ados"],"Create Calculators, Surveys, etc.":["Criar Calculadoras, Pesquisas, etc."],"Form Generation Limit Reached":["Limite de Gera\u00e7\u00e3o de Formul\u00e1rio Atingido"],"You have reached the maximum number of form generations in your Free Plan. SureForms Premium allows:":["Voc\u00ea atingiu o n\u00famero m\u00e1ximo de gera\u00e7\u00f5es de formul\u00e1rios no seu Plano Gratuito. O SureForms Premium permite:"],"%s AI Generations Left.":["%s Gera\u00e7\u00f5es de IA Restantes."],"Unlock Unlimited Generations":["Desbloqueie Gera\u00e7\u00f5es Ilimitadas"],"Connect to SureForms AI":["Conectar ao SureForms AI"],"You Have Hit Your Free Limit.":["Voc\u00ea atingiu o seu limite gratuito."],"Connect to SureForms AI to Get 10 More.":["Conecte-se ao SureForms AI para obter mais 10."],"Or create it yourself":["Ou crie voc\u00ea mesmo"],"Unable to create form":["N\u00e3o foi poss\u00edvel criar o formul\u00e1rio"],"Something went wrong. Please try again.":["Algo deu errado. Por favor, tente novamente."],"Describe what kind of form you want":["Descreva que tipo de formul\u00e1rio voc\u00ea deseja"],"Click to generate the form":["Clique para gerar o formul\u00e1rio"],"Connecting to AI service":["Conectando ao servi\u00e7o de IA"],"Generating fields":["Gerando campos"],"Finalizing your form":["Finalizando seu formul\u00e1rio"],"Opening form editor":["Abrindo o editor de formul\u00e1rios"],"Design Multistep Forms":["Projetar Formul\u00e1rios Multietapas"],"Send Form Entries to Your CRM or Any App":["Envie entradas de formul\u00e1rio para o seu CRM ou qualquer aplicativo"],"You've reached your daily generation limit.":["Voc\u00ea atingiu o seu limite di\u00e1rio de gera\u00e7\u00e3o."],"You've reached your daily limit for AI form generations.":["Voc\u00ea atingiu seu limite di\u00e1rio para gera\u00e7\u00f5es de formul\u00e1rios de IA."],"Quiz":["Question\u00e1rio"],"Unlock Quiz Forms":["Desbloquear Formul\u00e1rios de Question\u00e1rio"],"Create Engaging Quizzes That Score Automatically":["Crie question\u00e1rios envolventes que pontuam automaticamente"],"Build interactive quizzes with scored questions and graded results. Perfect for assessments, trivia, and educational content.":["Crie question\u00e1rios interativos com perguntas pontuadas e resultados avaliados. Perfeito para avalia\u00e7\u00f5es, curiosidades e conte\u00fado educacional."],"Auto-score responses instantly":["Avaliar respostas instantaneamente"],"Display graded results to users":["Exibir resultados avaliados para os usu\u00e1rios"],"Perfect for education, training, and fun trivia":["Perfeito para educa\u00e7\u00e3o, treinamento e curiosidades divertidas"],"Select this to create a quiz with scored questions and graded results.":["Selecione isto para criar um question\u00e1rio com perguntas pontuadas e resultados avaliados."],"Select this to create a survey to collect responses and opinions.":["Selecione isto para criar uma pesquisa para coletar respostas e opini\u00f5es."],"Survey":["Pesquisa"],"Unlock Survey Forms":["Desbloquear Formul\u00e1rios de Pesquisa"],"Collect Insights with Powerful Surveys":["Recolha insights com pesquisas poderosas"],"Create surveys to collect responses and opinions. Visualize results with charts and share aggregated insights with your audience.":["Crie pesquisas para coletar respostas e opini\u00f5es. Visualize os resultados com gr\u00e1ficos e compartilhe insights agregados com seu p\u00fablico."],"Aggregate and visualize responses":["Agregue e visualize respostas"],"Show live results to respondents":["Mostrar resultados ao vivo aos respondentes"],"Perfect for feedback, polls, and research":["Perfeito para feedback, pesquisas e sondagens"],"You do not have permission to create forms.":["Voc\u00ea n\u00e3o tem permiss\u00e3o para criar formul\u00e1rios."],"The form could not be saved. Please try again.":["O formul\u00e1rio n\u00e3o p\u00f4de ser salvo. Por favor, tente novamente."],"Unable to reach the SureForms AI service. Please check your connection and try again.":["N\u00e3o foi poss\u00edvel acessar o servi\u00e7o SureForms AI. Por favor, verifique sua conex\u00e3o e tente novamente."],"The AI service did not return a response. Please try again.":["O servi\u00e7o de IA n\u00e3o retornou uma resposta. Por favor, tente novamente."],"Form generation failed. Please try again.":["A gera\u00e7\u00e3o do formul\u00e1rio falhou. Por favor, tente novamente."],"The AI response was empty. Please refine your prompt and try again.":["A resposta da IA estava vazia. Por favor, refine seu prompt e tente novamente."],"Unable to build form fields from the AI response.":["N\u00e3o foi poss\u00edvel criar campos de formul\u00e1rio a partir da resposta da IA."]}}} \ No newline at end of file diff --git a/languages/sureforms-pt_PT-4b62e3f004dea2c587b5a3069263d994.json b/languages/sureforms-pt_PT-4b62e3f004dea2c587b5a3069263d994.json index ca4fa991c..5193e1963 100644 --- a/languages/sureforms-pt_PT-4b62e3f004dea2c587b5a3069263d994.json +++ b/languages/sureforms-pt_PT-4b62e3f004dea2c587b5a3069263d994.json @@ -1 +1 @@ -{"translation-revision-date":"2025-01-02T08:44:42+00:00","generator":"WP-CLI\/2.12.0","source":"assets\/build\/blocks.js","domain":"messages","locale_data":{"messages":{"":{"domain":"messages","lang":"en","plural-forms":"nplurals=2; plural=(n != 1);"},"Settings":["Configura\u00e7\u00f5es"],"Search":["Pesquisar"],"Fields":["Campos"],"Image":["Imagem"],"Submit":["Enviar"],"Required":["Obrigat\u00f3rio"],"Form Title":["T\u00edtulo do Formul\u00e1rio"],"Show":["Mostrar"],"Hide":["Esconder"],"Edit Form":["Editar Formul\u00e1rio"],"Icon":["\u00cdcone"],"Desktop":["\u00c1rea de trabalho"],"Medium":["M\u00e9dio"],"Mobile":["M\u00f3vel"],"Repeat":["Repetir"],"Scroll":["Rolar"],"Tablet":["Tablet"],"Basic":["B\u00e1sico"],"(no title)":["(sem t\u00edtulo)"],"Select a Form":["Selecione um Formul\u00e1rio"],"No forms found\u2026":["Nenhum formul\u00e1rio encontrado\u2026"],"Choose":["Escolher"],"Create New":["Criar Novo"],"Change Form":["Alterar Formul\u00e1rio"],"This form has been deleted or is unavailable.":["Este formul\u00e1rio foi exclu\u00eddo ou est\u00e1 indispon\u00edvel."],"Form Settings":["Configura\u00e7\u00f5es do Formul\u00e1rio"],"Show Form Title on this Page":["Mostrar t\u00edtulo do formul\u00e1rio nesta p\u00e1gina"],"Note: For editing SureForms, please refer to the SureForms Editor - ":["Nota: Para editar SureForms, consulte o Editor de SureForms -"],"Field preview":["Pr\u00e9-visualiza\u00e7\u00e3o do campo"],"General":["Geral"],"Style":["Estilo"],"Advanced":["Avan\u00e7ado"],"No tags available":["Sem etiquetas dispon\u00edveis"],"Device":["Dispositivo"],"Select Shortcodes":["Selecionar C\u00f3digos Curtos"],"Page Break Label":["R\u00f3tulo de Quebra de P\u00e1gina"],"Next":["Pr\u00f3ximo"],"Back":["Voltar"],"Reset":["Redefinir"],"Generic tags":["Etiquetas gen\u00e9ricas"],"Pixel":["Pixel"],"Em":["Em"],"Select Units":["Selecionar Unidades"],"%s units":["%s unidades"],"Margin":["Margem"],"Attributes":["Atributos"],"Input Pattern":["Padr\u00e3o de Entrada"],"None":["Nenhum"],"(###) ###-####":["(###) ###-####"],"(##) ####-####":["(##) ####-####"],"27\/08\/2024":["27\/08\/2024"],"23:59:59":["23:59:59"],"27\/08\/2024 23:59:59":["27\/08\/2024 23:59:59"],"Custom":["Personalizado"],"Custom Mask":["M\u00e1scara Personalizada"],"Please check the documentation to manage custom input pattern ":["Por favor, verifique a documenta\u00e7\u00e3o para gerenciar o padr\u00e3o de entrada personalizado"],"here":["aqui"],"Default Value":["Valor Padr\u00e3o"],"Error Message":["Mensagem de Erro"],"Help Text":["Texto de Ajuda"],"Number Format":["Formato de N\u00famero"],"US Style (Eg: 9,999.99)":["Estilo dos EUA (Ex: 9.999,99)"],"EU Style (Eg: 9.999,99)":["Estilo da UE (Ex: 9.999,99)"],"Minimum Value":["Valor M\u00ednimo"],"Maximum Value":["Valor M\u00e1ximo"],"Please check the Minimum and Maximum value":["Por favor, verifique o valor M\u00ednimo e M\u00e1ximo"],"Enable Email Confirmation":["Ativar Confirma\u00e7\u00e3o de E-mail"],"Checked by Default":["Marcado por padr\u00e3o"],"Error message":["Mensagem de erro"],"Checked by default":["Marcado por padr\u00e3o"],"Please add a option props to MultiButtonsControl":["Por favor, adicione uma op\u00e7\u00e3o de propriedades ao MultiButtonsControl"],"Icon Library":["Biblioteca de \u00cdcones"],"Close":["Fechar"],"All Icons":["Todas as \u00cdcones"],"Other":["Outro"],"No Icons Found":["Nenhum \u00edcone encontrado"],"Insert Icon":["Inserir \u00cdcone"],"Change Icon":["Alterar \u00cdcone"],"Choose Icon":["Escolher \u00cdcone"],"Confirm":["Confirmar"],"Cancel":["Cancelar"],"Processing\u2026":["Processando\u2026"],"Select Video":["Selecionar V\u00eddeo"],"Change Video":["Alterar V\u00eddeo"],"Select Lottie Animation":["Selecionar Anima\u00e7\u00e3o Lottie"],"Change Lottie Animation":["Alterar Anima\u00e7\u00e3o Lottie"],"Upload SVG":["Carregar SVG"],"Change SVG":["Alterar SVG"],"Select Image":["Selecionar imagem"],"Change Image":["Alterar Imagem"],"Upload SVG?":["Carregar SVG?"],"Upload SVG can be potentially risky. Are you sure?":["Fazer upload de SVG pode ser potencialmente arriscado. Tem certeza?"],"Upload Anyway":["Carregar Mesmo Assim"],"Bulk Add":["Adicionar em Massa"],"Bulk Add Options":["Adicionar Op\u00e7\u00f5es em Massa"],"Enter each option on a new line.":["Digite cada op\u00e7\u00e3o em uma nova linha."],"Insert Options":["Inserir Op\u00e7\u00f5es"],"Full Width":["Largura Total"],"Option Type":["Tipo de Op\u00e7\u00e3o"],"Edit Options":["Editar Op\u00e7\u00f5es"],"Add New Option":["Adicionar nova op\u00e7\u00e3o"],"ADD":["ADICIONAR"],"Enable Auto Country Detection":["Ativar Detec\u00e7\u00e3o Autom\u00e1tica de Pa\u00eds"],"%s Width":["Largura %s"],"Upgrade":["Atualizar"],"Clear":["Limpar"],"Select Color":["Selecionar Cor"],"Primary Color":["Cor Prim\u00e1ria"],"Text Color":["Cor do Texto"],"Field Spacing":["Espa\u00e7amento de Campo"],"Small":["Pequeno"],"Large":["Grande"],"Left":["Esquerda"],"Center":["Centro"],"Right":["Certo"],"Color":["Cor"],"Background Color":["Cor de Fundo"],"Auto":["Carro"],"Default":["Padr\u00e3o"],"Normal":["Normal"],"%":["%"],"Top":["Topo"],"Bottom":["Inferior"],"Width":["Largura"],"Size":["Tamanho"],"EM":["EM"],"Padding":["Preenchimento"],"Color 1":["Cor 1"],"Color 2":["Cor 2"],"Type":["Digite"],"Linear":["Linear"],"Radial":["Radial"],"Location 1":["Localiza\u00e7\u00e3o 1"],"Location 2":["Localiza\u00e7\u00e3o 2"],"Angle":["\u00c2ngulo"],"Classic":["Cl\u00e1ssico"],"Gradient":["Gradiente"],"Horizontal":["Horizontal"],"Vertical":["Vertical"],"Background":["Fundo"],"Cover":["Cobertura"],"Contain":["Conter"],"Layout":["Layout"],"Overlay":["Sobreposi\u00e7\u00e3o"],"No Repeat":["Sem repeti\u00e7\u00e3o"],"Overlay Opacity":["Opacidade da Sobreposi\u00e7\u00e3o"],"Conditional Logic":["L\u00f3gica Condicional"],"Upgrade to the SureForms Starter Plan to create dynamic forms that adapt based on user input, offering a personalised and efficient form experience.":["Fa\u00e7a upgrade para o Plano Starter do SureForms para criar formul\u00e1rios din\u00e2micos que se adaptam com base nas entradas do usu\u00e1rio, oferecendo uma experi\u00eancia de formul\u00e1rio personalizada e eficiente."],"Enable Conditional Logic":["Ativar L\u00f3gica Condicional"],"this field if":["este campo se"],"Configure Conditions":["Configurar Condi\u00e7\u00f5es"],"Premium":["Premium"],"Overlay Type":["Tipo de Sobreposi\u00e7\u00e3o"],"Image Overlay Color":["Cor de Sobreposi\u00e7\u00e3o da Imagem"],"Image Position":["Posi\u00e7\u00e3o da Imagem"],"Attachment":["Anexo"],"Fixed":["Fixo"],"Blend Mode":["Modo de Mesclagem"],"Multiply":["Multiplicar"],"Screen":["Tela"],"Darken":["Escurecer"],"Lighten":["Iluminar"],"Color Dodge":["Esquiva de Cor"],"Saturation":["Satura\u00e7\u00e3o"],"Repeat-x":["Repetir-x"],"Repeat-y":["Repita-y"],"PX":["PX"],"Button":["Bot\u00e3o"],"Prefix Label":["R\u00f3tulo de Prefixo"],"Suffix Label":["R\u00f3tulo de Sufixo"],"Border Radius":["Raio da Borda"],"Form Theme":["Tema do Formul\u00e1rio"],"Select Gradient":["Selecionar Gradiente"],"Unlock Conditional Logic Editor":["Desbloquear Editor de L\u00f3gica Condicional"],"Rich Text Editor":["Editor de Texto Rico"],"Read Only":["Apenas leitura"],"Select Country":["Selecionar Pa\u00eds"],"Default Country":["Pa\u00eds Padr\u00e3o"],"Subscription":["Assinatura"],"One Time":["Uma Vez"],"Unique Entry":["Entrada \u00danica"],"Maximum Characters":["M\u00e1ximo de caracteres"],"Textarea Height":["Altura da \u00c1rea de Texto"],"Minimum Selections":["Sele\u00e7\u00f5es M\u00ednimas"],"Maximum Selections":["Sele\u00e7\u00f5es M\u00e1ximas"],"Add Numeric Values to Options":["Adicionar valores num\u00e9ricos \u00e0s op\u00e7\u00f5es"],"Single Choice Only":["Apenas uma escolha"],"Enable Dropdown Search":["Ativar Pesquisa em Dropdown"],"Allow Multiple":["Permitir M\u00faltiplos"],"%1$s fields are required. Please configure these fields in the block settings.":["Os campos %1$s s\u00e3o obrigat\u00f3rios. Por favor, configure esses campos nas configura\u00e7\u00f5es do bloco."],"%1$s field is required. Please configure this field in the block settings.":["O campo %1$s \u00e9 obrigat\u00f3rio. Por favor, configure este campo nas configura\u00e7\u00f5es do bloco."],"You need to configure a payment account to collect payments from this form. Please configure your payment provider to proceed.":["Voc\u00ea precisa configurar uma conta de pagamento para coletar pagamentos deste formul\u00e1rio. Por favor, configure seu provedor de pagamento para continuar."],"Configure Payment Account":["Configurar Conta de Pagamento"],"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.":["Este \u00e9 um espa\u00e7o reservado para o bloco de Pagamento. Os campos de pagamento reais para o(s) provedor(es) de pagamento configurado(s) s\u00f3 aparecer\u00e3o quando voc\u00ea visualizar ou publicar o formul\u00e1rio."],"2 Payments":["2 Pagamentos"],"3 Payments":["3 Pagamentos"],"4 Payments":["4 Pagamentos"],"5 Payments":["5 Pagamentos"],"Never":["Nunca"],"Stop Subscription After":["Parar Assinatura Ap\u00f3s"],"Choose when to automatically stop the subscription":["Escolha quando parar automaticamente a assinatura"],"Number of Payments":["N\u00famero de Pagamentos"],"Enter a number between 1 to 100":["Insira um n\u00famero entre 1 e 100"],"Form Field":["Campo de Formul\u00e1rio"],"Payment Type":["Tipo de Pagamento"],"Subscription Plan Name":["Nome do Plano de Assinatura"],"Billing Interval":["Intervalo de Cobran\u00e7a"],"Daily":["Diariamente"],"Weekly":["Semanalmente"],"Monthly":["Mensal"],"Quarterly":["Trimestral"],"Yearly":["Anual"],"Amount Type":["Tipo de Quantia"],"Fixed Amount":["Quantia Fixa"],"Dynamic Amount":["Montante Din\u00e2mico"],"Choose whether to charge a fixed amount or charge the amount based on user input in other form fields.":["Escolha entre cobrar um valor fixo ou cobrar o valor com base na entrada do usu\u00e1rio em outros campos do formul\u00e1rio."],"Set the exact amount you want to charge. Users won\u2019t be able to change it":["Defina o valor exato que deseja cobrar. Os usu\u00e1rios n\u00e3o poder\u00e3o alter\u00e1-lo"],"Choose Amount Field":["Escolher Campo de Quantidade"],"Select a field\u2026":["Selecione um campo\u2026"],"Pick a field from your form like a number, dropdown, or multichoice whose value should decide the payment amount.":["Escolha um campo do seu formul\u00e1rio, como um n\u00famero, menu suspenso ou m\u00faltipla escolha, cujo valor deve determinar o valor do pagamento."],"Minimum Amount":["Quantidade M\u00ednima"],"Set the minimum amount users can enter (0 for no minimum)":["Defina o valor m\u00ednimo que os usu\u00e1rios podem inserir (0 para sem m\u00ednimo)"],"Customer Name Field (Required)":["Campo Nome do Cliente (Obrigat\u00f3rio)"],"Customer Name Field (Optional)":["Campo Nome do Cliente (Opcional)"],"Select the input field that contains the customer name (Required for subscriptions)":["Selecione o campo de entrada que cont\u00e9m o nome do cliente (Obrigat\u00f3rio para assinaturas)"],"Select the input field that contains the customer name":["Selecione o campo de entrada que cont\u00e9m o nome do cliente"],"Customer Email Field (Required)":["Campo de Email do Cliente (Obrigat\u00f3rio)"],"Select the email field that contains the customer email":["Selecione o campo de email que cont\u00e9m o email do cliente"],"Payment":["Pagamento"],"%s - Order ID":["%s - ID do Pedido"],"%s - Amount":["%s - Quantidade"],"%s - Customer Email":["%s - Email do Cliente"],"%s - Customer Name":["%s - Nome do Cliente"],"%s - Status":["%s - Status"],"Button Alignment":["Alinhamento do Bot\u00e3o"],"Placeholder":["Espa\u00e7o reservado"],"Preselect this option":["Pr\u00e9-selecione esta op\u00e7\u00e3o"],"Restrict Country Codes":["Restringir C\u00f3digos de Pa\u00eds"],"Restriction Type":["Tipo de Restri\u00e7\u00e3o"],"Allow":["Permitir"],"Block":["Bloquear"],"Select Allowed Countries":["Selecionar Pa\u00edses Permitidos"],"Choose countries\u2026":["Escolha pa\u00edses\u2026"],"Choose which country codes users can select in the phone number field. Leave empty to allow all country codes.":["Escolha quais c\u00f3digos de pa\u00eds os usu\u00e1rios podem selecionar no campo de n\u00famero de telefone. Deixe em branco para permitir todos os c\u00f3digos de pa\u00eds."],"Select Blocked Countries":["Selecionar Pa\u00edses Bloqueados"],"These countries will be hidden from the dropdown.":["Esses pa\u00edses ser\u00e3o ocultados do menu suspenso."],"Bulk Edit":["Edi\u00e7\u00e3o em Massa"],"Select Layout":["Selecionar Layout"],"Number of Columns":["N\u00famero de Colunas"],"Validation Message for Duplicate":["Mensagem de Valida\u00e7\u00e3o para Duplicado"],"Click here to insert a form":["Clique aqui para inserir um formul\u00e1rio"],"Inherit Form's Original Style":["Herdar o Estilo Original do Formul\u00e1rio"],"Text on Primary":["Texto no Prim\u00e1rio"],"%s - Description":["%s - Descri\u00e7\u00e3o"],"Upgrade to Unlock":["Atualize para Desbloquear"],"Custom (Premium)":["Personalizado (Premium)"],"Select a theme style for this form embed.":["Selecione um estilo de tema para este formul\u00e1rio incorporado."],"Colors":["Cores"],"Advanced Styling":["Estilo Avan\u00e7ado"],"Unlock Custom Styling":["Desbloquear Estilo Personalizado"],"Switch to Custom Mode to take full control of your form's design and spacing.":["Alterne para o Modo Personalizado para ter controle total sobre o design e o espa\u00e7amento do seu formul\u00e1rio."],"Full color control (buttons, fields, text)":["Controle total de cores (bot\u00f5es, campos, texto)"],"Row and column gap control":["Controle de espa\u00e7amento entre linhas e colunas"],"Field spacing and layout precision":["Precis\u00e3o de espa\u00e7amento e layout de campo"],"Complete button styling":["Estiliza\u00e7\u00e3o completa do bot\u00e3o"],"Payment Description":["Descri\u00e7\u00e3o do Pagamento"],"Shown on payment receipts and in your payment dashboard (Stripe and PayPal). Leave blank to use the default.":["Mostrado nos recibos de pagamento e no seu painel de pagamento (Stripe e PayPal). Deixe em branco para usar o padr\u00e3o."],"Slug":["Lesma"],"Auto-generated on save":["Gerado automaticamente ao salvar"],"This slug is already used by another field. It will revert to the previous value.":["Este slug j\u00e1 est\u00e1 sendo usado por outro campo. Ele voltar\u00e1 ao valor anterior."],"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.":["Alterar o slug pode quebrar envios de formul\u00e1rios, l\u00f3gica condicional, integra\u00e7\u00f5es ou qualquer outra funcionalidade que atualmente fa\u00e7a refer\u00eancia a este slug. Voc\u00ea precisar\u00e1 atualizar todas essas refer\u00eancias manualmente."],"Field Slug":["Slug do Campo"],"Location Services":["Servi\u00e7os de Localiza\u00e7\u00e3o"],"Unlock Address Autocomplete":["Desbloquear Autocompletar Endere\u00e7o"],"Upgrade to enable Google Address Autocomplete with interactive map preview, making address entry faster and more accurate for your users.":["Atualize para habilitar o Autocomplete de Endere\u00e7o do Google com visualiza\u00e7\u00e3o interativa do mapa, tornando a entrada de endere\u00e7os mais r\u00e1pida e precisa para seus usu\u00e1rios."],"Enable Google Autocomplete":["Ativar o Autocomplete do Google"],"Show Interactive Map":["Mostrar Mapa Interativo"],"Payments Per Page":["Pagamentos Por P\u00e1gina"],"Show Subscriptions Section":["Mostrar se\u00e7\u00e3o de assinaturas"],"Show a dedicated subscriptions section above payment history.":["Mostrar uma se\u00e7\u00e3o dedicada a assinaturas acima do hist\u00f3rico de pagamentos."],"Payment Dashboard":["Painel de Pagamentos"],"View your payments and manage subscriptions in a single dashboard.":["Veja seus pagamentos e gerencie assinaturas em um \u00fanico painel."],"Dynamic Default Value":["Valor Padr\u00e3o Din\u00e2mico"]}}} \ No newline at end of file +{"translation-revision-date":"2025-01-02T08:44:42+00:00","generator":"WP-CLI\/2.12.0","source":"assets\/build\/blocks.js","domain":"messages","locale_data":{"messages":{"":{"domain":"messages","lang":"en","plural-forms":"nplurals=2; plural=(n != 1);"},"Settings":["Configura\u00e7\u00f5es"],"Search":["Pesquisar"],"Fields":["Campos"],"Image":["Imagem"],"Submit":["Enviar"],"Required":["Obrigat\u00f3rio"],"Form Title":["T\u00edtulo do Formul\u00e1rio"],"Show":["Mostrar"],"Hide":["Esconder"],"Edit Form":["Editar Formul\u00e1rio"],"Icon":["\u00cdcone"],"Desktop":["\u00c1rea de trabalho"],"Medium":["M\u00e9dio"],"Mobile":["M\u00f3vel"],"Repeat":["Repetir"],"Scroll":["Rolar"],"Tablet":["Tablet"],"Basic":["B\u00e1sico"],"(no title)":["(sem t\u00edtulo)"],"Select a Form":["Selecione um Formul\u00e1rio"],"No forms found\u2026":["Nenhum formul\u00e1rio encontrado\u2026"],"Choose":["Escolher"],"Create New":["Criar Novo"],"Change Form":["Alterar Formul\u00e1rio"],"This form has been deleted or is unavailable.":["Este formul\u00e1rio foi exclu\u00eddo ou est\u00e1 indispon\u00edvel."],"Form Settings":["Configura\u00e7\u00f5es do Formul\u00e1rio"],"Show Form Title on this Page":["Mostrar t\u00edtulo do formul\u00e1rio nesta p\u00e1gina"],"Note: For editing SureForms, please refer to the SureForms Editor - ":["Nota: Para editar SureForms, consulte o Editor de SureForms -"],"Field preview":["Pr\u00e9-visualiza\u00e7\u00e3o do campo"],"General":["Geral"],"Style":["Estilo"],"Advanced":["Avan\u00e7ado"],"No tags available":["Sem etiquetas dispon\u00edveis"],"Device":["Dispositivo"],"Select Shortcodes":["Selecionar C\u00f3digos Curtos"],"Page Break Label":["R\u00f3tulo de Quebra de P\u00e1gina"],"Next":["Pr\u00f3ximo"],"Back":["Voltar"],"Reset":["Redefinir"],"Generic tags":["Etiquetas gen\u00e9ricas"],"Pixel":["Pixel"],"Em":["Em"],"Select Units":["Selecionar Unidades"],"%s units":["%s unidades"],"Margin":["Margem"],"Attributes":["Atributos"],"Input Pattern":["Padr\u00e3o de Entrada"],"None":["Nenhum"],"(###) ###-####":["(###) ###-####"],"(##) ####-####":["(##) ####-####"],"27\/08\/2024":["27\/08\/2024"],"23:59:59":["23:59:59"],"27\/08\/2024 23:59:59":["27\/08\/2024 23:59:59"],"Custom":["Personalizado"],"Custom Mask":["M\u00e1scara Personalizada"],"Please check the documentation to manage custom input pattern ":["Por favor, verifique a documenta\u00e7\u00e3o para gerenciar o padr\u00e3o de entrada personalizado"],"here":["aqui"],"Default Value":["Valor Padr\u00e3o"],"Error Message":["Mensagem de Erro"],"Help Text":["Texto de Ajuda"],"Number Format":["Formato de N\u00famero"],"US Style (Eg: 9,999.99)":["Estilo dos EUA (Ex: 9.999,99)"],"EU Style (Eg: 9.999,99)":["Estilo da UE (Ex: 9.999,99)"],"Minimum Value":["Valor M\u00ednimo"],"Maximum Value":["Valor M\u00e1ximo"],"Please check the Minimum and Maximum value":["Por favor, verifique o valor M\u00ednimo e M\u00e1ximo"],"Enable Email Confirmation":["Ativar Confirma\u00e7\u00e3o de E-mail"],"Checked by Default":["Marcado por padr\u00e3o"],"Error message":["Mensagem de erro"],"Checked by default":["Marcado por padr\u00e3o"],"Please add a option props to MultiButtonsControl":["Por favor, adicione uma op\u00e7\u00e3o de propriedades ao MultiButtonsControl"],"Icon Library":["Biblioteca de \u00cdcones"],"Close":["Fechar"],"All Icons":["Todas as \u00cdcones"],"Other":["Outro"],"No Icons Found":["Nenhum \u00edcone encontrado"],"Insert Icon":["Inserir \u00cdcone"],"Change Icon":["Alterar \u00cdcone"],"Choose Icon":["Escolher \u00cdcone"],"Confirm":["Confirmar"],"Cancel":["Cancelar"],"Processing\u2026":["Processando\u2026"],"Select Video":["Selecionar V\u00eddeo"],"Change Video":["Alterar V\u00eddeo"],"Select Lottie Animation":["Selecionar Anima\u00e7\u00e3o Lottie"],"Change Lottie Animation":["Alterar Anima\u00e7\u00e3o Lottie"],"Upload SVG":["Carregar SVG"],"Change SVG":["Alterar SVG"],"Select Image":["Selecionar imagem"],"Change Image":["Alterar Imagem"],"Upload SVG?":["Carregar SVG?"],"Upload SVG can be potentially risky. Are you sure?":["Fazer upload de SVG pode ser potencialmente arriscado. Tem certeza?"],"Upload Anyway":["Carregar Mesmo Assim"],"Bulk Add":["Adicionar em Massa"],"Bulk Add Options":["Adicionar Op\u00e7\u00f5es em Massa"],"Enter each option on a new line.":["Digite cada op\u00e7\u00e3o em uma nova linha."],"Insert Options":["Inserir Op\u00e7\u00f5es"],"Full Width":["Largura Total"],"Option Type":["Tipo de Op\u00e7\u00e3o"],"Edit Options":["Editar Op\u00e7\u00f5es"],"Add New Option":["Adicionar nova op\u00e7\u00e3o"],"ADD":["ADICIONAR"],"Enable Auto Country Detection":["Ativar Detec\u00e7\u00e3o Autom\u00e1tica de Pa\u00eds"],"%s Width":["Largura %s"],"Upgrade":["Atualizar"],"Clear":["Limpar"],"Select Color":["Selecionar Cor"],"Primary Color":["Cor Prim\u00e1ria"],"Text Color":["Cor do Texto"],"Field Spacing":["Espa\u00e7amento de Campo"],"Small":["Pequeno"],"Large":["Grande"],"Left":["Esquerda"],"Center":["Centro"],"Right":["Certo"],"Color":["Cor"],"Background Color":["Cor de Fundo"],"Auto":["Carro"],"Default":["Padr\u00e3o"],"Normal":["Normal"],"%":["%"],"Top":["Topo"],"Bottom":["Inferior"],"Width":["Largura"],"Size":["Tamanho"],"EM":["EM"],"Padding":["Preenchimento"],"Color 1":["Cor 1"],"Color 2":["Cor 2"],"Type":["Digite"],"Linear":["Linear"],"Radial":["Radial"],"Location 1":["Localiza\u00e7\u00e3o 1"],"Location 2":["Localiza\u00e7\u00e3o 2"],"Angle":["\u00c2ngulo"],"Classic":["Cl\u00e1ssico"],"Gradient":["Gradiente"],"Horizontal":["Horizontal"],"Vertical":["Vertical"],"Background":["Fundo"],"Cover":["Cobertura"],"Contain":["Conter"],"Layout":["Layout"],"Overlay":["Sobreposi\u00e7\u00e3o"],"No Repeat":["Sem repeti\u00e7\u00e3o"],"Overlay Opacity":["Opacidade da Sobreposi\u00e7\u00e3o"],"Conditional Logic":["L\u00f3gica Condicional"],"Upgrade to the SureForms Starter Plan to create dynamic forms that adapt based on user input, offering a personalised and efficient form experience.":["Fa\u00e7a upgrade para o Plano Starter do SureForms para criar formul\u00e1rios din\u00e2micos que se adaptam com base nas entradas do usu\u00e1rio, oferecendo uma experi\u00eancia de formul\u00e1rio personalizada e eficiente."],"Enable Conditional Logic":["Ativar L\u00f3gica Condicional"],"this field if":["este campo se"],"Configure Conditions":["Configurar Condi\u00e7\u00f5es"],"Premium":["Premium"],"Overlay Type":["Tipo de Sobreposi\u00e7\u00e3o"],"Image Overlay Color":["Cor de Sobreposi\u00e7\u00e3o da Imagem"],"Image Position":["Posi\u00e7\u00e3o da Imagem"],"Attachment":["Anexo"],"Fixed":["Fixo"],"Blend Mode":["Modo de Mesclagem"],"Multiply":["Multiplicar"],"Screen":["Tela"],"Darken":["Escurecer"],"Lighten":["Iluminar"],"Color Dodge":["Esquiva de Cor"],"Saturation":["Satura\u00e7\u00e3o"],"Repeat-x":["Repetir-x"],"Repeat-y":["Repita-y"],"PX":["PX"],"Button":["Bot\u00e3o"],"Prefix Label":["R\u00f3tulo de Prefixo"],"Suffix Label":["R\u00f3tulo de Sufixo"],"Border Radius":["Raio da Borda"],"Form Theme":["Tema do Formul\u00e1rio"],"Select Gradient":["Selecionar Gradiente"],"Unlock Conditional Logic Editor":["Desbloquear Editor de L\u00f3gica Condicional"],"Rich Text Editor":["Editor de Texto Rico"],"Read Only":["Apenas leitura"],"Select Country":["Selecionar Pa\u00eds"],"Default Country":["Pa\u00eds Padr\u00e3o"],"Subscription":["Assinatura"],"One Time":["Uma Vez"],"Unique Entry":["Entrada \u00danica"],"Maximum Characters":["M\u00e1ximo de caracteres"],"Textarea Height":["Altura da \u00c1rea de Texto"],"Minimum Selections":["Sele\u00e7\u00f5es M\u00ednimas"],"Maximum Selections":["Sele\u00e7\u00f5es M\u00e1ximas"],"Add Numeric Values to Options":["Adicionar valores num\u00e9ricos \u00e0s op\u00e7\u00f5es"],"Single Choice Only":["Apenas uma escolha"],"Enable Dropdown Search":["Ativar Pesquisa em Dropdown"],"Allow Multiple":["Permitir M\u00faltiplos"],"%1$s fields are required. Please configure these fields in the block settings.":["Os campos %1$s s\u00e3o obrigat\u00f3rios. Por favor, configure esses campos nas configura\u00e7\u00f5es do bloco."],"%1$s field is required. Please configure this field in the block settings.":["O campo %1$s \u00e9 obrigat\u00f3rio. Por favor, configure este campo nas configura\u00e7\u00f5es do bloco."],"You need to configure a payment account to collect payments from this form. Please configure your payment provider to proceed.":["Voc\u00ea precisa configurar uma conta de pagamento para coletar pagamentos deste formul\u00e1rio. Por favor, configure seu provedor de pagamento para continuar."],"Configure Payment Account":["Configurar Conta de Pagamento"],"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.":["Este \u00e9 um espa\u00e7o reservado para o bloco de Pagamento. Os campos de pagamento reais para o(s) provedor(es) de pagamento configurado(s) s\u00f3 aparecer\u00e3o quando voc\u00ea visualizar ou publicar o formul\u00e1rio."],"2 Payments":["2 Pagamentos"],"3 Payments":["3 Pagamentos"],"4 Payments":["4 Pagamentos"],"5 Payments":["5 Pagamentos"],"Never":["Nunca"],"Stop Subscription After":["Parar Assinatura Ap\u00f3s"],"Choose when to automatically stop the subscription":["Escolha quando parar automaticamente a assinatura"],"Number of Payments":["N\u00famero de Pagamentos"],"Enter a number between 1 to 100":["Insira um n\u00famero entre 1 e 100"],"Form Field":["Campo de Formul\u00e1rio"],"Payment Type":["Tipo de Pagamento"],"Subscription Plan Name":["Nome do Plano de Assinatura"],"Billing Interval":["Intervalo de Cobran\u00e7a"],"Daily":["Diariamente"],"Weekly":["Semanalmente"],"Monthly":["Mensal"],"Quarterly":["Trimestral"],"Yearly":["Anual"],"Amount Type":["Tipo de Quantia"],"Fixed Amount":["Quantia Fixa"],"Dynamic Amount":["Montante Din\u00e2mico"],"Choose whether to charge a fixed amount or charge the amount based on user input in other form fields.":["Escolha entre cobrar um valor fixo ou cobrar o valor com base na entrada do usu\u00e1rio em outros campos do formul\u00e1rio."],"Set the exact amount you want to charge. Users won\u2019t be able to change it":["Defina o valor exato que deseja cobrar. Os usu\u00e1rios n\u00e3o poder\u00e3o alter\u00e1-lo"],"Choose Amount Field":["Escolher Campo de Quantidade"],"Select a field\u2026":["Selecione um campo\u2026"],"Minimum Amount":["Quantidade M\u00ednima"],"Set the minimum amount users can enter (0 for no minimum)":["Defina o valor m\u00ednimo que os usu\u00e1rios podem inserir (0 para sem m\u00ednimo)"],"Customer Name Field (Required)":["Campo Nome do Cliente (Obrigat\u00f3rio)"],"Customer Name Field (Optional)":["Campo Nome do Cliente (Opcional)"],"Select the input field that contains the customer name (Required for subscriptions)":["Selecione o campo de entrada que cont\u00e9m o nome do cliente (Obrigat\u00f3rio para assinaturas)"],"Select the input field that contains the customer name":["Selecione o campo de entrada que cont\u00e9m o nome do cliente"],"Customer Email Field (Required)":["Campo de Email do Cliente (Obrigat\u00f3rio)"],"Select the email field that contains the customer email":["Selecione o campo de email que cont\u00e9m o email do cliente"],"Payment":["Pagamento"],"%s - Order ID":["%s - ID do Pedido"],"%s - Amount":["%s - Quantidade"],"%s - Customer Email":["%s - Email do Cliente"],"%s - Customer Name":["%s - Nome do Cliente"],"%s - Status":["%s - Status"],"Button Alignment":["Alinhamento do Bot\u00e3o"],"Placeholder":["Espa\u00e7o reservado"],"Preselect this option":["Pr\u00e9-selecione esta op\u00e7\u00e3o"],"Restrict Country Codes":["Restringir C\u00f3digos de Pa\u00eds"],"Restriction Type":["Tipo de Restri\u00e7\u00e3o"],"Allow":["Permitir"],"Block":["Bloquear"],"Select Allowed Countries":["Selecionar Pa\u00edses Permitidos"],"Choose countries\u2026":["Escolha pa\u00edses\u2026"],"Choose which country codes users can select in the phone number field. Leave empty to allow all country codes.":["Escolha quais c\u00f3digos de pa\u00eds os usu\u00e1rios podem selecionar no campo de n\u00famero de telefone. Deixe em branco para permitir todos os c\u00f3digos de pa\u00eds."],"Select Blocked Countries":["Selecionar Pa\u00edses Bloqueados"],"These countries will be hidden from the dropdown.":["Esses pa\u00edses ser\u00e3o ocultados do menu suspenso."],"Bulk Edit":["Edi\u00e7\u00e3o em Massa"],"Select Layout":["Selecionar Layout"],"Number of Columns":["N\u00famero de Colunas"],"Validation Message for Duplicate":["Mensagem de Valida\u00e7\u00e3o para Duplicado"],"Click here to insert a form":["Clique aqui para inserir um formul\u00e1rio"],"Inherit Form's Original Style":["Herdar o Estilo Original do Formul\u00e1rio"],"Text on Primary":["Texto no Prim\u00e1rio"],"%s - Description":["%s - Descri\u00e7\u00e3o"],"Upgrade to Unlock":["Atualize para Desbloquear"],"Custom (Premium)":["Personalizado (Premium)"],"Select a theme style for this form embed.":["Selecione um estilo de tema para este formul\u00e1rio incorporado."],"Colors":["Cores"],"Advanced Styling":["Estilo Avan\u00e7ado"],"Unlock Custom Styling":["Desbloquear Estilo Personalizado"],"Switch to Custom Mode to take full control of your form's design and spacing.":["Alterne para o Modo Personalizado para ter controle total sobre o design e o espa\u00e7amento do seu formul\u00e1rio."],"Full color control (buttons, fields, text)":["Controle total de cores (bot\u00f5es, campos, texto)"],"Row and column gap control":["Controle de espa\u00e7amento entre linhas e colunas"],"Field spacing and layout precision":["Precis\u00e3o de espa\u00e7amento e layout de campo"],"Complete button styling":["Estiliza\u00e7\u00e3o completa do bot\u00e3o"],"Payment Description":["Descri\u00e7\u00e3o do Pagamento"],"Shown on payment receipts and in your payment dashboard (Stripe and PayPal). Leave blank to use the default.":["Mostrado nos recibos de pagamento e no seu painel de pagamento (Stripe e PayPal). Deixe em branco para usar o padr\u00e3o."],"Slug":["Lesma"],"Auto-generated on save":["Gerado automaticamente ao salvar"],"This slug is already used by another field. It will revert to the previous value.":["Este slug j\u00e1 est\u00e1 sendo usado por outro campo. Ele voltar\u00e1 ao valor anterior."],"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.":["Alterar o slug pode quebrar envios de formul\u00e1rios, l\u00f3gica condicional, integra\u00e7\u00f5es ou qualquer outra funcionalidade que atualmente fa\u00e7a refer\u00eancia a este slug. Voc\u00ea precisar\u00e1 atualizar todas essas refer\u00eancias manualmente."],"Field Slug":["Slug do Campo"],"Location Services":["Servi\u00e7os de Localiza\u00e7\u00e3o"],"Unlock Address Autocomplete":["Desbloquear Autocompletar Endere\u00e7o"],"Upgrade to enable Google Address Autocomplete with interactive map preview, making address entry faster and more accurate for your users.":["Atualize para habilitar o Autocomplete de Endere\u00e7o do Google com visualiza\u00e7\u00e3o interativa do mapa, tornando a entrada de endere\u00e7os mais r\u00e1pida e precisa para seus usu\u00e1rios."],"Enable Google Autocomplete":["Ativar o Autocomplete do Google"],"Show Interactive Map":["Mostrar Mapa Interativo"],"Payments Per Page":["Pagamentos Por P\u00e1gina"],"Show Subscriptions Section":["Mostrar se\u00e7\u00e3o de assinaturas"],"Show a dedicated subscriptions section above payment history.":["Mostrar uma se\u00e7\u00e3o dedicada a assinaturas acima do hist\u00f3rico de pagamentos."],"Payment Dashboard":["Painel de Pagamentos"],"View your payments and manage subscriptions in a single dashboard.":["Veja seus pagamentos e gerencie assinaturas em um \u00fanico painel."],"Dynamic Default Value":["Valor Padr\u00e3o Din\u00e2mico"],"Minimum Characters":["M\u00ednimo de Caracteres"],"Minimum characters cannot exceed Maximum characters.":["Os caracteres m\u00ednimos n\u00e3o podem exceder os caracteres m\u00e1ximos."],"Both":["Ambos"],"One-Time Label":["Etiqueta \u00danica"],"Label shown to users for the one-time payment option.":["R\u00f3tulo mostrado aos usu\u00e1rios para a op\u00e7\u00e3o de pagamento \u00fanico."],"Subscription Label":["Etiqueta de Assinatura"],"Label shown to users for the subscription option.":["R\u00f3tulo mostrado aos usu\u00e1rios para a op\u00e7\u00e3o de assinatura."],"Default Selection":["Sele\u00e7\u00e3o Padr\u00e3o"],"Which option is pre-selected when the form loads.":["Qual op\u00e7\u00e3o \u00e9 pr\u00e9-selecionada quando o formul\u00e1rio \u00e9 carregado."],"One-Time Amount Type":["Tipo de Quantia \u00danica"],"Set how the one-time payment amount is determined.":["Defina como o valor do pagamento \u00fanico \u00e9 determinado."],"One-Time Fixed Amount":["Valor Fixo \u00danico"],"Amount charged for a one-time payment.":["Valor cobrado por um pagamento \u00fanico."],"One-Time Amount Field":["Campo de Valor \u00danico"],"Pick a form field whose value determines the one-time payment amount.":["Escolha um campo de formul\u00e1rio cujo valor determina o montante do pagamento \u00fanico."],"One-Time Minimum Amount":["Montante M\u00ednimo \u00danico"],"Minimum amount users can enter for one-time payment (0 for no minimum).":["Valor m\u00ednimo que os usu\u00e1rios podem inserir para pagamento \u00fanico (0 para sem m\u00ednimo)."],"Subscription Amount Type":["Tipo de Valor da Assinatura"],"Set how the subscription amount is determined.":["Defina como o valor da assinatura \u00e9 determinado."],"Subscription Fixed Amount":["Montante Fixo da Assinatura"],"Recurring amount charged per billing interval.":["Valor recorrente cobrado por intervalo de faturamento."],"Subscription Amount Field":["Campo de Valor da Assinatura"],"Pick a form field whose value determines the subscription amount.":["Escolha um campo de formul\u00e1rio cujo valor determina o valor da assinatura."],"Subscription Minimum Amount":["Montante M\u00ednimo de Subscri\u00e7\u00e3o"],"Minimum amount users can enter for subscription (0 for no minimum).":["Valor m\u00ednimo que os usu\u00e1rios podem inserir para a assinatura (0 para sem m\u00ednimo)."],"Pick a field from your form like a number, dropdown, multichoice, or hidden whose value should decide the payment amount.":["Escolha um campo do seu formul\u00e1rio, como um n\u00famero, lista suspensa, m\u00faltipla escolha ou oculto, cujo valor deve determinar o valor do pagamento."]}}} \ No newline at end of file diff --git a/languages/sureforms-pt_PT.mo b/languages/sureforms-pt_PT.mo index 2d9996652..91f4b5e02 100644 Binary files a/languages/sureforms-pt_PT.mo and b/languages/sureforms-pt_PT.mo differ diff --git a/languages/sureforms-pt_PT.po b/languages/sureforms-pt_PT.po index 88ed2eef4..f43f78853 100644 --- a/languages/sureforms-pt_PT.po +++ b/languages/sureforms-pt_PT.po @@ -106,13 +106,13 @@ msgstr "Editar %1$s" #: inc/ai-form-builder/ai-auth.php:93 #: inc/ai-form-builder/ai-auth.php:167 #: inc/background-process.php:112 -#: inc/create-new-form.php:101 +#: inc/create-new-form.php:102 #: inc/duplicate-form.php:176 #: inc/export.php:118 #: inc/export.php:176 #: inc/forms-data.php:88 #: inc/global-settings/global-settings.php:86 -#: inc/global-settings/global-settings.php:403 +#: inc/global-settings/global-settings.php:404 #: inc/rest-api.php:177 msgid "Nonce verification failed." msgstr "A verificação do nonce falhou." @@ -388,7 +388,7 @@ msgid "Selected radio option" msgstr "Opção de rádio selecionada" #: inc/admin-ajax.php:341 -#: inc/create-new-form.php:63 +#: inc/create-new-form.php:64 #: assets/build/blocks.js:172 #: assets/build/formEditor.js:172 msgid "Submit" @@ -427,53 +427,53 @@ msgid "The message array was not supplied" msgstr "O array de mensagens não foi fornecido" #: inc/ai-form-builder/ai-form-builder.php:68 -#: inc/ai-form-builder/ai-form-builder.php:78 -#: inc/ai-form-builder/ai-helper.php:73 +#: inc/ai-form-builder/ai-form-builder.php:87 +#: inc/ai-form-builder/ai-helper.php:294 msgid "The SureForms AI Middleware encountered an error." msgstr "O middleware de IA SureForms encontrou um erro." -#: inc/ai-form-builder/ai-helper.php:95 +#: inc/ai-form-builder/ai-helper.php:91 msgid "Unable to get usage response." msgstr "Não foi possível obter a resposta de uso." -#: inc/ai-form-builder/ai-helper.php:148 +#: inc/ai-form-builder/ai-helper.php:145 msgid "The SureForms API server encountered an error." msgstr "O servidor da API SureForms encontrou um erro." -#: inc/ai-form-builder/ai-helper.php:174 -#: inc/ai-form-builder/ai-helper.php:206 +#: inc/ai-form-builder/ai-helper.php:167 +#: inc/ai-form-builder/ai-helper.php:199 msgid "An unknown error occurred." msgstr "Ocorreu um erro desconhecido." -#: inc/ai-form-builder/ai-helper.php:181 +#: inc/ai-form-builder/ai-helper.php:174 msgid "HTTP Request Failed" msgstr "Falha na Solicitação HTTP" -#: inc/ai-form-builder/ai-helper.php:185 +#: inc/ai-form-builder/ai-helper.php:178 msgid "License Verification Failed" msgstr "Falha na Verificação da Licença" -#: inc/ai-form-builder/ai-helper.php:189 +#: inc/ai-form-builder/ai-helper.php:182 msgid "User Verification Failed" msgstr "Falha na Verificação do Usuário" -#: inc/ai-form-builder/ai-helper.php:193 +#: inc/ai-form-builder/ai-helper.php:186 msgid "Referer Mismatch" msgstr "Incompatibilidade de Referência" -#: inc/ai-form-builder/ai-helper.php:197 +#: inc/ai-form-builder/ai-helper.php:190 msgid "Invalid Website URL" msgstr "URL do site inválido" -#: inc/ai-form-builder/ai-helper.php:198 +#: inc/ai-form-builder/ai-helper.php:191 msgid "AI Form Builder does not work on localhost. Please try on a live website." msgstr "O AI Form Builder não funciona no localhost. Por favor, tente em um site ao vivo." -#: inc/ai-form-builder/ai-helper.php:201 +#: inc/ai-form-builder/ai-helper.php:194 msgid "Domain Verification Failed" msgstr "Falha na Verificação do Domínio" -#: inc/ai-form-builder/ai-helper.php:205 +#: inc/ai-form-builder/ai-helper.php:198 msgid "Unknown Error" msgstr "Erro Desconhecido" @@ -481,22 +481,18 @@ msgstr "Erro Desconhecido" msgid "Submission id missing." msgstr "Falta o ID da submissão." -#: inc/create-new-form.php:113 +#: inc/create-new-form.php:114 msgid "Invalid JSON format." msgstr "Formato JSON inválido." -#: inc/create-new-form.php:125 +#: inc/create-new-form.php:126 msgid "Missing required properties in form info." msgstr "Faltam propriedades obrigatórias nas informações do formulário." -#: inc/create-new-form.php:161 +#: inc/create-new-form.php:187 msgid "SureForms Form created successfully." msgstr "SureForms Formulário criado com sucesso." -#: inc/create-new-form.php:168 -msgid "Error creating SureForms Form, " -msgstr "Erro ao criar o formulário SureForms," - #: inc/email/email-template.php:46 msgid "New form submission" msgstr "Nova submissão de formulário" @@ -558,7 +554,7 @@ msgstr "Número" msgid "Phone" msgstr "Telefone" -#: inc/fields/textarea-markup.php:95 +#: inc/fields/textarea-markup.php:111 msgid "Textarea" msgstr "Área de texto" @@ -601,8 +597,8 @@ msgstr "Nenhum formulário encontrado." #: inc/abilities/settings/get-global-settings.php:192 #: inc/global-settings/email-summary.php:571 -#: inc/global-settings/global-settings.php:250 -#: inc/global-settings/global-settings.php:456 +#: inc/global-settings/global-settings.php:251 +#: inc/global-settings/global-settings.php:457 #: assets/build/settings.js:172 msgid "Monday" msgstr "Segunda-feira" @@ -7009,7 +7005,7 @@ msgstr "Vista da Rua" msgid "Strikethrough" msgstr "Riscado" -#: inc/fields/payment-markup.php:412 +#: inc/fields/payment-markup.php:513 #: modules/gutenberg/icons/icons-v6-3.php:1812 #: assets/build/payments.js:172 msgid "Stripe" @@ -11593,6 +11589,7 @@ msgstr "Crie Seu Primeiro Formulário" msgid "Invalid nonce action or name." msgstr "Ação ou nome de nonce inválido." +#: inc/admin/editor-nudge.php:216 #: inc/helper.php:2029 #: inc/helper.php:2037 msgid "Invalid security token." @@ -11776,7 +11773,7 @@ msgstr "Explore o SureDash" msgid "Something went wrong. We have logged the error for further investigation" msgstr "Algo deu errado. Registramos o erro para investigação posterior" -#: inc/field-validation.php:273 +#: inc/field-validation.php:276 msgid "Field is not valid." msgstr "O campo não é válido." @@ -11934,82 +11931,82 @@ msgstr "Nenhum dado de formulário fornecido para importação." msgid "Invalid form data structure provided." msgstr "Estrutura de dados do formulário inválida fornecida." -#: inc/fields/payment-markup.php:249 +#: inc/fields/payment-markup.php:346 #: inc/payments/payment-helper.php:543 msgid "Subscription Plan" msgstr "Plano de Assinatura" #. translators: 1: Amount with currency, 2: Interval (day/week/month/quarter/year) -#: inc/fields/payment-markup.php:288 +#: inc/fields/payment-markup.php:672 #, php-format msgid "%1$s per %2$s (until cancelled)" msgstr "%1$s por %2$s (até ser cancelado)" #. translators: 1: Amount with currency, 2: Interval (day/week/month/quarter/year), 3: Number of billing cycles -#: inc/fields/payment-markup.php:297 +#: inc/fields/payment-markup.php:681 #, php-format msgid "%1$s per %2$s (%3$s payments)" msgstr "%1$s por %2$s (%3$s pagamentos)" #. translators: 1: Amount with currency, 2: Interval (day/week/month/quarter/year) -#: inc/fields/payment-markup.php:307 +#: inc/fields/payment-markup.php:691 #, php-format msgid "%1$s per %2$s" msgstr "%1$s por %2$s" #. translators: 1: Amount with currency placeholder, 2: Interval (day/week/month/quarter/year) -#: inc/fields/payment-markup.php:334 +#: inc/fields/payment-markup.php:714 #, php-format msgid "{amount} per %s (until cancelled)" msgstr "{amount} por %s (até ser cancelado)" #. translators: 1: Amount with currency placeholder, 2: Interval (day/week/month/quarter/year), 3: Number of billing cycles -#: inc/fields/payment-markup.php:337 +#: inc/fields/payment-markup.php:717 #, php-format msgid "{amount} per %1$s (%2$s payments)" msgstr "{amount} por %1$s (%2$s pagamentos)" #. translators: 1: Amount with currency placeholder, 2: Interval (day/week/month/quarter/year) -#: inc/fields/payment-markup.php:340 +#: inc/fields/payment-markup.php:720 #, php-format msgid "{amount} per %s" msgstr "{amount} por %s" #. translators: %s: Minimum amount with currency -#: inc/fields/payment-markup.php:353 +#: inc/fields/payment-markup.php:740 #, php-format msgid "Minimum amount: %s" msgstr "Montante mínimo: %s" -#: inc/fields/payment-markup.php:385 +#: inc/fields/payment-markup.php:486 msgid "Processing payment..." msgstr "Processando pagamento..." -#: inc/fields/payment-markup.php:579 +#: inc/fields/payment-markup.php:906 msgid "day" msgstr "dia" -#: inc/fields/payment-markup.php:580 +#: inc/fields/payment-markup.php:907 msgid "week" msgstr "semana" -#: inc/fields/payment-markup.php:581 +#: inc/fields/payment-markup.php:908 msgid "month" msgstr "mês" -#: inc/fields/payment-markup.php:582 +#: inc/fields/payment-markup.php:909 msgid "quarter" msgstr "trimestre" -#: inc/fields/payment-markup.php:583 +#: inc/fields/payment-markup.php:910 msgid "year" msgstr "ano" -#: inc/fields/payment-markup.php:608 +#: inc/fields/payment-markup.php:935 msgid "Test mode is enabled:" msgstr "O modo de teste está ativado:" -#: inc/fields/payment-markup.php:610 +#: inc/fields/payment-markup.php:937 msgid "Click here to enable live mode and accept payment" msgstr "Clique aqui para ativar o modo ao vivo e aceitar pagamento" @@ -12192,6 +12189,7 @@ msgstr "Formulário Desconhecido" msgid "N/A" msgstr "N/D" +#: inc/fields/payment-markup.php:247 #: inc/payments/admin/admin-handler.php:975 #: inc/payments/payment-history-shortcode.php:306 #: assets/build/blocks.js:172 @@ -12220,21 +12218,21 @@ msgstr "Desconhecido" #: inc/payments/admin/admin-handler.php:1468 #: inc/payments/admin/admin-handler.php:1472 #: inc/payments/admin/admin-handler.php:1476 -#: inc/payments/front-end.php:811 -#: inc/payments/front-end.php:1209 +#: inc/payments/front-end.php:854 +#: inc/payments/front-end.php:1253 msgid "Guest User" msgstr "Usuário Convidado" -#: inc/payments/front-end.php:91 +#: inc/payments/front-end.php:92 msgid "Invalid payment amount." msgstr "Valor de pagamento inválido." -#: inc/payments/front-end.php:107 +#: inc/payments/front-end.php:109 msgid "Valid customer email is required for payments." msgstr "É necessário um e-mail válido do cliente para pagamentos." -#: inc/payments/front-end.php:113 -#: inc/payments/front-end.php:320 +#: inc/payments/front-end.php:115 +#: inc/payments/front-end.php:340 #: inc/payments/stripe/admin-stripe-handler.php:877 #: inc/payments/stripe/payments-settings.php:349 #: inc/payments/stripe/payments-settings.php:474 @@ -12244,137 +12242,137 @@ msgstr "É necessário um e-mail válido do cliente para pagamentos." msgid "Stripe is not connected." msgstr "O Stripe não está conectado." -#: inc/payments/front-end.php:119 -#: inc/payments/front-end.php:326 -#: inc/payments/front-end.php:610 -#: inc/payments/front-end.php:1099 +#: inc/payments/front-end.php:121 +#: inc/payments/front-end.php:346 +#: inc/payments/front-end.php:634 +#: inc/payments/front-end.php:1142 msgid "Stripe secret key not found." msgstr "Chave secreta do Stripe não encontrada." #. translators: %s: formatted payment amount -#: inc/payments/front-end.php:201 +#: inc/payments/front-end.php:203 #, php-format msgid "The payment amount (%s) is below the minimum allowed. Stripe only processes amounts above 50¢." msgstr "O valor do pagamento (%s) está abaixo do mínimo permitido. O Stripe só processa valores acima de 50¢." #. translators: %s: Field name -#: inc/payments/front-end.php:268 +#: inc/payments/front-end.php:273 #, php-format msgid "Missing required field: %s" msgstr "Campo obrigatório ausente: %s" -#: inc/payments/front-end.php:287 +#: inc/payments/front-end.php:292 msgid "Valid customer email is required for subscriptions." msgstr "É necessário um e-mail válido do cliente para assinaturas." -#: inc/payments/front-end.php:292 +#: inc/payments/front-end.php:297 msgid "Customer name is required for subscriptions." msgstr "O nome do cliente é necessário para assinaturas." -#: inc/payments/front-end.php:308 +#: inc/payments/front-end.php:314 msgid "Amount must be greater than 0" msgstr "O valor deve ser maior que 0" -#: inc/payments/front-end.php:314 +#: inc/payments/front-end.php:322 msgid "Invalid billing interval" msgstr "Intervalo de cobrança inválido" -#: inc/payments/front-end.php:337 +#: inc/payments/front-end.php:357 msgid "Failed to create customer for subscription." msgstr "Falha ao criar cliente para a assinatura." -#: inc/payments/front-end.php:370 -#: inc/payments/front-end.php:386 +#: inc/payments/front-end.php:390 +#: inc/payments/front-end.php:406 msgid "Failed to create subscription through middleware." msgstr "Falha ao criar a assinatura através do middleware." -#: inc/payments/front-end.php:391 +#: inc/payments/front-end.php:411 msgid "Empty response from subscription creation." msgstr "Resposta vazia da criação de assinatura." -#: inc/payments/front-end.php:396 +#: inc/payments/front-end.php:416 msgid "Invalid JSON response from subscription creation." msgstr "Resposta JSON inválida da criação de assinatura." -#: inc/payments/front-end.php:400 -#: inc/payments/front-end.php:404 +#: inc/payments/front-end.php:420 +#: inc/payments/front-end.php:424 msgid "Invalid subscription data." msgstr "Dados de assinatura inválidos." -#: inc/payments/front-end.php:411 +#: inc/payments/front-end.php:431 msgid "Failed to create subscription." msgstr "Falha ao criar assinatura." #. translators: %s: Error message -#: inc/payments/front-end.php:441 +#: inc/payments/front-end.php:464 #, php-format msgid "Unexpected error: %s" msgstr "Erro inesperado: %s" -#: inc/payments/front-end.php:581 +#: inc/payments/front-end.php:604 #: inc/payments/stripe/admin-stripe-handler.php:103 #: inc/payments/stripe/admin-stripe-handler.php:184 #: inc/payments/stripe/admin-stripe-handler.php:489 msgid "Subscription ID not found." msgstr "ID de assinatura não encontrado." -#: inc/payments/front-end.php:599 +#: inc/payments/front-end.php:623 msgid "Customer ID not found for the payment." msgstr "ID do cliente não encontrado para o pagamento." -#: inc/payments/front-end.php:627 +#: inc/payments/front-end.php:651 msgid "Failed to retrieve setup intent." msgstr "Falha ao recuperar a intenção de configuração." -#: inc/payments/front-end.php:656 +#: inc/payments/front-end.php:699 msgid "Failed to update subscription." msgstr "Falha ao atualizar a assinatura." -#: inc/payments/front-end.php:664 +#: inc/payments/front-end.php:707 msgid "Latest invoice not found on subscription." msgstr "Fatura mais recente não encontrada na assinatura." -#: inc/payments/front-end.php:677 +#: inc/payments/front-end.php:720 msgid "Failed to retrieve invoice." msgstr "Falha ao recuperar a fatura." -#: inc/payments/front-end.php:699 +#: inc/payments/front-end.php:742 msgid "Payment intent not found on invoice." msgstr "Intenção de pagamento não encontrada na fatura." -#: inc/payments/front-end.php:714 +#: inc/payments/front-end.php:757 msgid "Failed to confirm payment." msgstr "Falha ao confirmar o pagamento." -#: inc/payments/front-end.php:730 +#: inc/payments/front-end.php:773 msgid "Failed to retrieve subscription." msgstr "Falha ao recuperar a assinatura." -#: inc/payments/front-end.php:745 +#: inc/payments/front-end.php:788 msgid "Subscription not found for the payment." msgstr "Assinatura não encontrada para o pagamento." #. translators: %d: User ID -#: inc/payments/front-end.php:809 -#: inc/payments/front-end.php:1209 +#: inc/payments/front-end.php:852 +#: inc/payments/front-end.php:1253 #, php-format msgid "User ID: %d" msgstr "ID do usuário: %d" #. translators: %s: Invoice status -#: inc/payments/front-end.php:817 +#: inc/payments/front-end.php:860 #, php-format msgid "Invoice Status: %s" msgstr "Status da Fatura: %s" #. translators: Title for subscription verification log -#: inc/payments/front-end.php:824 +#: inc/payments/front-end.php:867 msgid "Subscription Verification" msgstr "Verificação de Assinatura" #. translators: %s: Subscription ID #. translators: %s: Stripe subscription ID -#: inc/payments/front-end.php:828 +#: inc/payments/front-end.php:871 #: inc/payments/stripe/admin-stripe-handler.php:119 #: inc/payments/stripe/admin-stripe-handler.php:204 #: inc/payments/stripe/admin-stripe-handler.php:505 @@ -12390,8 +12388,8 @@ msgstr "ID de Assinatura: %s" #. 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:830 -#: inc/payments/front-end.php:1220 +#: inc/payments/front-end.php:873 +#: inc/payments/front-end.php:1264 #: inc/payments/stripe/admin-stripe-handler.php:124 #: inc/payments/stripe/admin-stripe-handler.php:209 #: inc/payments/stripe/admin-stripe-handler.php:510 @@ -12406,13 +12404,13 @@ msgid "Payment Gateway: %s" msgstr "Gateway de Pagamento: %s" #. translators: %s: Payment Intent ID -#: inc/payments/front-end.php:832 +#: inc/payments/front-end.php:875 #, php-format msgid "Payment Intent ID: %s" msgstr "ID da Intenção de Pagamento: %s" #. translators: %s: Charge ID -#: inc/payments/front-end.php:834 +#: inc/payments/front-end.php:877 #: inc/payments/stripe/stripe-webhook.php:1048 #, php-format msgid "Charge ID: %s" @@ -12420,7 +12418,7 @@ msgstr "ID de Cobrança: %s" #. translators: %s: Subscription Status #. translators: %s: subscription status -#: inc/payments/front-end.php:836 +#: inc/payments/front-end.php:879 #: inc/payments/stripe/admin-stripe-handler.php:129 #: inc/payments/stripe/admin-stripe-handler.php:214 #: inc/payments/stripe/admin-stripe-handler.php:515 @@ -12429,7 +12427,7 @@ msgid "Subscription Status: %s" msgstr "Status da Assinatura: %s" #. translators: %s: Customer ID -#: inc/payments/front-end.php:838 +#: inc/payments/front-end.php:881 #: inc/payments/stripe/stripe-webhook.php:1122 #, php-format msgid "Customer ID: %s" @@ -12437,8 +12435,8 @@ msgstr "ID do Cliente: %s" #. translators: 1: Amount, 2: Currency #. translators: %1$s: amount, %2$s: currency. -#: inc/payments/front-end.php:840 -#: inc/payments/front-end.php:1222 +#: inc/payments/front-end.php:883 +#: inc/payments/front-end.php:1266 #: inc/payments/stripe/stripe-webhook.php:1053 #: inc/payments/stripe/stripe-webhook.php:1114 #, php-format @@ -12447,34 +12445,34 @@ msgstr "Quantia: %1$s %2$s" #. translators: %s: Payment mode (e.g. Live or Test) #. translators: %s: payment mode -#: inc/payments/front-end.php:843 -#: inc/payments/front-end.php:1227 +#: inc/payments/front-end.php:886 +#: inc/payments/front-end.php:1271 #, php-format msgid "Mode: %s" msgstr "Modo: %s" -#: inc/payments/front-end.php:877 +#: inc/payments/front-end.php:920 msgid "Failed to verify subscription." msgstr "Falha ao verificar a assinatura." -#: inc/payments/front-end.php:1131 -#: inc/payments/front-end.php:1149 -#: inc/payments/front-end.php:1157 -#: inc/payments/front-end.php:1164 +#: inc/payments/front-end.php:1175 +#: inc/payments/front-end.php:1193 +#: inc/payments/front-end.php:1201 +#: inc/payments/front-end.php:1208 msgid "Failed to retrieve payment intent." msgstr "Falha ao recuperar a intenção de pagamento." -#: inc/payments/front-end.php:1172 +#: inc/payments/front-end.php:1216 msgid "Payment was not confirmed successfully." msgstr "O pagamento não foi confirmado com sucesso." -#: inc/payments/front-end.php:1214 +#: inc/payments/front-end.php:1258 msgid "Payment Verification" msgstr "Verificação de Pagamento" #. translators: %s: Stripe transaction ID #. translators: %s: Charge ID -#: inc/payments/front-end.php:1218 +#: inc/payments/front-end.php:1262 #: inc/payments/stripe/stripe-webhook.php:1110 #, php-format msgid "Transaction ID: %s" @@ -12482,18 +12480,18 @@ msgstr "ID da Transação: %s" #. translators: %s: payment status #. translators: %s: Status -#: inc/payments/front-end.php:1224 +#: inc/payments/front-end.php:1268 #: inc/payments/stripe/stripe-webhook.php:576 #: inc/payments/stripe/stripe-webhook.php:1116 #, php-format msgid "Status: %s" msgstr "Status: %s" -#: inc/payments/front-end.php:1330 +#: inc/payments/front-end.php:1374 msgid "Failed to create Stripe customer." msgstr "Falha ao criar cliente Stripe." -#: inc/payments/front-end.php:1394 +#: inc/payments/front-end.php:1438 msgid "Failed to create Stripe guest customer." msgstr "Falha ao criar cliente convidado do Stripe." @@ -12856,6 +12854,7 @@ msgstr "Erro desconhecido" msgid "Missing payment ID." msgstr "ID de pagamento ausente." +#: inc/admin/editor-nudge.php:209 #: inc/payments/stripe/admin-stripe-handler.php:84 #: inc/payments/stripe/admin-stripe-handler.php:470 msgid "You are not allowed to perform this action." @@ -13535,10 +13534,6 @@ msgstr "Escolher Campo de Quantidade" msgid "Select a field…" msgstr "Selecione um campo…" -#: assets/build/blocks.js:172 -msgid "Pick a field from your form like a number, dropdown, or multichoice whose value should decide the payment amount." -msgstr "Escolha um campo do seu formulário, como um número, menu suspenso ou múltipla escolha, cujo valor deve determinar o valor do pagamento." - #: assets/build/blocks.js:172 msgid "Minimum Amount" msgstr "Quantidade Mínima" @@ -14118,6 +14113,7 @@ msgstr "Use a IA para gerar formulários instantaneamente a partir de um prompt msgid "Build engaging conversational, calculation, and multi-step forms." msgstr "Crie formulários envolventes de conversação, cálculo e de múltiplas etapas." +#: inc/admin/editor-nudge.php:192 #: assets/build/forms.js:172 msgid "Create Form" msgstr "Criar Formulário" @@ -14976,76 +14972,78 @@ msgstr "O post especificado não é um formulário SureForms." msgid "Failed to create duplicate form." msgstr "Falha ao criar formulário duplicado." -#: inc/payments/front-end.php:97 -#: inc/payments/front-end.php:298 -#: inc/payments/payment-helper.php:594 +#: inc/payments/front-end.php:98 +#: inc/payments/front-end.php:303 +#: inc/payments/payment-helper.php:595 msgid "Invalid form configuration." msgstr "Configuração de formulário inválida." -#: inc/payments/payment-helper.php:602 +#: inc/payments/payment-helper.php:603 msgid "Payment configuration not found for this form." msgstr "Configuração de pagamento não encontrada para este formulário." #. translators: 1: expected currency, 2: received currency -#: inc/payments/payment-helper.php:613 +#: inc/payments/payment-helper.php:614 #, php-format msgid "Currency mismatch: expected %1$s, received %2$s." msgstr "Incompatibilidade de moeda: esperado %1$s, recebido %2$s." #. translators: 1: expected amount with currency -#: inc/payments/payment-helper.php:630 +#: inc/payments/payment-helper.php:649 #, php-format msgid "Payment amount must be exactly %1$s." msgstr "O valor do pagamento deve ser exatamente %1$s." #. translators: 1: minimum amount with currency -#: inc/payments/payment-helper.php:641 +#: inc/payments/payment-helper.php:660 #, php-format msgid "Payment amount must be at least %1$s." msgstr "O valor do pagamento deve ser pelo menos %1$s." -#: inc/payments/payment-helper.php:717 +#: inc/payments/payment-helper.php:737 msgid "Invalid payment verification parameters." msgstr "Parâmetros de verificação de pagamento inválidos." -#: inc/payments/payment-helper.php:728 +#: inc/payments/payment-helper.php:748 msgid "Payment verification failed. Invalid payment intent." msgstr "Falha na verificação do pagamento. Intenção de pagamento inválida." -#: inc/payments/payment-helper.php:814 -#: inc/payments/payment-helper.php:952 +#: inc/payments/payment-helper.php:903 +#: inc/payments/payment-helper.php:1043 msgid "Variable amount field configuration not found." msgstr "Configuração do campo de quantidade variável não encontrada." -#: inc/payments/payment-helper.php:835 +#: inc/payments/payment-helper.php:924 msgid "No payment options are configured for this field." msgstr "Nenhuma opção de pagamento está configurada para este campo." #. translators: %s: currency code -#: inc/payments/payment-helper.php:861 +#: inc/payments/payment-helper.php:950 msgid "Invalid payment amount. Please select a valid amount from the available options." msgstr "Quantia de pagamento inválida. Por favor, selecione uma quantia válida entre as opções disponíveis." #. translators: %1$s: expected amount, %2$s: payment amount -#: inc/payments/payment-helper.php:896 +#: inc/payments/payment-helper.php:986 msgid "Payment configuration not found." msgstr "Configuração de pagamento não encontrada." #. translators: %1$s: expected amount, %2$s: payment amount -#: inc/payments/payment-helper.php:912 -#: inc/payments/payment-helper.php:964 -#: inc/payments/payment-helper.php:1000 +#: inc/payments/payment-helper.php:1003 +#: inc/payments/payment-helper.php:1055 +#: inc/payments/payment-helper.php:1091 +#: inc/payments/payment-helper.php:1111 #, php-format msgid "Payment amount mismatch. Expected %1$s, received %2$s." msgstr "Diferença no valor do pagamento. Esperado %1$s, recebido %2$s." -#: inc/payments/payment-helper.php:941 -#: inc/payments/payment-helper.php:991 +#: 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." msgstr "É necessário o valor do campo de quantidade variável." #. translators: %1$s: minimum amount, %2$s: payment amount -#: inc/payments/payment-helper.php:1012 +#: inc/payments/payment-helper.php:1125 #, php-format msgid "Payment amount below minimum. Minimum: %1$s, received %2$s." msgstr "Valor do pagamento abaixo do mínimo. Mínimo: %1$s, recebido %2$s." @@ -15107,7 +15105,7 @@ msgstr "Ocorreu um erro ao duplicar o formulário." msgid "This will create a copy of \"%s\" with all its settings." msgstr "Isso criará uma cópia de \"%s\" com todas as suas configurações." -#: inc/fields/payment-markup.php:413 +#: inc/fields/payment-markup.php:514 msgid "Pay with credit or debit card" msgstr "Pague com cartão de crédito ou débito" @@ -15115,8 +15113,8 @@ msgstr "Pague com cartão de crédito ou débito" msgid "This form is not yet available. Please check back after the scheduled start time." msgstr "Este formulário ainda não está disponível. Por favor, verifique novamente após o horário de início programado." -#: inc/form-restriction.php:165 -#: inc/form-restriction.php:166 +#: inc/form-restriction.php:187 +#: inc/form-restriction.php:188 #: assets/build/formEditor.js:172 msgid "This form is no longer accepting submissions. The submission period has ended." msgstr "Este formulário não está mais aceitando envios. O período de envio terminou." @@ -15131,7 +15129,7 @@ msgstr "Gateway de pagamento não encontrado." msgid "Refund processing is not supported for %s gateway." msgstr "O processamento de reembolsos não é suportado para o gateway %s." -#: inc/payments/payment-helper.php:974 +#: inc/payments/payment-helper.php:1065 msgid "Number field configuration not found." msgstr "Configuração do campo numérico não encontrada." @@ -15508,11 +15506,11 @@ msgstr "O título do formulário é obrigatório." msgid "At least one form field is required." msgstr "Pelo menos um campo de formulário é necessário." -#: inc/abilities/forms/create-form.php:322 +#: inc/abilities/forms/create-form.php:326 msgid "Failed to generate form fields from the provided data." msgstr "Falha ao gerar campos do formulário a partir dos dados fornecidos." -#: inc/abilities/forms/create-form.php:372 +#: inc/abilities/forms/create-form.php:376 msgid "Failed to create the form." msgstr "Falha ao criar o formulário." @@ -15688,23 +15686,23 @@ msgstr "Sessão de autenticação expirada. Por favor, tente novamente." msgid "Invalid access key format." msgstr "Formato de chave de acesso inválido." -#: inc/ai-form-builder/ai-helper.php:182 +#: inc/ai-form-builder/ai-helper.php:175 msgid "Unable to connect to SureForms API. Please check your connection." msgstr "Não foi possível conectar à API do SureForms. Por favor, verifique sua conexão." -#: inc/ai-form-builder/ai-helper.php:186 +#: inc/ai-form-builder/ai-helper.php:179 msgid "Unable to verify license. Please check your license key." msgstr "Não foi possível verificar a licença. Por favor, verifique sua chave de licença." -#: inc/ai-form-builder/ai-helper.php:190 +#: inc/ai-form-builder/ai-helper.php:183 msgid "An error occurred while trying to verify your email. Please check your email you have used to log in or sign up on billing.sureforms.com." msgstr "Ocorreu um erro ao tentar verificar seu e-mail. Por favor, verifique o e-mail que você usou para fazer login ou se inscrever em billing.sureforms.com." -#: inc/ai-form-builder/ai-helper.php:194 +#: inc/ai-form-builder/ai-helper.php:187 msgid "Unable to verify referer. Please check your referer." msgstr "Não foi possível verificar o referenciador. Por favor, verifique seu referenciador." -#: inc/ai-form-builder/ai-helper.php:202 +#: inc/ai-form-builder/ai-helper.php:195 msgid "Domain Verification Failed on current site. Please try again on another website." msgstr "Falha na Verificação de Domínio no site atual. Por favor, tente novamente em outro site." @@ -15730,8 +15728,8 @@ msgstr "Eu consinto que este site armazene minhas informações para que possam msgid "Text field" msgstr "Campo de texto" -#: inc/form-restriction.php:160 -#: inc/form-restriction.php:161 +#: inc/form-restriction.php:182 +#: inc/form-restriction.php:183 #: inc/post-types.php:1203 #: inc/post-types.php:1243 msgid "This form is not yet available. Check back after the scheduled start time." @@ -15741,8 +15739,8 @@ msgstr "Este formulário ainda não está disponível. Verifique novamente após #: inc/form-submit.php:400 #: inc/form-submit.php:445 #: inc/form-submit.php:968 -#: inc/payments/front-end.php:77 -#: inc/payments/front-end.php:258 +#: 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 @@ -16097,32 +16095,32 @@ msgid "Enter a valid email address." msgstr "Insira um endereço de e-mail válido." #. translators: %s represents the minimum acceptable value -#: inc/translatable.php:94 +#: inc/translatable.php:97 #, php-format msgid "Minimum value is %s." msgstr "O valor mínimo é %s." #. translators: %s represents the maximum acceptable value -#: inc/translatable.php:97 +#: inc/translatable.php:100 #, php-format msgid "Maximum value is %s." msgstr "O valor máximo é %s." #. translators: %s represents the minimum number of options to select -#: inc/translatable.php:100 -#: inc/translatable.php:106 +#: inc/translatable.php:103 +#: inc/translatable.php:109 #, php-format msgid "Select at least %s options." msgstr "Selecione pelo menos %s opções." #. translators: %s represents the maximum number of options that can be selected -#: inc/translatable.php:103 -#: inc/translatable.php:109 +#: inc/translatable.php:106 +#: inc/translatable.php:112 #, php-format msgid "You can select up to %s options." msgstr "Você pode selecionar até %s opções." -#: inc/translatable.php:120 +#: inc/translatable.php:123 msgid "This form is now closed as we have reached the maximum number of entries." msgstr "Este formulário está agora fechado, pois atingimos o número máximo de inscrições." @@ -16649,35 +16647,35 @@ msgstr "Recuperar as configurações globais do SureForms. Opcionalmente, filtre msgid "Setting categories to retrieve. Omit for all categories." msgstr "Definindo categorias para recuperar. Omitir para todas as categorias." -#: inc/abilities/settings/update-global-settings.php:105 +#: inc/abilities/settings/update-global-settings.php:106 msgid "Update Global Settings" msgstr "Atualizar Configurações Globais" -#: inc/abilities/settings/update-global-settings.php:106 +#: inc/abilities/settings/update-global-settings.php:107 msgid "Update SureForms global settings for a specific category: general, validation-messages, email-summary, or security." msgstr "Atualize as configurações globais do SureForms para uma categoria específica: geral, mensagens de validação, resumo de e-mail ou segurança." -#: inc/abilities/settings/update-global-settings.php:139 +#: inc/abilities/settings/update-global-settings.php:140 msgid "The settings category to update." msgstr "A categoria de configurações a ser atualizada." -#: inc/abilities/settings/update-global-settings.php:144 +#: inc/abilities/settings/update-global-settings.php:145 msgid "Key-value pairs of settings to update." msgstr "Pares chave-valor de configurações para atualizar." -#: inc/abilities/settings/update-global-settings.php:180 +#: inc/abilities/settings/update-global-settings.php:181 msgid "Settings category is required." msgstr "A categoria de configurações é obrigatória." -#: inc/abilities/settings/update-global-settings.php:188 +#: inc/abilities/settings/update-global-settings.php:189 msgid "Settings data is required." msgstr "É necessário fornecer os dados de configurações." -#: inc/abilities/settings/update-global-settings.php:199 +#: inc/abilities/settings/update-global-settings.php:200 msgid "No valid settings keys provided for this category." msgstr "Nenhuma chave de configuração válida fornecida para esta categoria." -#: inc/abilities/settings/update-global-settings.php:225 +#: inc/abilities/settings/update-global-settings.php:226 msgid "Invalid settings category." msgstr "Categoria de configurações inválida." @@ -17578,6 +17576,212 @@ msgstr "Złoty polonês" msgid "Dynamic Default Value" msgstr "Valor Padrão Dinâmico" +#: inc/admin/editor-nudge.php:191 +msgid "Hey! It looks like you're creating a form. Build a ready-to-use form in under 30 seconds with SureForms AI, with no extra setup required." +msgstr "Ei! Parece que você está criando um formulário. Construa um formulário pronto para uso em menos de 30 segundos com o SureForms AI, sem necessidade de configuração extra." + +#: inc/admin/editor-nudge.php:228 +#: inc/admin/editor-nudge.php:237 +msgid "Invalid post." +msgstr "Publicação inválida." + +#: inc/admin/editor-nudge.php:246 +msgid "You cannot edit this post." +msgstr "Você não pode editar esta postagem." + +#: inc/ai-form-builder/ai-form-builder.php:96 +msgid "The AI did not return a form. Please refine your prompt and try again." +msgstr "A IA não retornou um formulário. Por favor, refine seu prompt e tente novamente." + +#: inc/ai-form-builder/ai-form-builder.php:104 +msgid "The AI response is missing a form title. Please try again." +msgstr "A resposta da IA está faltando um título de formulário. Por favor, tente novamente." + +#: inc/ai-form-builder/ai-form-builder.php:115 +#: inc/ai-form-builder/field-mapping.php:69 +msgid "The AI was unable to generate form fields. Please try again." +msgstr "A IA não conseguiu gerar os campos do formulário. Por favor, tente novamente." + +#: inc/ai-form-builder/field-mapping.php:41 +msgid "The AI form data is missing. Please try again." +msgstr "Os dados do formulário de IA estão faltando. Por favor, tente novamente." + +#: inc/ai-form-builder/field-mapping.php:51 +msgid "The AI form data is not in the expected format." +msgstr "Os dados do formulário de IA não estão no formato esperado." + +#: inc/ai-form-builder/field-mapping.php:60 +msgid "The AI response did not include a form. Please try again." +msgstr "A resposta da IA não incluiu um formulário. Por favor, tente novamente." + +#: inc/ai-form-builder/field-mapping.php:90 +msgid "The AI returned a malformed form field. Please try again." +msgstr "A IA retornou um campo de formulário malformado. Por favor, tente novamente." + +#: inc/create-new-form.php:160 +#: inc/create-new-form.php:173 +msgid "Error creating SureForms Form." +msgstr "Erro ao criar o formulário SureForms." + +#. translators: %s represents the minimum number of characters required +#: inc/field-validation.php:289 +#: inc/translatable.php:94 +#, php-format +msgid "Please enter at least %s characters." +msgstr "Por favor, insira pelo menos %s caracteres." + +#: inc/fields/payment-markup.php:246 +msgid "One-Time Payment" +msgstr "Pagamento Único" + +#: inc/fields/payment-markup.php:562 +msgid "Choose payment type" +msgstr "Escolha o tipo de pagamento" + +#: inc/payments/front-end.php:333 +msgid "Billing interval does not match the form configuration." +msgstr "O intervalo de faturamento não corresponde à configuração do formulário." + +#: inc/payments/payment-helper.php:627 +msgid "Payment type does not match the form configuration." +msgstr "O tipo de pagamento não corresponde à configuração do formulário." + +#: inc/payments/payment-helper.php:760 +msgid "Payment verification failed. Payment type mismatch." +msgstr "Falha na verificação do pagamento. Tipo de pagamento incompatível." + +#: assets/build/blocks.js:172 +msgid "Minimum Characters" +msgstr "Mínimo de Caracteres" + +#: assets/build/blocks.js:172 +msgid "Minimum characters cannot exceed Maximum characters." +msgstr "Os caracteres mínimos não podem exceder os caracteres máximos." + +#: assets/build/blocks.js:172 +msgid "Both" +msgstr "Ambos" + +#: assets/build/blocks.js:172 +msgid "One-Time Label" +msgstr "Etiqueta Única" + +#: assets/build/blocks.js:172 +msgid "Label shown to users for the one-time payment option." +msgstr "Rótulo mostrado aos usuários para a opção de pagamento único." + +#: assets/build/blocks.js:172 +msgid "Subscription Label" +msgstr "Etiqueta de Assinatura" + +#: assets/build/blocks.js:172 +msgid "Label shown to users for the subscription option." +msgstr "Rótulo mostrado aos usuários para a opção de assinatura." + +#: assets/build/blocks.js:172 +msgid "Default Selection" +msgstr "Seleção Padrão" + +#: assets/build/blocks.js:172 +msgid "Which option is pre-selected when the form loads." +msgstr "Qual opção é pré-selecionada quando o formulário é carregado." + +#: assets/build/blocks.js:172 +msgid "One-Time Amount Type" +msgstr "Tipo de Quantia Única" + +#: assets/build/blocks.js:172 +msgid "Set how the one-time payment amount is determined." +msgstr "Defina como o valor do pagamento único é determinado." + +#: assets/build/blocks.js:172 +msgid "One-Time Fixed Amount" +msgstr "Valor Fixo Único" + +#: assets/build/blocks.js:172 +msgid "Amount charged for a one-time payment." +msgstr "Valor cobrado por um pagamento único." + +#: assets/build/blocks.js:172 +msgid "One-Time Amount Field" +msgstr "Campo de Valor Único" + +#: assets/build/blocks.js:172 +msgid "Pick a form field whose value determines the one-time payment amount." +msgstr "Escolha um campo de formulário cujo valor determina o montante do pagamento único." + +#: assets/build/blocks.js:172 +msgid "One-Time Minimum Amount" +msgstr "Montante Mínimo Único" + +#: assets/build/blocks.js:172 +msgid "Minimum amount users can enter for one-time payment (0 for no minimum)." +msgstr "Valor mínimo que os usuários podem inserir para pagamento único (0 para sem mínimo)." + +#: assets/build/blocks.js:172 +msgid "Subscription Amount Type" +msgstr "Tipo de Valor da Assinatura" + +#: assets/build/blocks.js:172 +msgid "Set how the subscription amount is determined." +msgstr "Defina como o valor da assinatura é determinado." + +#: assets/build/blocks.js:172 +msgid "Subscription Fixed Amount" +msgstr "Montante Fixo da Assinatura" + +#: assets/build/blocks.js:172 +msgid "Recurring amount charged per billing interval." +msgstr "Valor recorrente cobrado por intervalo de faturamento." + +#: assets/build/blocks.js:172 +msgid "Subscription Amount Field" +msgstr "Campo de Valor da Assinatura" + +#: assets/build/blocks.js:172 +msgid "Pick a form field whose value determines the subscription amount." +msgstr "Escolha um campo de formulário cujo valor determina o valor da assinatura." + +#: assets/build/blocks.js:172 +msgid "Subscription Minimum Amount" +msgstr "Montante Mínimo de Subscrição" + +#: assets/build/blocks.js:172 +msgid "Minimum amount users can enter for subscription (0 for no minimum)." +msgstr "Valor mínimo que os usuários podem inserir para a assinatura (0 para sem mínimo)." + +#: 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 "Escolha um campo do seu formulário, como um número, lista suspensa, múltipla escolha ou oculto, cujo valor deve determinar o valor do pagamento." + +#: assets/build/templatePicker.js:172 +msgid "You do not have permission to create forms." +msgstr "Você não tem permissão para criar formulários." + +#: assets/build/templatePicker.js:172 +msgid "The form could not be saved. Please try again." +msgstr "O formulário não pôde ser salvo. Por favor, tente novamente." + +#: assets/build/templatePicker.js:172 +msgid "Unable to reach the SureForms AI service. Please check your connection and try again." +msgstr "Não foi possível acessar o serviço SureForms AI. Por favor, verifique sua conexão e tente novamente." + +#: assets/build/templatePicker.js:172 +msgid "The AI service did not return a response. Please try again." +msgstr "O serviço de IA não retornou uma resposta. Por favor, tente novamente." + +#: assets/build/templatePicker.js:172 +msgid "Form generation failed. Please try again." +msgstr "A geração do formulário falhou. Por favor, tente novamente." + +#: assets/build/templatePicker.js:172 +msgid "The AI response was empty. Please refine your prompt and try again." +msgstr "A resposta da IA estava vazia. Por favor, refine seu prompt e tente novamente." + +#: assets/build/templatePicker.js:172 +msgid "Unable to build form fields from the AI response." +msgstr "Não foi possível criar campos de formulário a partir da resposta da IA." + #: inc/post-types.php:205 msgctxt "post type general name" msgid "Forms" diff --git a/languages/sureforms.pot b/languages/sureforms.pot index 30939bd29..7aa3b1b9a 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.8.1\n" +"Project-Id-Version: SureForms 2.8.2\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-04-24T10:40:54+00:00\n" +"POT-Creation-Date: 2026-05-04T11:21:29+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" @@ -688,11 +688,11 @@ msgstr "" msgid "At least one form field is required." msgstr "" -#: inc/abilities/forms/create-form.php:322 +#: inc/abilities/forms/create-form.php:326 msgid "Failed to generate form fields from the provided data." msgstr "" -#: inc/abilities/forms/create-form.php:372 +#: inc/abilities/forms/create-form.php:376 msgid "Failed to create the form." msgstr "" @@ -878,41 +878,41 @@ msgstr "" #: inc/abilities/settings/get-global-settings.php:192 #: inc/global-settings/email-summary.php:571 -#: inc/global-settings/global-settings.php:250 -#: inc/global-settings/global-settings.php:456 +#: inc/global-settings/global-settings.php:251 +#: inc/global-settings/global-settings.php:457 #: assets/build/settings.js:172 msgid "Monday" msgstr "" -#: inc/abilities/settings/update-global-settings.php:105 +#: inc/abilities/settings/update-global-settings.php:106 msgid "Update Global Settings" msgstr "" -#: inc/abilities/settings/update-global-settings.php:106 +#: inc/abilities/settings/update-global-settings.php:107 msgid "Update SureForms global settings for a specific category: general, validation-messages, email-summary, or security." msgstr "" -#: inc/abilities/settings/update-global-settings.php:139 +#: inc/abilities/settings/update-global-settings.php:140 msgid "The settings category to update." msgstr "" -#: inc/abilities/settings/update-global-settings.php:144 +#: inc/abilities/settings/update-global-settings.php:145 msgid "Key-value pairs of settings to update." msgstr "" -#: inc/abilities/settings/update-global-settings.php:180 +#: inc/abilities/settings/update-global-settings.php:181 msgid "Settings category is required." msgstr "" -#: inc/abilities/settings/update-global-settings.php:188 +#: inc/abilities/settings/update-global-settings.php:189 msgid "Settings data is required." msgstr "" -#: inc/abilities/settings/update-global-settings.php:199 +#: inc/abilities/settings/update-global-settings.php:200 msgid "No valid settings keys provided for this category." msgstr "" -#: inc/abilities/settings/update-global-settings.php:225 +#: inc/abilities/settings/update-global-settings.php:226 msgid "Invalid settings category." msgstr "" @@ -986,7 +986,7 @@ msgid "Selected radio option" msgstr "" #: inc/admin-ajax.php:341 -#: inc/create-new-form.php:63 +#: inc/create-new-form.php:64 #: assets/build/blocks.js:172 #: assets/build/formEditor.js:172 msgid "Submit" @@ -1017,17 +1017,47 @@ msgstr "" msgid "File not found." msgstr "" +#: inc/admin/editor-nudge.php:191 +msgid "Hey! It looks like you're creating a form. Build a ready-to-use form in under 30 seconds with SureForms AI, with no extra setup required." +msgstr "" + +#: inc/admin/editor-nudge.php:192 +#: assets/build/forms.js:172 +msgid "Create Form" +msgstr "" + +#: inc/admin/editor-nudge.php:209 +#: inc/payments/stripe/admin-stripe-handler.php:84 +#: inc/payments/stripe/admin-stripe-handler.php:470 +msgid "You are not allowed to perform this action." +msgstr "" + +#: inc/admin/editor-nudge.php:216 +#: inc/helper.php:2029 +#: inc/helper.php:2037 +msgid "Invalid security token." +msgstr "" + +#: inc/admin/editor-nudge.php:228 +#: inc/admin/editor-nudge.php:237 +msgid "Invalid post." +msgstr "" + +#: inc/admin/editor-nudge.php:246 +msgid "You cannot edit this post." +msgstr "" + #: inc/ai-form-builder/ai-auth.php:45 #: inc/ai-form-builder/ai-auth.php:93 #: inc/ai-form-builder/ai-auth.php:167 #: inc/background-process.php:112 -#: inc/create-new-form.php:101 +#: inc/create-new-form.php:102 #: inc/duplicate-form.php:176 #: inc/export.php:118 #: inc/export.php:176 #: inc/forms-data.php:88 #: inc/global-settings/global-settings.php:86 -#: inc/global-settings/global-settings.php:403 +#: inc/global-settings/global-settings.php:404 #: inc/rest-api.php:177 msgid "Nonce verification failed." msgstr "" @@ -1069,76 +1099,105 @@ msgid "The message array was not supplied" msgstr "" #: inc/ai-form-builder/ai-form-builder.php:68 -#: inc/ai-form-builder/ai-form-builder.php:78 -#: inc/ai-form-builder/ai-helper.php:73 +#: inc/ai-form-builder/ai-form-builder.php:87 +#: inc/ai-form-builder/ai-helper.php:294 msgid "The SureForms AI Middleware encountered an error." msgstr "" -#: inc/ai-form-builder/ai-helper.php:95 +#: inc/ai-form-builder/ai-form-builder.php:96 +msgid "The AI did not return a form. Please refine your prompt and try again." +msgstr "" + +#: inc/ai-form-builder/ai-form-builder.php:104 +msgid "The AI response is missing a form title. Please try again." +msgstr "" + +#: inc/ai-form-builder/ai-form-builder.php:115 +#: inc/ai-form-builder/field-mapping.php:69 +msgid "The AI was unable to generate form fields. Please try again." +msgstr "" + +#: inc/ai-form-builder/ai-helper.php:91 msgid "Unable to get usage response." msgstr "" -#: inc/ai-form-builder/ai-helper.php:148 +#: inc/ai-form-builder/ai-helper.php:145 msgid "The SureForms API server encountered an error." msgstr "" -#: inc/ai-form-builder/ai-helper.php:174 -#: inc/ai-form-builder/ai-helper.php:206 +#: inc/ai-form-builder/ai-helper.php:167 +#: inc/ai-form-builder/ai-helper.php:199 msgid "An unknown error occurred." msgstr "" -#: inc/ai-form-builder/ai-helper.php:181 +#: inc/ai-form-builder/ai-helper.php:174 msgid "HTTP Request Failed" msgstr "" -#: inc/ai-form-builder/ai-helper.php:182 +#: inc/ai-form-builder/ai-helper.php:175 msgid "Unable to connect to SureForms API. Please check your connection." msgstr "" -#: inc/ai-form-builder/ai-helper.php:185 +#: inc/ai-form-builder/ai-helper.php:178 msgid "License Verification Failed" msgstr "" -#: inc/ai-form-builder/ai-helper.php:186 +#: inc/ai-form-builder/ai-helper.php:179 msgid "Unable to verify license. Please check your license key." msgstr "" -#: inc/ai-form-builder/ai-helper.php:189 +#: inc/ai-form-builder/ai-helper.php:182 msgid "User Verification Failed" msgstr "" -#: inc/ai-form-builder/ai-helper.php:190 +#: inc/ai-form-builder/ai-helper.php:183 msgid "An error occurred while trying to verify your email. Please check your email you have used to log in or sign up on billing.sureforms.com." msgstr "" -#: inc/ai-form-builder/ai-helper.php:193 +#: inc/ai-form-builder/ai-helper.php:186 msgid "Referer Mismatch" msgstr "" -#: inc/ai-form-builder/ai-helper.php:194 +#: inc/ai-form-builder/ai-helper.php:187 msgid "Unable to verify referer. Please check your referer." msgstr "" -#: inc/ai-form-builder/ai-helper.php:197 +#: inc/ai-form-builder/ai-helper.php:190 msgid "Invalid Website URL" msgstr "" -#: inc/ai-form-builder/ai-helper.php:198 +#: inc/ai-form-builder/ai-helper.php:191 msgid "AI Form Builder does not work on localhost. Please try on a live website." msgstr "" -#: inc/ai-form-builder/ai-helper.php:201 +#: inc/ai-form-builder/ai-helper.php:194 msgid "Domain Verification Failed" msgstr "" -#: inc/ai-form-builder/ai-helper.php:202 +#: inc/ai-form-builder/ai-helper.php:195 msgid "Domain Verification Failed on current site. Please try again on another website." msgstr "" -#: inc/ai-form-builder/ai-helper.php:205 +#: inc/ai-form-builder/ai-helper.php:198 msgid "Unknown Error" msgstr "" +#: inc/ai-form-builder/field-mapping.php:41 +msgid "The AI form data is missing. Please try again." +msgstr "" + +#: inc/ai-form-builder/field-mapping.php:51 +msgid "The AI form data is not in the expected format." +msgstr "" + +#: inc/ai-form-builder/field-mapping.php:60 +msgid "The AI response did not include a form. Please try again." +msgstr "" + +#: inc/ai-form-builder/field-mapping.php:90 +msgid "The AI returned a malformed form field. Please try again." +msgstr "" + #: inc/background-process.php:103 msgid "After submission process has already been triggered for this submission." msgstr "" @@ -1159,20 +1218,21 @@ msgstr "" msgid "This form has been deleted or is unavailable." msgstr "" -#: inc/create-new-form.php:113 +#: inc/create-new-form.php:114 msgid "Invalid JSON format." msgstr "" -#: inc/create-new-form.php:125 +#: inc/create-new-form.php:126 msgid "Missing required properties in form info." msgstr "" -#: inc/create-new-form.php:161 -msgid "SureForms Form created successfully." +#: inc/create-new-form.php:160 +#: inc/create-new-form.php:173 +msgid "Error creating SureForms Form." msgstr "" -#: inc/create-new-form.php:168 -msgid "Error creating SureForms Form, " +#: inc/create-new-form.php:187 +msgid "SureForms Form created successfully." msgstr "" #: inc/duplicate-form.php:39 @@ -1277,10 +1337,17 @@ msgstr "" msgid "Unable to import form." msgstr "" -#: inc/field-validation.php:273 +#: inc/field-validation.php:276 msgid "Field is not valid." msgstr "" +#. translators: %s represents the minimum number of characters required +#: inc/field-validation.php:289 +#: inc/translatable.php:94 +#, php-format +msgid "Please enter at least %s characters." +msgstr "" + #: inc/fields/address-markup.php:29 msgid "Address" msgstr "" @@ -1334,92 +1401,108 @@ msgstr "" msgid "Number" msgstr "" -#: inc/fields/payment-markup.php:249 +#: inc/fields/payment-markup.php:246 +msgid "One-Time Payment" +msgstr "" + +#: inc/fields/payment-markup.php:247 +#: inc/payments/admin/admin-handler.php:975 +#: inc/payments/payment-history-shortcode.php:306 +#: assets/build/blocks.js:172 +#: assets/build/payments.js:172 +msgid "Subscription" +msgstr "" + +#: inc/fields/payment-markup.php:346 #: inc/payments/payment-helper.php:543 msgid "Subscription Plan" msgstr "" +#: inc/fields/payment-markup.php:486 +msgid "Processing payment..." +msgstr "" + +#: inc/fields/payment-markup.php:513 +#: modules/gutenberg/icons/icons-v6-3.php:1812 +#: assets/build/payments.js:172 +msgid "Stripe" +msgstr "" + +#: inc/fields/payment-markup.php:514 +msgid "Pay with credit or debit card" +msgstr "" + +#: inc/fields/payment-markup.php:562 +msgid "Choose payment type" +msgstr "" + #. translators: 1: Amount with currency, 2: Interval (day/week/month/quarter/year) -#: inc/fields/payment-markup.php:288 +#: inc/fields/payment-markup.php:672 #, php-format msgid "%1$s per %2$s (until cancelled)" msgstr "" #. translators: 1: Amount with currency, 2: Interval (day/week/month/quarter/year), 3: Number of billing cycles -#: inc/fields/payment-markup.php:297 +#: inc/fields/payment-markup.php:681 #, php-format msgid "%1$s per %2$s (%3$s payments)" msgstr "" #. translators: 1: Amount with currency, 2: Interval (day/week/month/quarter/year) -#: inc/fields/payment-markup.php:307 +#: inc/fields/payment-markup.php:691 #, php-format msgid "%1$s per %2$s" msgstr "" #. translators: 1: Amount with currency placeholder, 2: Interval (day/week/month/quarter/year) -#: inc/fields/payment-markup.php:334 +#: inc/fields/payment-markup.php:714 #, php-format msgid "{amount} per %s (until cancelled)" msgstr "" #. translators: 1: Amount with currency placeholder, 2: Interval (day/week/month/quarter/year), 3: Number of billing cycles -#: inc/fields/payment-markup.php:337 +#: inc/fields/payment-markup.php:717 #, php-format msgid "{amount} per %1$s (%2$s payments)" msgstr "" #. translators: 1: Amount with currency placeholder, 2: Interval (day/week/month/quarter/year) -#: inc/fields/payment-markup.php:340 +#: inc/fields/payment-markup.php:720 #, php-format msgid "{amount} per %s" msgstr "" #. translators: %s: Minimum amount with currency -#: inc/fields/payment-markup.php:353 +#: inc/fields/payment-markup.php:740 #, php-format msgid "Minimum amount: %s" msgstr "" -#: inc/fields/payment-markup.php:385 -msgid "Processing payment..." -msgstr "" - -#: inc/fields/payment-markup.php:412 -#: modules/gutenberg/icons/icons-v6-3.php:1812 -#: assets/build/payments.js:172 -msgid "Stripe" -msgstr "" - -#: inc/fields/payment-markup.php:413 -msgid "Pay with credit or debit card" -msgstr "" - -#: inc/fields/payment-markup.php:579 +#: inc/fields/payment-markup.php:906 msgid "day" msgstr "" -#: inc/fields/payment-markup.php:580 +#: inc/fields/payment-markup.php:907 msgid "week" msgstr "" -#: inc/fields/payment-markup.php:581 +#: inc/fields/payment-markup.php:908 msgid "month" msgstr "" -#: inc/fields/payment-markup.php:582 +#: inc/fields/payment-markup.php:909 msgid "quarter" msgstr "" -#: inc/fields/payment-markup.php:583 +#: inc/fields/payment-markup.php:910 msgid "year" msgstr "" -#: inc/fields/payment-markup.php:608 +#: inc/fields/payment-markup.php:935 msgid "Test mode is enabled:" msgstr "" -#: inc/fields/payment-markup.php:610 +#: inc/fields/payment-markup.php:937 msgid "Click here to enable live mode and accept payment" msgstr "" @@ -1428,7 +1511,7 @@ msgstr "" msgid "Phone" msgstr "" -#: inc/fields/textarea-markup.php:95 +#: inc/fields/textarea-markup.php:111 msgid "Textarea" msgstr "" @@ -1438,15 +1521,15 @@ msgstr "" msgid "URL" msgstr "" -#: inc/form-restriction.php:160 -#: inc/form-restriction.php:161 +#: inc/form-restriction.php:182 +#: inc/form-restriction.php:183 #: inc/post-types.php:1203 #: inc/post-types.php:1243 msgid "This form is not yet available. Check back after the scheduled start time." msgstr "" -#: inc/form-restriction.php:165 -#: inc/form-restriction.php:166 +#: inc/form-restriction.php:187 +#: inc/form-restriction.php:188 #: assets/build/formEditor.js:172 msgid "This form is no longer accepting submissions. The submission period has ended." msgstr "" @@ -1455,8 +1538,8 @@ msgstr "" #: inc/form-submit.php:400 #: inc/form-submit.php:445 #: inc/form-submit.php:968 -#: inc/payments/front-end.php:77 -#: inc/payments/front-end.php:258 +#: 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 @@ -1914,11 +1997,6 @@ msgstr "" msgid "Invalid nonce action or name." msgstr "" -#: inc/helper.php:2029 -#: inc/helper.php:2037 -msgid "Invalid security token." -msgstr "" - #: inc/helper.php:2044 msgid "Invalid request type." msgstr "" @@ -2754,13 +2832,6 @@ msgstr "" msgid "N/A" msgstr "" -#: inc/payments/admin/admin-handler.php:975 -#: inc/payments/payment-history-shortcode.php:306 -#: assets/build/blocks.js:172 -#: assets/build/payments.js:172 -msgid "Subscription" -msgstr "" - #: inc/payments/admin/admin-handler.php:977 msgid "Renewal" msgstr "" @@ -2782,27 +2853,27 @@ msgstr "" #: inc/payments/admin/admin-handler.php:1468 #: inc/payments/admin/admin-handler.php:1472 #: inc/payments/admin/admin-handler.php:1476 -#: inc/payments/front-end.php:811 -#: inc/payments/front-end.php:1209 +#: inc/payments/front-end.php:854 +#: inc/payments/front-end.php:1253 msgid "Guest User" msgstr "" -#: inc/payments/front-end.php:91 +#: inc/payments/front-end.php:92 msgid "Invalid payment amount." msgstr "" -#: inc/payments/front-end.php:97 -#: inc/payments/front-end.php:298 -#: inc/payments/payment-helper.php:594 +#: inc/payments/front-end.php:98 +#: inc/payments/front-end.php:303 +#: inc/payments/payment-helper.php:595 msgid "Invalid form configuration." msgstr "" -#: inc/payments/front-end.php:107 +#: inc/payments/front-end.php:109 msgid "Valid customer email is required for payments." msgstr "" -#: inc/payments/front-end.php:113 -#: inc/payments/front-end.php:320 +#: inc/payments/front-end.php:115 +#: inc/payments/front-end.php:340 #: inc/payments/stripe/admin-stripe-handler.php:877 #: inc/payments/stripe/payments-settings.php:349 #: inc/payments/stripe/payments-settings.php:474 @@ -2812,137 +2883,141 @@ msgstr "" msgid "Stripe is not connected." msgstr "" -#: inc/payments/front-end.php:119 -#: inc/payments/front-end.php:326 -#: inc/payments/front-end.php:610 -#: inc/payments/front-end.php:1099 +#: inc/payments/front-end.php:121 +#: inc/payments/front-end.php:346 +#: inc/payments/front-end.php:634 +#: inc/payments/front-end.php:1142 msgid "Stripe secret key not found." msgstr "" #. translators: %s: formatted payment amount -#: inc/payments/front-end.php:201 +#: inc/payments/front-end.php:203 #, php-format msgid "The payment amount (%s) is below the minimum allowed. Stripe only processes amounts above 50¢." msgstr "" #. translators: %s: Field name -#: inc/payments/front-end.php:268 +#: inc/payments/front-end.php:273 #, php-format msgid "Missing required field: %s" msgstr "" -#: inc/payments/front-end.php:287 +#: inc/payments/front-end.php:292 msgid "Valid customer email is required for subscriptions." msgstr "" -#: inc/payments/front-end.php:292 +#: inc/payments/front-end.php:297 msgid "Customer name is required for subscriptions." msgstr "" -#: inc/payments/front-end.php:308 +#: inc/payments/front-end.php:314 msgid "Amount must be greater than 0" msgstr "" -#: inc/payments/front-end.php:314 +#: inc/payments/front-end.php:322 msgid "Invalid billing interval" msgstr "" -#: inc/payments/front-end.php:337 +#: inc/payments/front-end.php:333 +msgid "Billing interval does not match the form configuration." +msgstr "" + +#: inc/payments/front-end.php:357 msgid "Failed to create customer for subscription." msgstr "" -#: inc/payments/front-end.php:370 -#: inc/payments/front-end.php:386 +#: inc/payments/front-end.php:390 +#: inc/payments/front-end.php:406 msgid "Failed to create subscription through middleware." msgstr "" -#: inc/payments/front-end.php:391 +#: inc/payments/front-end.php:411 msgid "Empty response from subscription creation." msgstr "" -#: inc/payments/front-end.php:396 +#: inc/payments/front-end.php:416 msgid "Invalid JSON response from subscription creation." msgstr "" -#: inc/payments/front-end.php:400 -#: inc/payments/front-end.php:404 +#: inc/payments/front-end.php:420 +#: inc/payments/front-end.php:424 msgid "Invalid subscription data." msgstr "" -#: inc/payments/front-end.php:411 +#: inc/payments/front-end.php:431 msgid "Failed to create subscription." msgstr "" #. translators: %s: Error message -#: inc/payments/front-end.php:441 +#: inc/payments/front-end.php:464 #, php-format msgid "Unexpected error: %s" msgstr "" -#: inc/payments/front-end.php:581 +#: inc/payments/front-end.php:604 #: inc/payments/stripe/admin-stripe-handler.php:103 #: inc/payments/stripe/admin-stripe-handler.php:184 #: inc/payments/stripe/admin-stripe-handler.php:489 msgid "Subscription ID not found." msgstr "" -#: inc/payments/front-end.php:599 +#: inc/payments/front-end.php:623 msgid "Customer ID not found for the payment." msgstr "" -#: inc/payments/front-end.php:627 +#: inc/payments/front-end.php:651 msgid "Failed to retrieve setup intent." msgstr "" -#: inc/payments/front-end.php:656 +#: inc/payments/front-end.php:699 msgid "Failed to update subscription." msgstr "" -#: inc/payments/front-end.php:664 +#: inc/payments/front-end.php:707 msgid "Latest invoice not found on subscription." msgstr "" -#: inc/payments/front-end.php:677 +#: inc/payments/front-end.php:720 msgid "Failed to retrieve invoice." msgstr "" -#: inc/payments/front-end.php:699 +#: inc/payments/front-end.php:742 msgid "Payment intent not found on invoice." msgstr "" -#: inc/payments/front-end.php:714 +#: inc/payments/front-end.php:757 msgid "Failed to confirm payment." msgstr "" -#: inc/payments/front-end.php:730 +#: inc/payments/front-end.php:773 msgid "Failed to retrieve subscription." msgstr "" -#: inc/payments/front-end.php:745 +#: inc/payments/front-end.php:788 msgid "Subscription not found for the payment." msgstr "" #. translators: %d: User ID -#: inc/payments/front-end.php:809 -#: inc/payments/front-end.php:1209 +#: inc/payments/front-end.php:852 +#: inc/payments/front-end.php:1253 #, php-format msgid "User ID: %d" msgstr "" #. translators: %s: Invoice status -#: inc/payments/front-end.php:817 +#: inc/payments/front-end.php:860 #, php-format msgid "Invoice Status: %s" msgstr "" #. translators: Title for subscription verification log -#: inc/payments/front-end.php:824 +#: inc/payments/front-end.php:867 msgid "Subscription Verification" msgstr "" #. translators: %s: Subscription ID #. translators: %s: Stripe subscription ID -#: inc/payments/front-end.php:828 +#: inc/payments/front-end.php:871 #: inc/payments/stripe/admin-stripe-handler.php:119 #: inc/payments/stripe/admin-stripe-handler.php:204 #: inc/payments/stripe/admin-stripe-handler.php:505 @@ -2958,8 +3033,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:830 -#: inc/payments/front-end.php:1220 +#: inc/payments/front-end.php:873 +#: inc/payments/front-end.php:1264 #: inc/payments/stripe/admin-stripe-handler.php:124 #: inc/payments/stripe/admin-stripe-handler.php:209 #: inc/payments/stripe/admin-stripe-handler.php:510 @@ -2974,13 +3049,13 @@ msgid "Payment Gateway: %s" msgstr "" #. translators: %s: Payment Intent ID -#: inc/payments/front-end.php:832 +#: inc/payments/front-end.php:875 #, php-format msgid "Payment Intent ID: %s" msgstr "" #. translators: %s: Charge ID -#: inc/payments/front-end.php:834 +#: inc/payments/front-end.php:877 #: inc/payments/stripe/stripe-webhook.php:1048 #, php-format msgid "Charge ID: %s" @@ -2988,7 +3063,7 @@ msgstr "" #. translators: %s: Subscription Status #. translators: %s: subscription status -#: inc/payments/front-end.php:836 +#: inc/payments/front-end.php:879 #: inc/payments/stripe/admin-stripe-handler.php:129 #: inc/payments/stripe/admin-stripe-handler.php:214 #: inc/payments/stripe/admin-stripe-handler.php:515 @@ -2997,7 +3072,7 @@ msgid "Subscription Status: %s" msgstr "" #. translators: %s: Customer ID -#: inc/payments/front-end.php:838 +#: inc/payments/front-end.php:881 #: inc/payments/stripe/stripe-webhook.php:1122 #, php-format msgid "Customer ID: %s" @@ -3005,8 +3080,8 @@ msgstr "" #. translators: 1: Amount, 2: Currency #. translators: %1$s: amount, %2$s: currency. -#: inc/payments/front-end.php:840 -#: inc/payments/front-end.php:1222 +#: inc/payments/front-end.php:883 +#: inc/payments/front-end.php:1266 #: inc/payments/stripe/stripe-webhook.php:1053 #: inc/payments/stripe/stripe-webhook.php:1114 #, php-format @@ -3015,34 +3090,34 @@ msgstr "" #. translators: %s: Payment mode (e.g. Live or Test) #. translators: %s: payment mode -#: inc/payments/front-end.php:843 -#: inc/payments/front-end.php:1227 +#: inc/payments/front-end.php:886 +#: inc/payments/front-end.php:1271 #, php-format msgid "Mode: %s" msgstr "" -#: inc/payments/front-end.php:877 +#: inc/payments/front-end.php:920 msgid "Failed to verify subscription." msgstr "" -#: inc/payments/front-end.php:1131 -#: inc/payments/front-end.php:1149 -#: inc/payments/front-end.php:1157 -#: inc/payments/front-end.php:1164 +#: inc/payments/front-end.php:1175 +#: inc/payments/front-end.php:1193 +#: inc/payments/front-end.php:1201 +#: inc/payments/front-end.php:1208 msgid "Failed to retrieve payment intent." msgstr "" -#: inc/payments/front-end.php:1172 +#: inc/payments/front-end.php:1216 msgid "Payment was not confirmed successfully." msgstr "" -#: inc/payments/front-end.php:1214 +#: inc/payments/front-end.php:1258 msgid "Payment Verification" msgstr "" #. translators: %s: Stripe transaction ID #. translators: %s: Charge ID -#: inc/payments/front-end.php:1218 +#: inc/payments/front-end.php:1262 #: inc/payments/stripe/stripe-webhook.php:1110 #, php-format msgid "Transaction ID: %s" @@ -3050,18 +3125,18 @@ msgstr "" #. translators: %s: payment status #. translators: %s: Status -#: inc/payments/front-end.php:1224 +#: inc/payments/front-end.php:1268 #: inc/payments/stripe/stripe-webhook.php:576 #: inc/payments/stripe/stripe-webhook.php:1116 #, php-format msgid "Status: %s" msgstr "" -#: inc/payments/front-end.php:1330 +#: inc/payments/front-end.php:1374 msgid "Failed to create Stripe customer." msgstr "" -#: inc/payments/front-end.php:1394 +#: inc/payments/front-end.php:1438 msgid "Failed to create Stripe guest customer." msgstr "" @@ -3451,74 +3526,84 @@ msgstr "" msgid "Unknown error" msgstr "" -#: inc/payments/payment-helper.php:602 +#: inc/payments/payment-helper.php:603 msgid "Payment configuration not found for this form." msgstr "" #. translators: 1: expected currency, 2: received currency -#: inc/payments/payment-helper.php:613 +#: inc/payments/payment-helper.php:614 #, php-format msgid "Currency mismatch: expected %1$s, received %2$s." msgstr "" +#: inc/payments/payment-helper.php:627 +msgid "Payment type does not match the form configuration." +msgstr "" + #. translators: 1: expected amount with currency -#: inc/payments/payment-helper.php:630 +#: inc/payments/payment-helper.php:649 #, php-format msgid "Payment amount must be exactly %1$s." msgstr "" #. translators: 1: minimum amount with currency -#: inc/payments/payment-helper.php:641 +#: inc/payments/payment-helper.php:660 #, php-format msgid "Payment amount must be at least %1$s." msgstr "" -#: inc/payments/payment-helper.php:717 +#: inc/payments/payment-helper.php:737 msgid "Invalid payment verification parameters." msgstr "" -#: inc/payments/payment-helper.php:728 +#: inc/payments/payment-helper.php:748 msgid "Payment verification failed. Invalid payment intent." msgstr "" -#: inc/payments/payment-helper.php:814 -#: inc/payments/payment-helper.php:952 +#: inc/payments/payment-helper.php:760 +msgid "Payment verification failed. Payment type mismatch." +msgstr "" + +#: inc/payments/payment-helper.php:903 +#: inc/payments/payment-helper.php:1043 msgid "Variable amount field configuration not found." msgstr "" -#: inc/payments/payment-helper.php:835 +#: inc/payments/payment-helper.php:924 msgid "No payment options are configured for this field." msgstr "" #. translators: %s: currency code -#: inc/payments/payment-helper.php:861 +#: inc/payments/payment-helper.php:950 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:896 +#: inc/payments/payment-helper.php:986 msgid "Payment configuration not found." msgstr "" #. translators: %1$s: expected amount, %2$s: payment amount -#: inc/payments/payment-helper.php:912 -#: inc/payments/payment-helper.php:964 -#: inc/payments/payment-helper.php:1000 +#: inc/payments/payment-helper.php:1003 +#: inc/payments/payment-helper.php:1055 +#: inc/payments/payment-helper.php:1091 +#: inc/payments/payment-helper.php:1111 #, php-format msgid "Payment amount mismatch. Expected %1$s, received %2$s." msgstr "" -#: inc/payments/payment-helper.php:941 -#: inc/payments/payment-helper.php:991 +#: 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." msgstr "" -#: inc/payments/payment-helper.php:974 +#: inc/payments/payment-helper.php:1065 msgid "Number field configuration not found." msgstr "" #. translators: %1$s: minimum amount, %2$s: payment amount -#: inc/payments/payment-helper.php:1012 +#: inc/payments/payment-helper.php:1125 #, php-format msgid "Payment amount below minimum. Minimum: %1$s, received %2$s." msgstr "" @@ -3819,11 +3904,6 @@ msgstr "" msgid "Missing payment ID." msgstr "" -#: inc/payments/stripe/admin-stripe-handler.php:84 -#: inc/payments/stripe/admin-stripe-handler.php:470 -msgid "You are not allowed to perform this action." -msgstr "" - #: inc/payments/stripe/admin-stripe-handler.php:94 #: inc/payments/stripe/admin-stripe-handler.php:478 msgid "Payment not found in the database." @@ -4636,32 +4716,32 @@ msgid "Enter a valid email address." msgstr "" #. translators: %s represents the minimum acceptable value -#: inc/translatable.php:94 +#: inc/translatable.php:97 #, php-format msgid "Minimum value is %s." msgstr "" #. translators: %s represents the maximum acceptable value -#: inc/translatable.php:97 +#: inc/translatable.php:100 #, php-format msgid "Maximum value is %s." msgstr "" #. translators: %s represents the minimum number of options to select -#: inc/translatable.php:100 -#: inc/translatable.php:106 +#: inc/translatable.php:103 +#: inc/translatable.php:109 #, php-format msgid "Select at least %s options." msgstr "" #. translators: %s represents the maximum number of options that can be selected -#: inc/translatable.php:103 -#: inc/translatable.php:109 +#: inc/translatable.php:106 +#: inc/translatable.php:112 #, php-format msgid "You can select up to %s options." msgstr "" -#: inc/translatable.php:120 +#: inc/translatable.php:123 msgid "This form is now closed as we have reached the maximum number of entries." msgstr "" @@ -12688,6 +12768,14 @@ msgstr "" msgid "Rich Text Editor" msgstr "" +#: assets/build/blocks.js:172 +msgid "Minimum Characters" +msgstr "" + +#: assets/build/blocks.js:172 +msgid "Minimum characters cannot exceed Maximum characters." +msgstr "" + #: assets/build/blocks.js:172 msgid "Textarea Height" msgstr "" @@ -12978,6 +13066,10 @@ msgstr "" msgid "Payment Type" msgstr "" +#: assets/build/blocks.js:172 +msgid "Both" +msgstr "" + #: assets/build/blocks.js:172 msgid "Subscription Plan Name" msgstr "" @@ -13007,7 +13099,31 @@ msgid "Yearly" msgstr "" #: assets/build/blocks.js:172 -msgid "Amount Type" +msgid "One-Time Label" +msgstr "" + +#: assets/build/blocks.js:172 +msgid "Label shown to users for the one-time payment option." +msgstr "" + +#: assets/build/blocks.js:172 +msgid "Subscription Label" +msgstr "" + +#: assets/build/blocks.js:172 +msgid "Label shown to users for the subscription option." +msgstr "" + +#: assets/build/blocks.js:172 +msgid "Default Selection" +msgstr "" + +#: assets/build/blocks.js:172 +msgid "Which option is pre-selected when the form loads." +msgstr "" + +#: assets/build/blocks.js:172 +msgid "One-Time Amount Type" msgstr "" #: assets/build/blocks.js:172 @@ -13019,15 +13135,19 @@ msgid "Dynamic Amount" msgstr "" #: 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." +msgid "Set how the one-time payment amount is determined." msgstr "" #: assets/build/blocks.js:172 -msgid "Set the exact amount you want to charge. Users won’t be able to change it" +msgid "One-Time Fixed Amount" msgstr "" #: assets/build/blocks.js:172 -msgid "Choose Amount Field" +msgid "Amount charged for a one-time payment." +msgstr "" + +#: assets/build/blocks.js:172 +msgid "One-Time Amount Field" msgstr "" #: assets/build/blocks.js:172 @@ -13035,7 +13155,67 @@ msgid "Select a field…" msgstr "" #: assets/build/blocks.js:172 -msgid "Pick a field from your form like a number, dropdown, or multichoice whose value should decide the payment amount." +msgid "Pick a form field whose value determines the one-time payment amount." +msgstr "" + +#: assets/build/blocks.js:172 +msgid "One-Time Minimum Amount" +msgstr "" + +#: assets/build/blocks.js:172 +msgid "Minimum amount users can enter for one-time payment (0 for no minimum)." +msgstr "" + +#: assets/build/blocks.js:172 +msgid "Subscription Amount Type" +msgstr "" + +#: assets/build/blocks.js:172 +msgid "Set how the subscription amount is determined." +msgstr "" + +#: assets/build/blocks.js:172 +msgid "Subscription Fixed Amount" +msgstr "" + +#: assets/build/blocks.js:172 +msgid "Recurring amount charged per billing interval." +msgstr "" + +#: assets/build/blocks.js:172 +msgid "Subscription Amount Field" +msgstr "" + +#: assets/build/blocks.js:172 +msgid "Pick a form field whose value determines the subscription amount." +msgstr "" + +#: assets/build/blocks.js:172 +msgid "Subscription Minimum Amount" +msgstr "" + +#: assets/build/blocks.js:172 +msgid "Minimum amount users can enter for subscription (0 for no minimum)." +msgstr "" + +#: assets/build/blocks.js:172 +msgid "Amount Type" +msgstr "" + +#: 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:172 +msgid "Set the exact amount you want to charge. Users won’t be able to change it" +msgstr "" + +#: assets/build/blocks.js:172 +msgid "Choose Amount Field" +msgstr "" + +#: 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 "" #: assets/build/blocks.js:172 @@ -15264,10 +15444,6 @@ msgstr "" msgid "Build engaging conversational, calculation, and multi-step forms." msgstr "" -#: assets/build/forms.js:172 -msgid "Create Form" -msgstr "" - #: assets/build/forms.js:172 msgid "An error occurred while fetching forms." msgstr "" @@ -16695,6 +16871,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 "" @@ -16970,10 +17154,30 @@ msgstr "" msgid "Generating fields" msgstr "" +#: assets/build/templatePicker.js:172 +msgid "Unable to reach the SureForms AI service. Please check your connection and try again." +msgstr "" + +#: assets/build/templatePicker.js:172 +msgid "The AI service did not return a response. Please try again." +msgstr "" + #: assets/build/templatePicker.js:172 msgid "Finalizing your form" msgstr "" +#: assets/build/templatePicker.js:172 +msgid "Form generation failed. Please try again." +msgstr "" + +#: assets/build/templatePicker.js:172 +msgid "The AI response was empty. Please refine your prompt and try again." +msgstr "" + +#: assets/build/templatePicker.js:172 +msgid "Unable to build form fields from the AI response." +msgstr "" + #: assets/build/templatePicker.js:172 msgid "Opening form editor" msgstr "" diff --git a/modules/gutenberg/dist/blocks/advanced-heading/class-advanced-heading.php b/modules/gutenberg/dist/blocks/advanced-heading/class-advanced-heading.php index f5179bc3d..b0de4215b 100644 --- a/modules/gutenberg/dist/blocks/advanced-heading/class-advanced-heading.php +++ b/modules/gutenberg/dist/blocks/advanced-heading/class-advanced-heading.php @@ -664,7 +664,17 @@ public function render_html( $attributes ) { $heading_wrapper = $attributes['headingWrapper']; } - $element = ! empty( $heading_wrapper ) ? $heading_wrapper : 'div'; + // Validate tag-name attributes against the editor UI options to prevent + // arbitrary HTML injection in tag-name position (esc_attr() does not strip + // `<`, `>`, spaces or `=`, which is unsafe when echoed as a tag name). + $allowed_wrapper_tags = [ 'div', 'header' ]; + $allowed_heading_tags = [ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'div' ]; + + $element = in_array( $heading_wrapper, $allowed_wrapper_tags, true ) ? $heading_wrapper : 'div'; + + $heading_tag = isset( $attributes['headingTag'] ) && in_array( $attributes['headingTag'], $allowed_heading_tags, true ) + ? $attributes['headingTag'] + : 'h2'; $seperator = ''; @@ -681,7 +691,7 @@ public function render_html( $attributes ) { $attributes['headingId'] = isset( $attributes['headingId'] ) ? "id='{$attributes['headingId']}'" : ''; $heading_text .= sprintf( '<%1$s class="uagb-heading-text" %3$s>%2$s', - esc_attr( $attributes['headingTag'] ), + esc_attr( $heading_tag ), $attributes['headingTitle'], esc_attr( $attributes['headingId'] ) ); diff --git a/modules/gutenberg/dist/blocks/image/class-spec-image.php b/modules/gutenberg/dist/blocks/image/class-spec-image.php index bb88749df..2fd8ee418 100644 --- a/modules/gutenberg/dist/blocks/image/class-spec-image.php +++ b/modules/gutenberg/dist/blocks/image/class-spec-image.php @@ -783,11 +783,19 @@ class="' . esc_attr( $attributes['linkClass'] ) . '" if ( ! empty( $attributes['heading'] ) ) { - $heading_id = isset( $attributes['headingId'] ) ? ' id="' . $attributes['headingId'] . '"' : ''; + // Validate the tag-name attribute against the editor UI options + // (esc_html() does not strip spaces or `=`, which is unsafe when + // echoed in tag-name position). + $allowed_heading_tags = [ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6' ]; + $heading_tag = isset( $attributes['headingTag'] ) && in_array( $attributes['headingTag'], $allowed_heading_tags, true ) + ? $attributes['headingTag'] + : 'h2'; + + $heading_id = ! empty( $attributes['headingId'] ) ? ' id="' . esc_attr( $attributes['headingId'] ) . '"' : ''; $image_heading = sprintf( '<%1$s%2$s class="uagb-image-heading">%3$s', - esc_html( $attributes['headingTag'] ), - esc_attr( $heading_id ), + esc_html( $heading_tag ), + $heading_id, esc_html( $attributes['heading'] ) ); } diff --git a/modules/gutenberg/src/components/background/index.js b/modules/gutenberg/src/components/background/index.js index 60df4e862..5fde166bc 100644 --- a/modules/gutenberg/src/components/background/index.js +++ b/modules/gutenberg/src/components/background/index.js @@ -357,6 +357,7 @@ const Background = ( props ) => { <>
{
{
{
@@ -594,6 +598,7 @@ const Background = ( props ) => {
@@ -1351,6 +1356,7 @@ const Background = ( props ) => { <>
{
@@ -1452,6 +1459,7 @@ const Background = ( props ) => {
@@ -1490,6 +1498,7 @@ const Background = ( props ) => {
diff --git a/modules/gutenberg/src/components/number-control/index.js b/modules/gutenberg/src/components/number-control/index.js index a94f96397..9e91a6339 100644 --- a/modules/gutenberg/src/components/number-control/index.js +++ b/modules/gutenberg/src/components/number-control/index.js @@ -226,6 +226,7 @@ const UAGNumberControl = ( props ) => { { ! isEnableDynamicContent() && ( <> { const presetDropdown = ( {
{ /> { withInputField && isNumberControlSupported && ( { const output = {}; output.Desktop = ( setAttributes( { [ data.desktop.label ]: value } ) @@ -53,6 +54,7 @@ const ResponsiveSelectControl = ( props ) => { ); output.Tablet = ( setAttributes( { [ data.tablet.label ]: value } ) @@ -62,6 +64,7 @@ const ResponsiveSelectControl = ( props ) => { ); output.Mobile = ( setAttributes( { [ data.mobile.label ]: value } ) diff --git a/modules/gutenberg/src/components/select-control/index.js b/modules/gutenberg/src/components/select-control/index.js index 28a6afa93..2263f2cb1 100644 --- a/modules/gutenberg/src/components/select-control/index.js +++ b/modules/gutenberg/src/components/select-control/index.js @@ -93,6 +93,7 @@ export default function UAGSelectControl( { { controlBeforeDomElement } { children ? ( @@ -106,6 +107,7 @@ export default function UAGSelectControl( { ) : ( diff --git a/modules/gutenberg/src/components/text-control/index.js b/modules/gutenberg/src/components/text-control/index.js index 1f225a746..0d5272084 100644 --- a/modules/gutenberg/src/components/text-control/index.js +++ b/modules/gutenberg/src/components/text-control/index.js @@ -132,6 +132,7 @@ const UAGTextControl = ( props ) => { <> { props?.variant !== 'textarea' && ( =6.9.0" } @@ -121,6 +123,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.27.1.tgz", "integrity": "sha512-IaaGWsQqfsQWVLqMn9OB92MNN7zukfVA4s7KKAI0KfrrDsZ0yhi5uV4baBuLuN7n3vsZpwP8asPPcVwApxvjBQ==", + "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.27.1", @@ -183,6 +186,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.1.tgz", "integrity": "sha512-WnuuDILl9oOBbKnb4L+DyODx7iC47XfzmNCpTttFsSp6hTG7XZxu60+4IO+2/hPfcGOoKbFiwoI/+zwARbNQow==", + "dev": true, "dependencies": { "@babel/types": "^7.27.1" }, @@ -194,6 +198,7 @@ "version": "7.27.2", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", + "dev": true, "dependencies": { "@babel/compat-data": "^7.27.2", "@babel/helper-validator-option": "^7.27.1", @@ -209,6 +214,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.27.1.tgz", "integrity": "sha512-QwGAmuvM17btKU5VqXfb+Giw4JcN0hjuufz3DYnpeVDvZLAObloM77bhMXiqry3Iio+Ai4phVRDwl6WU10+r5A==", + "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.1", "@babel/helper-member-expression-to-functions": "^7.27.1", @@ -229,6 +235,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.27.1.tgz", "integrity": "sha512-uVDC72XVf8UbrH5qQTc18Agb8emwjTiZrQE11Nv3CuBEZmVvTwwE9CBUEvHku06gQCAyYf8Nv6ja1IN+6LMbxQ==", + "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.1", "regexpu-core": "^6.2.0", @@ -245,6 +252,7 @@ "version": "0.6.4", "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.4.tgz", "integrity": "sha512-jljfR1rGnXXNWnmQg2K3+bvhkxB51Rl32QRaOTuwwjviGrHzIbSc8+x9CpraDtbT7mfyjXObULP4w/adunNwAw==", + "dev": true, "dependencies": { "@babel/helper-compilation-targets": "^7.22.6", "@babel/helper-plugin-utils": "^7.22.5", @@ -260,6 +268,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.27.1.tgz", "integrity": "sha512-E5chM8eWjTp/aNoVpcbfM7mLxu9XGLWYise2eBKGQomAk/Mb4XoxyqXTZbuTohbsl8EKqdlMhnDI2CCLfcs9wA==", + "dev": true, "dependencies": { "@babel/traverse": "^7.27.1", "@babel/types": "^7.27.1" @@ -284,6 +293,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.1.tgz", "integrity": "sha512-9yHn519/8KvTU5BjTVEEeIM3w9/2yXNKoD82JifINImhpKkARMJKPP59kLo+BafpdN5zgNeIcS4jsGDmd3l58g==", + "dev": true, "dependencies": { "@babel/helper-module-imports": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1", @@ -300,6 +310,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz", "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==", + "dev": true, "dependencies": { "@babel/types": "^7.27.1" }, @@ -311,6 +322,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", + "dev": true, "engines": { "node": ">=6.9.0" } @@ -319,6 +331,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.27.1.tgz", "integrity": "sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==", + "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.1", "@babel/helper-wrap-function": "^7.27.1", @@ -335,6 +348,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.27.1.tgz", "integrity": "sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA==", + "dev": true, "dependencies": { "@babel/helper-member-expression-to-functions": "^7.27.1", "@babel/helper-optimise-call-expression": "^7.27.1", @@ -351,6 +365,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz", "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==", + "dev": true, "dependencies": { "@babel/traverse": "^7.27.1", "@babel/types": "^7.27.1" @@ -379,6 +394,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, "engines": { "node": ">=6.9.0" } @@ -387,6 +403,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.27.1.tgz", "integrity": "sha512-NFJK2sHUvrjo8wAU/nQTWU890/zB2jj0qBcCbZbbf+005cAsv6tMjXz31fBign6M5ov1o0Bllu+9nbqkfsjjJQ==", + "dev": true, "dependencies": { "@babel/template": "^7.27.1", "@babel/traverse": "^7.27.1", @@ -400,6 +417,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.1.tgz", "integrity": "sha512-FCvFTm0sWV8Fxhpp2McP5/W53GPllQ9QeQ7SiqGWjMf/LVG07lFa5+pgK05IRhVwtvafT22KF+ZSnM9I545CvQ==", + "dev": true, "dependencies": { "@babel/template": "^7.27.1", "@babel/types": "^7.27.1" @@ -426,6 +444,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.27.1.tgz", "integrity": "sha512-QPG3C9cCVRQLxAVwmefEmwdTanECuUBMQZ/ym5kiw3XKCGA7qkuQLcjWWHcrD/GKbn/WmJwaezfuuAOcyKlRPA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/traverse": "^7.27.1" @@ -441,6 +460,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.27.1.tgz", "integrity": "sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -455,6 +475,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.27.1.tgz", "integrity": "sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -469,6 +490,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.27.1.tgz", "integrity": "sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", @@ -485,6 +507,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.27.1.tgz", "integrity": "sha512-6BpaYGDavZqkI6yT+KSPdpZFfpnd68UKXbcjI9pJ13pvHhPrCKWOOLp+ysvMeA+DxnhuPpgIaRpxRxo5A9t5jw==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/traverse": "^7.27.1" @@ -496,138 +519,6 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/plugin-proposal-class-properties": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", - "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead.", - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-decorators": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.27.1.tgz", - "integrity": "sha512-DTxe4LBPrtFdsWzgpmbBKevg3e9PBy+dXRt19kSbucbZvL2uqtdqwwpluL1jfxYE0wIDTFp1nTy/q6gNLsxXrg==", - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/plugin-syntax-decorators": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-export-default-from": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.27.1.tgz", - "integrity": "sha512-hjlsMBl1aJc5lp8MoCDEZCiYzlgdRAShOjAfRw6X+GlpLpUPU7c3XNLsKFZbQk/1cRzBlJ7CXg3xJAJMrFa1Uw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", - "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-nullish-coalescing-operator instead.", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-object-rest-spread": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz", - "integrity": "sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-object-rest-spread instead.", - "dependencies": { - "@babel/compat-data": "^7.20.5", - "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.20.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-optional-chaining": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz", - "integrity": "sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-chaining instead.", - "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-private-methods": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz", - "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-private-methods instead.", - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-private-property-in-object": { - "version": "7.21.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.11.tgz", - "integrity": "sha512-0QZ8qP/3RLDVBwBFoWAwCtgcDZJVwA5LUJRZU8x2YFfKNuFq161wK3cuGrALu5yiPu+vzwTAg/sMWVNeWeNyaw==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-private-property-in-object instead.", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-create-class-features-plugin": "^7.21.0", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/plugin-syntax-async-generators": { "version": "7.8.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", @@ -679,24 +570,11 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-decorators": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.27.1.tgz", - "integrity": "sha512-YMq8Z87Lhl8EGkmb0MwYkt36QnxC+fzCgrl66ereamPlYToRpIk5nUjKUY3QKLWq8mwUB1BgbeXcTJhZOCDg5A==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/plugin-syntax-dynamic-import": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -708,6 +586,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.27.1.tgz", "integrity": "sha512-UT/Jrhw57xg4ILHLFnzFpPDlMbcdEicaAtjPQpbj9wa8T4r5KVWCimHcL/460g8Ht0DMxDyjsLgiWSkVjnwPFg==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -722,6 +601,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz", "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -760,6 +640,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -786,6 +667,7 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -809,6 +691,7 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -832,6 +715,7 @@ "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -843,6 +727,7 @@ "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, @@ -872,6 +757,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz", "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -886,6 +772,7 @@ "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6" @@ -901,6 +788,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.27.1.tgz", "integrity": "sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -915,6 +803,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.27.1.tgz", "integrity": "sha512-eST9RrwlpaoJBDHShc+DS2SG4ATTi2MYNb4OxYkf3n+7eb49LWpnS+HSpVfW4x927qQwgk8A2hGNVaajAEw0EA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-remap-async-to-generator": "^7.27.1", @@ -931,6 +820,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.27.1.tgz", "integrity": "sha512-NREkZsZVJS4xmTr8qzE5y8AfIPqsdQfRuUiLRTEzb7Qii8iFWCyDKaUV2c0rCuh4ljDZ98ALHP/PetiBV2nddA==", + "dev": true, "dependencies": { "@babel/helper-module-imports": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1", @@ -947,6 +837,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.27.1.tgz", "integrity": "sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -961,6 +852,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.27.1.tgz", "integrity": "sha512-QEcFlMl9nGTgh1rn2nIeU5bkfb9BAjaQcWbiP4LvKxUot52ABcTkpcyJ7f2Q2U2RuQ84BNLgts3jRme2dTx6Fw==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -975,6 +867,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.27.1.tgz", "integrity": "sha512-D0VcalChDMtuRvJIu3U/fwWjf8ZMykz5iZsg77Nuj821vCKI3zCyRLwRdWbsuJ/uRwZhZ002QtCqIkwC/ZkvbA==", + "dev": true, "dependencies": { "@babel/helper-create-class-features-plugin": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1" @@ -990,6 +883,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.27.1.tgz", "integrity": "sha512-s734HmYU78MVzZ++joYM+NkJusItbdRcbm+AGRgJCt3iA+yux0QpD9cBVdz3tKyrjVYWRl7j0mHSmv4lhV0aoA==", + "dev": true, "dependencies": { "@babel/helper-create-class-features-plugin": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1" @@ -1005,6 +899,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.27.1.tgz", "integrity": "sha512-7iLhfFAubmpeJe/Wo2TVuDrykh/zlWXLzPNdL0Jqn/Xu8R3QQ8h9ff8FQoISZOsw74/HFqFI7NX63HN7QFIHKA==", + "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.1", "@babel/helper-compilation-targets": "^7.27.1", @@ -1024,6 +919,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.27.1.tgz", "integrity": "sha512-lj9PGWvMTVksbWiDT2tW68zGS/cyo4AkZ/QTp0sQT0mjPopCmrSkzxeXkznjqBxzDI6TclZhOJbBmbBLjuOZUw==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/template": "^7.27.1" @@ -1039,6 +935,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.27.1.tgz", "integrity": "sha512-ttDCqhfvpE9emVkXbPD8vyxxh4TWYACVybGkDj+oReOGwnp066ITEivDlLwe0b1R0+evJ13IXQuLNB5w1fhC5Q==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -1053,6 +950,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.27.1.tgz", "integrity": "sha512-gEbkDVGRvjj7+T1ivxrfgygpT7GUd4vmODtYpbs0gZATdkX8/iSnOtZSxiZnsgm1YjTgjI6VKBGSJJevkrclzw==", + "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1" @@ -1068,6 +966,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.27.1.tgz", "integrity": "sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -1082,6 +981,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.27.1.tgz", "integrity": "sha512-hkGcueTEzuhB30B3eJCbCYeCaaEQOmQR0AdvzpD4LoN0GXMWzzGSuRrxR2xTnCrvNbVwK9N6/jQ92GSLfiZWoQ==", + "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1" @@ -1097,6 +997,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.27.1.tgz", "integrity": "sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -1111,6 +1012,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.27.1.tgz", "integrity": "sha512-uspvXnhHvGKf2r4VVtBpeFnuDWsJLQ6MF6lGJLC89jBR1uoVeqM416AZtTuhTezOfgHicpJQmoD5YUakO/YmXQ==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -1125,6 +1027,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.27.1.tgz", "integrity": "sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -1139,6 +1042,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.27.1.tgz", "integrity": "sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" @@ -1154,6 +1058,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.27.1.tgz", "integrity": "sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ==", + "dev": true, "dependencies": { "@babel/helper-compilation-targets": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1", @@ -1170,6 +1075,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.27.1.tgz", "integrity": "sha512-6WVLVJiTjqcQauBhn1LkICsR2H+zm62I3h9faTDKt1qP4jn2o72tSvqMwtGFKGTpojce0gJs+76eZ2uCHRZh0Q==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -1184,6 +1090,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.27.1.tgz", "integrity": "sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -1198,6 +1105,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.27.1.tgz", "integrity": "sha512-SJvDs5dXxiae4FbSL1aBJlG4wvl594N6YEVVn9e3JGulwioy6z3oPjx/sQBO3Y4NwUu5HNix6KJ3wBZoewcdbw==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -1212,6 +1120,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.27.1.tgz", "integrity": "sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -1226,6 +1135,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.27.1.tgz", "integrity": "sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA==", + "dev": true, "dependencies": { "@babel/helper-module-transforms": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1" @@ -1241,6 +1151,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.27.1.tgz", "integrity": "sha512-OJguuwlTYlN0gBZFRPqwOGNWssZjfIUdS7HMYtN8c1KmwpwHFBwTeFZrg9XZa+DFTitWOW5iTAG7tyCUPsCCyw==", + "dev": true, "dependencies": { "@babel/helper-module-transforms": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1" @@ -1256,6 +1167,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.27.1.tgz", "integrity": "sha512-w5N1XzsRbc0PQStASMksmUeqECuzKuTJer7kFagK8AXgpCMkeDMO5S+aaFb7A51ZYDF7XI34qsTX+fkHiIm5yA==", + "dev": true, "dependencies": { "@babel/helper-module-transforms": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1", @@ -1273,6 +1185,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.27.1.tgz", "integrity": "sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w==", + "dev": true, "dependencies": { "@babel/helper-module-transforms": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1" @@ -1288,6 +1201,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.27.1.tgz", "integrity": "sha512-SstR5JYy8ddZvD6MhV0tM/j16Qds4mIpJTOd1Yu9J9pJjH93bxHECF7pgtc28XvkzTD6Pxcm/0Z73Hvk7kb3Ng==", + "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1" @@ -1303,6 +1217,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.27.1.tgz", "integrity": "sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -1317,6 +1232,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.27.1.tgz", "integrity": "sha512-aGZh6xMo6q9vq1JGcw58lZ1Z0+i0xB2x0XaauNIUXd6O1xXc3RwoWEBlsTQrY4KQ9Jf0s5rgD6SiNkaUdJegTA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -1331,6 +1247,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.27.1.tgz", "integrity": "sha512-fdPKAcujuvEChxDBJ5c+0BTaS6revLV7CJL08e4m3de8qJfNIuCc2nc7XJYOjBoTMJeqSmwXJ0ypE14RCjLwaw==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -1345,6 +1262,7 @@ "version": "7.27.2", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.27.2.tgz", "integrity": "sha512-AIUHD7xJ1mCrj3uPozvtngY3s0xpv7Nu7DoUSnzNY6Xam1Cy4rUznR//pvMHOhQ4AvbCexhbqXCtpxGHOGOO6g==", + "dev": true, "dependencies": { "@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-plugin-utils": "^7.27.1", @@ -1362,6 +1280,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.27.1.tgz", "integrity": "sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-replace-supers": "^7.27.1" @@ -1377,6 +1296,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.27.1.tgz", "integrity": "sha512-txEAEKzYrHEX4xSZN4kJ+OfKXFVSWKB2ZxM9dpcE3wT7smwkNmXo5ORRlVzMVdJbD+Q8ILTgSD7959uj+3Dm3Q==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -1391,6 +1311,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.27.1.tgz", "integrity": "sha512-BQmKPPIuc8EkZgNKsv0X4bPmOoayeu4F1YCwx2/CfmDSXDbp7GnzlUH+/ul5VGfRg1AoFPsrIThlEBj2xb4CAg==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" @@ -1406,6 +1327,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.27.1.tgz", "integrity": "sha512-018KRk76HWKeZ5l4oTj2zPpSh+NbGdt0st5S6x0pga6HgrjBOJb24mMDHorFopOOd6YHkLgOZ+zaCjZGPO4aKg==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -1420,6 +1342,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.27.1.tgz", "integrity": "sha512-10FVt+X55AjRAYI9BrdISN9/AQWHqldOeZDUoLyif1Kn05a56xVBXb8ZouL8pZ9jem8QpXaOt8TS7RHUIS+GPA==", + "dev": true, "dependencies": { "@babel/helper-create-class-features-plugin": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1" @@ -1435,6 +1358,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.27.1.tgz", "integrity": "sha512-5J+IhqTi1XPa0DXF83jYOaARrX+41gOewWbkPyjMNRDqgOCqdffGh8L3f/Ek5utaEBZExjSAzcyjmV9SSAWObQ==", + "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.1", "@babel/helper-create-class-features-plugin": "^7.27.1", @@ -1451,6 +1375,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.27.1.tgz", "integrity": "sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -1480,6 +1405,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.27.1.tgz", "integrity": "sha512-p9+Vl3yuHPmkirRrg021XiP+EETmPMQTLr6Ayjj85RLNEbb3Eya/4VI0vAdzQG9SEAl2Lnt7fy5lZyMzjYoZQQ==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -1494,6 +1420,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.27.1.tgz", "integrity": "sha512-2KH4LWGSrJIkVf5tSiBFYuXDAoWRq2MMwgivCf+93dd0GQi8RXLjKA/0EvRnVV5G0hrHczsquXuD01L8s6dmBw==", + "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.1", "@babel/helper-module-imports": "^7.27.1", @@ -1512,6 +1439,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.27.1.tgz", "integrity": "sha512-ykDdF5yI4f1WrAolLqeF3hmYU12j9ntLQl/AOG1HAS21jxyg1Q0/J/tpREuYLfatGdGmXp/3yS0ZA76kOlVq9Q==", + "dev": true, "dependencies": { "@babel/plugin-transform-react-jsx": "^7.27.1" }, @@ -1526,6 +1454,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.27.1.tgz", "integrity": "sha512-JfuinvDOsD9FVMTHpzA/pBLisxpv1aSf+OIV8lgH3MuWrks19R27e6a6DipIg4aX1Zm9Wpb04p8wljfKrVSnPA==", + "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1" @@ -1541,6 +1470,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.27.1.tgz", "integrity": "sha512-B19lbbL7PMrKr52BNPjCqg1IyNUIjTcxKj8uX9zHO+PmWN93s19NDr/f69mIkEp2x9nmDJ08a7lgHaTTzvW7mw==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -1555,6 +1485,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.27.1.tgz", "integrity": "sha512-TtEciroaiODtXvLZv4rmfMhkCv8jx3wgKpL68PuiPh2M4fvz5jhsA7697N1gMvkvr/JTF13DrFYyEbY9U7cVPA==", + "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1" @@ -1570,6 +1501,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.27.1.tgz", "integrity": "sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -1617,6 +1549,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.27.1.tgz", "integrity": "sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -1631,6 +1564,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.27.1.tgz", "integrity": "sha512-kpb3HUqaILBJcRFVhFUs6Trdd4mkrzcGXss+6/mxUd273PfbWqSDHRzMT2234gIg2QYfAjvXLSquP1xECSg09Q==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" @@ -1646,6 +1580,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.27.1.tgz", "integrity": "sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -1660,6 +1595,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.27.1.tgz", "integrity": "sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -1674,6 +1610,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.27.1.tgz", "integrity": "sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -1688,6 +1625,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.27.1.tgz", "integrity": "sha512-Q5sT5+O4QUebHdbwKedFBEwRLb02zJ7r4A5Gg2hUoLuU3FjdMcyqcywqUrLCaDsFCxzokf7u9kuy7qz51YUuAg==", + "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.1", "@babel/helper-create-class-features-plugin": "^7.27.1", @@ -1706,6 +1644,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.27.1.tgz", "integrity": "sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, @@ -1720,6 +1659,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.27.1.tgz", "integrity": "sha512-uW20S39PnaTImxp39O5qFlHLS9LJEmANjMG7SxIhap8rCHqu0Ik+tLEPX5DKmHn6CsWQ7j3lix2tFOa5YtL12Q==", + "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1" @@ -1735,6 +1675,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.27.1.tgz", "integrity": "sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw==", + "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1" @@ -1750,6 +1691,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.27.1.tgz", "integrity": "sha512-EtkOujbc4cgvb0mlpQefi4NTPBzhSIevblFevACNLUspmrALgmEBdL/XfnyyITfd8fKBZrZys92zOWcik7j9Tw==", + "dev": true, "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1" @@ -1765,6 +1707,7 @@ "version": "7.27.2", "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.27.2.tgz", "integrity": "sha512-Ma4zSuYSlGNRlCLO+EAzLnCmJK2vdstgv+n7aUP+/IKZrOfWHOJVdSJtuub8RzHTj3ahD37k5OKJWvzf16TQyQ==", + "dev": true, "dependencies": { "@babel/compat-data": "^7.27.2", "@babel/helper-compilation-targets": "^7.27.2", @@ -1847,6 +1790,7 @@ "version": "7.21.0-placeholder-for-preset-env.2", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "dev": true, "engines": { "node": ">=6.9.0" }, @@ -1858,6 +1802,7 @@ "version": "0.11.1", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.11.1.tgz", "integrity": "sha512-yGCqvBT4rwMczo28xkH/noxJ6MZ4nJfkVYdoDaC/utLtWrXxv27HVrzAeSbqR8SxDsp46n0YF47EbHoixy6rXQ==", + "dev": true, "dependencies": { "@babel/helper-define-polyfill-provider": "^0.6.3", "core-js-compat": "^3.40.0" @@ -1870,6 +1815,7 @@ "version": "0.1.6-no-external-plugins", "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", "@babel/types": "^7.4.4", @@ -1883,6 +1829,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.27.1.tgz", "integrity": "sha512-oJHWh2gLhU9dW9HHr42q0cI0/iHHXTLGe39qvpAZZzagHy0MzYLCnCVV0symeRvzmjHyVU7mw2K06E6u/JwbhA==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-validator-option": "^7.27.1", @@ -1902,6 +1849,7 @@ "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.27.1.tgz", "integrity": "sha512-l7WfQfX0WK4M0v2RudjuQK4u99BS6yLHYEmdtVPP7lKV013zr9DygFuWNlnbvQ9LR+LS0Egz/XAvGx5U9MX0fQ==", + "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-validator-option": "^7.27.1", @@ -1916,24 +1864,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/register": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.27.1.tgz", - "integrity": "sha512-K13lQpoV54LATKkzBpBAEu1GGSIRzxR9f4IN4V8DCDgiUMo2UDGagEZr3lPeVNJPLkWUi5JE4hCHKneVTwQlYQ==", - "dependencies": { - "clone-deep": "^4.0.1", - "find-cache-dir": "^2.0.0", - "make-dir": "^2.1.0", - "pirates": "^4.0.6", - "source-map-support": "^0.5.16" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/runtime": { "version": "7.7.2", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.7.2.tgz", @@ -2076,147 +2006,34 @@ "resolved": "https://registry.npmjs.org/@date-fns/tz/-/tz-1.2.0.tgz", "integrity": "sha512-LBrd7MiJZ9McsOgxqWX7AaxrDjcFVjWH/tIKJd7pnR7McaslGYOP1QmmiBXdJH/H/yLCT+rcQ7FaPBUxRGUtrg==" }, - "node_modules/@devtools-ds/object-inspector": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@devtools-ds/object-inspector/-/object-inspector-1.2.1.tgz", - "integrity": "sha512-nrAVVj4c4Iv9958oE4HA7Mk6T+4Mn/4xBRlFDeX4Ps6SMzsqO8bKhw/y6+bOfNyb/TYHmC0/pnPS68GDVZcg5Q==", - "dependencies": { - "@babel/runtime": "7.7.2", - "@devtools-ds/object-parser": "^1.2.1", - "@devtools-ds/themes": "^1.2.1", - "@devtools-ds/tree": "^1.2.1", - "clsx": "1.1.0" - }, - "peerDependencies": { - "react": ">= 16.8.6" - } - }, - "node_modules/@devtools-ds/object-inspector/node_modules/clsx": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.0.tgz", - "integrity": "sha512-3avwM37fSK5oP6M5rQ9CNe99lwxhXDOeSWVPAOYF6OazUTgZCMb0yWlJpmdD74REy1gkEaFiub2ULv4fq9GUhA==", + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "dev": true, "engines": { - "node": ">=6" - } - }, - "node_modules/@devtools-ds/object-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@devtools-ds/object-parser/-/object-parser-1.2.1.tgz", - "integrity": "sha512-6qB+THhQfJqXyHn8wpJ1KFxXcbpLTlRyCVmkelhr0c1+MPLZcC+0XJxpVZ1AOEXPa6CWVZThBYSCvnYQEvfCqw==", - "dependencies": { - "@babel/runtime": "~7.5.4" - } - }, - "node_modules/@devtools-ds/object-parser/node_modules/@babel/runtime": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.5.5.tgz", - "integrity": "sha512-28QvEGyQyNkB0/m2B4FU7IEZGK2NUrcMtT6BZEFALTguLk+AUT6ofsHtPk5QyjAdUkpMJ+/Em+quwz4HOt30AQ==", - "dependencies": { - "regenerator-runtime": "^0.13.2" - } - }, - "node_modules/@devtools-ds/themes": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@devtools-ds/themes/-/themes-1.2.1.tgz", - "integrity": "sha512-4/KFsHnokGxUq8CSCchINcVBb6fQ74HtEfNtMuitGtGg3VCRV0kaVSOsz6wzShzhLEaVLd5coSRQKaZj7yx72w==", - "dependencies": { - "@babel/runtime": "~7.5.4", - "@design-systems/utils": "2.12.0", - "clsx": "1.1.0" - }, - "peerDependencies": { - "react": ">= 16.8.6" - } - }, - "node_modules/@devtools-ds/themes/node_modules/@babel/runtime": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.5.5.tgz", - "integrity": "sha512-28QvEGyQyNkB0/m2B4FU7IEZGK2NUrcMtT6BZEFALTguLk+AUT6ofsHtPk5QyjAdUkpMJ+/Em+quwz4HOt30AQ==", - "dependencies": { - "regenerator-runtime": "^0.13.2" + "node": ">=10.0.0" } }, - "node_modules/@devtools-ds/themes/node_modules/@design-systems/utils": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/@design-systems/utils/-/utils-2.12.0.tgz", - "integrity": "sha512-Y/d2Zzr+JJfN6u1gbuBUb1ufBuLMJJRZQk+dRmw8GaTpqKx5uf7cGUYGTwN02dIb3I+Tf+cW8jcGBTRiFxdYFg==", + "node_modules/@emotion/babel-plugin": { + "version": "11.13.5", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz", + "integrity": "sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==", "dependencies": { - "@babel/runtime": "^7.11.2", - "clsx": "^1.0.4", - "focus-lock": "^0.8.0", - "react-merge-refs": "^1.0.0" - }, - "peerDependencies": { - "@types/react": "*", - "react": ">= 16.8.6", - "react-dom": ">= 16.8.6" + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/serialize": "^1.3.3", + "babel-plugin-macros": "^3.1.0", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^4.0.0", + "find-root": "^1.1.0", + "source-map": "^0.5.7", + "stylis": "4.2.0" } }, - "node_modules/@devtools-ds/themes/node_modules/@design-systems/utils/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/@devtools-ds/themes/node_modules/clsx": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.0.tgz", - "integrity": "sha512-3avwM37fSK5oP6M5rQ9CNe99lwxhXDOeSWVPAOYF6OazUTgZCMb0yWlJpmdD74REy1gkEaFiub2ULv4fq9GUhA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/@devtools-ds/tree": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@devtools-ds/tree/-/tree-1.2.1.tgz", - "integrity": "sha512-2ZHG28oWJno0gD+20EoSJO0yffm6JS5r7YzYhGMkrnLGvcCRZuwXSxMmIshSPLIR0cjidiAfGCqsrigHIR4ZQA==", - "dependencies": { - "@babel/runtime": "7.7.2", - "@devtools-ds/themes": "^1.2.1", - "clsx": "1.1.0" - }, - "peerDependencies": { - "react": ">= 16.8.6" - } - }, - "node_modules/@devtools-ds/tree/node_modules/clsx": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.0.tgz", - "integrity": "sha512-3avwM37fSK5oP6M5rQ9CNe99lwxhXDOeSWVPAOYF6OazUTgZCMb0yWlJpmdD74REy1gkEaFiub2ULv4fq9GUhA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/@discoveryjs/json-ext": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", - "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", - "dev": true, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/@emotion/babel-plugin": { - "version": "11.13.5", - "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz", - "integrity": "sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==", - "dependencies": { - "@babel/helper-module-imports": "^7.16.7", - "@babel/runtime": "^7.18.3", - "@emotion/hash": "^0.9.2", - "@emotion/memoize": "^0.9.0", - "@emotion/serialize": "^1.3.3", - "babel-plugin-macros": "^3.1.0", - "convert-source-map": "^1.5.0", - "escape-string-regexp": "^4.0.0", - "find-root": "^1.1.0", - "source-map": "^0.5.7", - "stylis": "4.2.0" - } - }, - "node_modules/@emotion/babel-plugin/node_modules/@babel/runtime": { + "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==", @@ -2362,7 +2179,7 @@ "version": "4.7.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", - "devOptional": true, + "dev": true, "dependencies": { "eslint-visitor-keys": "^3.4.3" }, @@ -2380,7 +2197,7 @@ "version": "3.4.3", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "devOptional": true, + "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -2392,7 +2209,7 @@ "version": "4.12.1", "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", - "devOptional": true, + "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } @@ -2401,7 +2218,7 @@ "version": "2.1.4", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", - "devOptional": true, + "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", @@ -2424,13 +2241,13 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "devOptional": true + "dev": true }, "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "devOptional": true, + "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -2440,7 +2257,7 @@ "version": "13.24.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "devOptional": true, + "dev": true, "dependencies": { "type-fest": "^0.20.2" }, @@ -2455,7 +2272,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "devOptional": true, + "dev": true, "dependencies": { "argparse": "^2.0.1" }, @@ -2467,7 +2284,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "devOptional": true, + "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -2479,7 +2296,7 @@ "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "devOptional": true, + "dev": true, "engines": { "node": ">=10" }, @@ -2491,7 +2308,7 @@ "version": "8.57.1", "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", - "devOptional": true, + "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } @@ -2668,7 +2485,7 @@ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", "deprecated": "Use @eslint/config-array instead", - "devOptional": true, + "dev": true, "dependencies": { "@humanwhocodes/object-schema": "^2.0.3", "debug": "^4.3.1", @@ -2682,7 +2499,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "devOptional": true, + "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -2692,7 +2509,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "devOptional": true, + "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -2704,7 +2521,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "devOptional": true, + "dev": true, "engines": { "node": ">=12.22" }, @@ -2718,7 +2535,7 @@ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", "deprecated": "Use @eslint/object-schema instead", - "devOptional": true + "dev": true }, "node_modules/@inquirer/figures": { "version": "1.0.11", @@ -3312,6 +3129,7 @@ "version": "0.3.6", "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "dev": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25" @@ -3647,6 +3465,7 @@ "version": "2.5.1", "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz", "integrity": "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==", + "dev": true, "hasInstallScript": true, "optional": true, "dependencies": { @@ -3685,6 +3504,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "android" @@ -3704,6 +3524,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "darwin" @@ -3723,6 +3544,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "darwin" @@ -3742,6 +3564,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "freebsd" @@ -3761,6 +3584,7 @@ "cpu": [ "arm" ], + "dev": true, "optional": true, "os": [ "linux" @@ -3780,6 +3604,7 @@ "cpu": [ "arm" ], + "dev": true, "optional": true, "os": [ "linux" @@ -3799,6 +3624,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -3818,6 +3644,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -3837,6 +3664,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -3856,6 +3684,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -3875,6 +3704,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "win32" @@ -3894,6 +3724,7 @@ "cpu": [ "ia32" ], + "dev": true, "optional": true, "os": [ "win32" @@ -3913,6 +3744,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "win32" @@ -3935,14 +3767,6 @@ "third-party-web": "latest" } }, - "node_modules/@paypal/paypal-js": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/@paypal/paypal-js/-/paypal-js-5.1.6.tgz", - "integrity": "sha512-1upF06pv0AUtTftRVSra44p8ibqGa3ruKLArvdhpZla25zcrND7R+nDUIMrJ0iteVYZowhujZStFs6NoruExfg==", - "dependencies": { - "promise-polyfill": "^8.3.0" - } - }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -4087,117 +3911,13 @@ } }, "node_modules/@remix-run/router": { - "version": "1.23.0", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.0.tgz", - "integrity": "sha512-O3rHJzAQKamUz1fvE0Qaw0xSFqsA/yafi2iqeE0pvdFtCO1viYx8QL6f3Ln/aCCTLxs68SLf0KPM9eSeM8yBnA==", + "version": "1.23.2", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.2.tgz", + "integrity": "sha512-Ic6m2U/rMjTkhERIa/0ZtXJP17QUi2CbWE7cqx4J58M8aA3QTfW+2UlQ4psvTX9IO1RfNVhK3pcpdjej7L+t2w==", "engines": { "node": ">=14.0.0" } }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.34.9", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.9.tgz", - "integrity": "sha512-0CY3/K54slrzLDjOA7TOjN1NuLKERBgk9nY5V34mhmuu673YNb+7ghaDUs6N0ujXR7fz5XaS5Aa6d2TNxZd0OQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "darwin" - ], - "peer": true - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.34.9", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.9.tgz", - "integrity": "sha512-eOojSEAi/acnsJVYRxnMkPFqcxSMFfrw7r2iD9Q32SGkb/Q9FpUY1UlAu1DH9T7j++gZ0lHjnm4OyH2vCI7l7Q==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" - ], - "peer": true - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.34.9", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.9.tgz", - "integrity": "sha512-6TZjPHjKZUQKmVKMUowF3ewHxctrRR09eYyvT5eFv8w/fXarEra83A2mHTVJLA5xU91aCNOUnM+DWFMSbQ0Nxw==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "peer": true - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.34.9", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.9.tgz", - "integrity": "sha512-LD2fytxZJZ6xzOKnMbIpgzFOuIKlxVOpiMAXawsAZ2mHBPEYOnLRK5TTEsID6z4eM23DuO88X0Tq1mErHMVq0A==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "peer": true - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.34.9", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.9.tgz", - "integrity": "sha512-FwBHNSOjUTQLP4MG7y6rR6qbGw4MFeQnIBrMe161QGaQoBQLqSUEKlHIiVgF3g/mb3lxlxzJOpIBhaP+C+KP2A==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "peer": true - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.34.9", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.9.tgz", - "integrity": "sha512-cYRpV4650z2I3/s6+5/LONkjIz8MBeqrk+vPXV10ORBnshpn8S32bPqQ2Utv39jCiDcO2eJTuSlPXpnvmaIgRA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "peer": true - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.34.9", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.9.tgz", - "integrity": "sha512-z4mQK9dAN6byRA/vsSgQiPeuO63wdiDxZ9yg9iyX2QTzKuQM7T4xlBoeUP/J8uiFkqxkcWndWi+W7bXdPbt27Q==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "win32" - ], - "peer": true - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.34.9", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.9.tgz", - "integrity": "sha512-AyleYRPU7+rgkMWbEh71fQlrzRfeP6SyMnRf9XX4fCdDPAJumdSBqYEcWPMzVQ4ScAl7E4oFfK0GUVn77xSwbw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "win32" - ], - "peer": true - }, "node_modules/@rtsao/scc": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", @@ -4411,1093 +4131,100 @@ "@sinonjs/commons": "^3.0.0" } }, - "node_modules/@stencil/core": { - "version": "4.38.3", - "resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.38.3.tgz", - "integrity": "sha512-rSDzGUfi58X8K79ySjlM6KlY+mq7D+ittzgNAdYHcsXHc70sBpdatFhnbOg25uVDiMf7xRAH9slP38pPdXnZOQ==", - "peer": true, - "bin": { - "stencil": "bin/stencil" - }, + "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", + "integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==", + "dev": true, "engines": { - "node": ">=16.0.0", - "npm": ">=7.10.0" + "node": ">=14" }, - "optionalDependencies": { - "@rollup/rollup-darwin-arm64": "4.34.9", - "@rollup/rollup-darwin-x64": "4.34.9", - "@rollup/rollup-linux-arm64-gnu": "4.34.9", - "@rollup/rollup-linux-arm64-musl": "4.34.9", - "@rollup/rollup-linux-x64-gnu": "4.34.9", - "@rollup/rollup-linux-x64-musl": "4.34.9", - "@rollup/rollup-win32-arm64-msvc": "4.34.9", - "@rollup/rollup-win32-x64-msvc": "4.34.9" - } - }, - "node_modules/@stencil/store": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@stencil/store/-/store-2.1.3.tgz", - "integrity": "sha512-qeWJisbcafVcAhFZidiqK82ULlgBzPNEhlsm0PZ54FHkNTIomxns2MiI7IOGUvGPumK1WK7KzajRomHHc8SYag==", - "engines": { - "node": ">=18.0.0", - "npm": ">=6.0.0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" }, "peerDependencies": { - "@stencil/core": ">=2.0.0 || >=3.0.0 || >= 4.0.0-beta.0 || >= 4.0.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@storybook/addon-a11y": { - "version": "6.5.16", - "resolved": "https://registry.npmjs.org/@storybook/addon-a11y/-/addon-a11y-6.5.16.tgz", - "integrity": "sha512-/e9s34o+TmEhy+Q3/YzbRJ5AJ/Sy0gjZXlvsCrcRpiQLdt5JRbN8s+Lbn/FWxy8U1Tb1wlLYlqjJ+fYi5RrS3A==", - "dependencies": { - "@storybook/addons": "6.5.16", - "@storybook/api": "6.5.16", - "@storybook/channels": "6.5.16", - "@storybook/client-logger": "6.5.16", - "@storybook/components": "6.5.16", - "@storybook/core-events": "6.5.16", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/theming": "6.5.16", - "axe-core": "^4.2.0", - "core-js": "^3.8.2", - "global": "^4.4.0", - "lodash": "^4.17.21", - "react-sizeme": "^3.0.1", - "regenerator-runtime": "^0.13.7", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" + "node_modules/@svgr/babel-plugin-remove-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==", + "dev": true, + "engines": { + "node": ">=14" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" + "type": "github", + "url": "https://github.com/sponsors/gregberge" }, "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "react": { - "optional": true - }, - "react-dom": { - "optional": true - } + "@babel/core": "^7.0.0-0" } }, - "node_modules/@storybook/addon-interactions": { - "version": "6.5.16", - "resolved": "https://registry.npmjs.org/@storybook/addon-interactions/-/addon-interactions-6.5.16.tgz", - "integrity": "sha512-DdTtyp3DgB/SpbM1GQgMnuSEBCkadxmj1mUcPk+Wp2iY+fDwsuoRDkr1H9Oe7IvlBKe7ciR79LEjoaABXNdw4w==", - "dependencies": { - "@devtools-ds/object-inspector": "^1.1.2", - "@storybook/addons": "6.5.16", - "@storybook/api": "6.5.16", - "@storybook/client-logger": "6.5.16", - "@storybook/components": "6.5.16", - "@storybook/core-common": "6.5.16", - "@storybook/core-events": "6.5.16", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/instrumenter": "6.5.16", - "@storybook/theming": "6.5.16", - "core-js": "^3.8.2", - "global": "^4.4.0", - "jest-mock": "^27.0.6", - "polished": "^4.2.2", - "ts-dedent": "^2.2.0" + "node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz", + "integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==", + "dev": true, + "engines": { + "node": ">=14" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" + "type": "github", + "url": "https://github.com/sponsors/gregberge" }, "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "react": { - "optional": true - }, - "react-dom": { - "optional": true - } + "@babel/core": "^7.0.0-0" } }, - "node_modules/@storybook/addons": { - "version": "6.5.16", - "resolved": "https://registry.npmjs.org/@storybook/addons/-/addons-6.5.16.tgz", - "integrity": "sha512-p3DqQi+8QRL5k7jXhXmJZLsE/GqHqyY6PcoA1oNTJr0try48uhTGUOYkgzmqtDaa/qPFO5LP+xCPzZXckGtquQ==", - "dependencies": { - "@storybook/api": "6.5.16", - "@storybook/channels": "6.5.16", - "@storybook/client-logger": "6.5.16", - "@storybook/core-events": "6.5.16", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/router": "6.5.16", - "@storybook/theming": "6.5.16", - "@types/webpack-env": "^1.16.0", - "core-js": "^3.8.2", - "global": "^4.4.0", - "regenerator-runtime": "^0.13.7" + "node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz", + "integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==", + "dev": true, + "engines": { + "node": ">=14" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" + "type": "github", + "url": "https://github.com/sponsors/gregberge" }, "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@storybook/api": { - "version": "6.5.16", - "resolved": "https://registry.npmjs.org/@storybook/api/-/api-6.5.16.tgz", - "integrity": "sha512-HOsuT8iomqeTMQJrRx5U8nsC7lJTwRr1DhdD0SzlqL4c80S/7uuCy4IZvOt4sYQjOzW5fOo/kamcoBXyLproTA==", - "dependencies": { - "@storybook/channels": "6.5.16", - "@storybook/client-logger": "6.5.16", - "@storybook/core-events": "6.5.16", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/router": "6.5.16", - "@storybook/semver": "^7.3.2", - "@storybook/theming": "6.5.16", - "core-js": "^3.8.2", - "fast-deep-equal": "^3.1.3", - "global": "^4.4.0", - "lodash": "^4.17.21", - "memoizerific": "^1.11.3", - "regenerator-runtime": "^0.13.7", - "store2": "^2.12.0", - "telejson": "^6.0.8", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" + "node_modules/@svgr/babel-plugin-svg-dynamic-title": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz", + "integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==", + "dev": true, + "engines": { + "node": ">=14" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" + "type": "github", + "url": "https://github.com/sponsors/gregberge" }, "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@storybook/channels": { - "version": "6.5.16", - "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-6.5.16.tgz", - "integrity": "sha512-VylzaWQZaMozEwZPJdyJoz+0jpDa8GRyaqu9TGG6QGv+KU5POoZaGLDkRE7TzWkyyP0KQLo80K99MssZCpgSeg==", - "dependencies": { - "core-js": "^3.8.2", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2" + "node_modules/@svgr/babel-plugin-svg-em-dimensions": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz", + "integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==", + "dev": true, + "engines": { + "node": ">=14" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/client-logger": { - "version": "6.5.16", - "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.5.16.tgz", - "integrity": "sha512-pxcNaCj3ItDdicPTXTtmYJE3YC1SjxFrBmHcyrN+nffeNyiMuViJdOOZzzzucTUG0wcOOX8jaSyak+nnHg5H1Q==", - "dependencies": { - "core-js": "^3.8.2", - "global": "^4.4.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/components": { - "version": "6.5.16", - "resolved": "https://registry.npmjs.org/@storybook/components/-/components-6.5.16.tgz", - "integrity": "sha512-LzBOFJKITLtDcbW9jXl0/PaG+4xAz25PK8JxPZpIALbmOpYWOAPcO6V9C2heX6e6NgWFMUxjplkULEk9RCQMNA==", - "dependencies": { - "@storybook/client-logger": "6.5.16", - "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/theming": "6.5.16", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "qs": "^6.10.0", - "regenerator-runtime": "^0.13.7", - "util-deprecate": "^1.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/core-common": { - "version": "6.5.16", - "resolved": "https://registry.npmjs.org/@storybook/core-common/-/core-common-6.5.16.tgz", - "integrity": "sha512-2qtnKP3TTOzt2cp6LXKRTh7XrI9z5VanMnMTgeoFcA5ebnndD4V6BExQUdYPClE/QooLx6blUWNgS9dFEpjSqQ==", - "dependencies": { - "@babel/core": "^7.12.10", - "@babel/plugin-proposal-class-properties": "^7.12.1", - "@babel/plugin-proposal-decorators": "^7.12.12", - "@babel/plugin-proposal-export-default-from": "^7.12.1", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.12.1", - "@babel/plugin-proposal-object-rest-spread": "^7.12.1", - "@babel/plugin-proposal-optional-chaining": "^7.12.7", - "@babel/plugin-proposal-private-methods": "^7.12.1", - "@babel/plugin-proposal-private-property-in-object": "^7.12.1", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-transform-arrow-functions": "^7.12.1", - "@babel/plugin-transform-block-scoping": "^7.12.12", - "@babel/plugin-transform-classes": "^7.12.1", - "@babel/plugin-transform-destructuring": "^7.12.1", - "@babel/plugin-transform-for-of": "^7.12.1", - "@babel/plugin-transform-parameters": "^7.12.1", - "@babel/plugin-transform-shorthand-properties": "^7.12.1", - "@babel/plugin-transform-spread": "^7.12.1", - "@babel/preset-env": "^7.12.11", - "@babel/preset-react": "^7.12.10", - "@babel/preset-typescript": "^7.12.7", - "@babel/register": "^7.12.1", - "@storybook/node-logger": "6.5.16", - "@storybook/semver": "^7.3.2", - "@types/node": "^14.0.10 || ^16.0.0", - "@types/pretty-hrtime": "^1.0.0", - "babel-loader": "^8.0.0", - "babel-plugin-macros": "^3.0.1", - "babel-plugin-polyfill-corejs3": "^0.1.0", - "chalk": "^4.1.0", - "core-js": "^3.8.2", - "express": "^4.17.1", - "file-system-cache": "^1.0.5", - "find-up": "^5.0.0", - "fork-ts-checker-webpack-plugin": "^6.0.4", - "fs-extra": "^9.0.1", - "glob": "^7.1.6", - "handlebars": "^4.7.7", - "interpret": "^2.2.0", - "json5": "^2.2.3", - "lazy-universal-dotenv": "^3.0.1", - "picomatch": "^2.3.0", - "pkg-dir": "^5.0.0", - "pretty-hrtime": "^1.0.3", - "resolve-from": "^5.0.0", - "slash": "^3.0.0", - "telejson": "^6.0.8", - "ts-dedent": "^2.0.0", - "util-deprecate": "^1.0.2", - "webpack": "4" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@storybook/core-common/node_modules/@webassemblyjs/ast": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", - "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", - "dependencies": { - "@webassemblyjs/helper-module-context": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/wast-parser": "1.9.0" - } - }, - "node_modules/@storybook/core-common/node_modules/@webassemblyjs/helper-api-error": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", - "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==" - }, - "node_modules/@storybook/core-common/node_modules/@webassemblyjs/helper-buffer": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz", - "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==" - }, - "node_modules/@storybook/core-common/node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", - "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==" - }, - "node_modules/@storybook/core-common/node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz", - "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==", - "dependencies": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-buffer": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/wasm-gen": "1.9.0" - } - }, - "node_modules/@storybook/core-common/node_modules/@webassemblyjs/ieee754": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz", - "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==", - "dependencies": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "node_modules/@storybook/core-common/node_modules/@webassemblyjs/leb128": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz", - "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==", - "dependencies": { - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@storybook/core-common/node_modules/@webassemblyjs/utf8": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz", - "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==" - }, - "node_modules/@storybook/core-common/node_modules/@webassemblyjs/wasm-edit": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz", - "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==", - "dependencies": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-buffer": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/helper-wasm-section": "1.9.0", - "@webassemblyjs/wasm-gen": "1.9.0", - "@webassemblyjs/wasm-opt": "1.9.0", - "@webassemblyjs/wasm-parser": "1.9.0", - "@webassemblyjs/wast-printer": "1.9.0" - } - }, - "node_modules/@storybook/core-common/node_modules/@webassemblyjs/wasm-gen": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz", - "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==", - "dependencies": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/ieee754": "1.9.0", - "@webassemblyjs/leb128": "1.9.0", - "@webassemblyjs/utf8": "1.9.0" - } - }, - "node_modules/@storybook/core-common/node_modules/@webassemblyjs/wasm-opt": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz", - "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==", - "dependencies": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-buffer": "1.9.0", - "@webassemblyjs/wasm-gen": "1.9.0", - "@webassemblyjs/wasm-parser": "1.9.0" - } - }, - "node_modules/@storybook/core-common/node_modules/@webassemblyjs/wasm-parser": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz", - "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==", - "dependencies": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-api-error": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/ieee754": "1.9.0", - "@webassemblyjs/leb128": "1.9.0", - "@webassemblyjs/utf8": "1.9.0" - } - }, - "node_modules/@storybook/core-common/node_modules/@webassemblyjs/wast-printer": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", - "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", - "dependencies": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/wast-parser": "1.9.0", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@storybook/core-common/node_modules/acorn": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", - "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/@storybook/core-common/node_modules/braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dependencies": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@storybook/core-common/node_modules/braces/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@storybook/core-common/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "node_modules/@storybook/core-common/node_modules/enhanced-resolve": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz", - "integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==", - "dependencies": { - "graceful-fs": "^4.1.2", - "memory-fs": "^0.5.0", - "tapable": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@storybook/core-common/node_modules/enhanced-resolve/node_modules/memory-fs": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", - "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", - "dependencies": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" - }, - "engines": { - "node": ">=4.3.0 <5.0.0 || >=5.10" - } - }, - "node_modules/@storybook/core-common/node_modules/eslint-scope": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", - "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", - "dependencies": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/@storybook/core-common/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/@storybook/core-common/node_modules/fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", - "dependencies": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@storybook/core-common/node_modules/fill-range/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@storybook/core-common/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@storybook/core-common/node_modules/is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@storybook/core-common/node_modules/is-number/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@storybook/core-common/node_modules/is-wsl": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", - "integrity": "sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/@storybook/core-common/node_modules/loader-runner": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", - "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", - "engines": { - "node": ">=4.3.0 <5.0.0 || >=5.10" - } - }, - "node_modules/@storybook/core-common/node_modules/loader-utils": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz", - "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/@storybook/core-common/node_modules/loader-utils/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/@storybook/core-common/node_modules/micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@storybook/core-common/node_modules/schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", - "dependencies": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" - }, - "engines": { - "node": ">= 4" - } - }, - "node_modules/@storybook/core-common/node_modules/serialize-javascript": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", - "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/@storybook/core-common/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@storybook/core-common/node_modules/terser": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.1.tgz", - "integrity": "sha512-4GnLC0x667eJG0ewJTa6z/yXrbLGv80D9Ru6HIpCQmO+Q4PfEtBFi0ObSckqwL6VyQv/7ENJieXHo2ANmdQwgw==", - "dependencies": { - "commander": "^2.20.0", - "source-map": "~0.6.1", - "source-map-support": "~0.5.12" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@storybook/core-common/node_modules/terser-webpack-plugin": { - "version": "1.4.6", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.6.tgz", - "integrity": "sha512-2lBVf/VMVIddjSn3GqbT90GvIJ/eYXJkt8cTzU7NbjKqK8fwv18Ftr4PlbF46b/e88743iZFL5Dtr/rC4hjIeA==", - "dependencies": { - "cacache": "^12.0.2", - "find-cache-dir": "^2.1.0", - "is-wsl": "^1.1.0", - "schema-utils": "^1.0.0", - "serialize-javascript": "^4.0.0", - "source-map": "^0.6.1", - "terser": "^4.1.2", - "webpack-sources": "^1.4.0", - "worker-farm": "^1.7.0" - }, - "engines": { - "node": ">= 6.9.0" - }, - "peerDependencies": { - "webpack": "^4.0.0" - } - }, - "node_modules/@storybook/core-common/node_modules/to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", - "dependencies": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@storybook/core-common/node_modules/watchpack": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz", - "integrity": "sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==", - "dependencies": { - "graceful-fs": "^4.1.2", - "neo-async": "^2.5.0" - }, - "optionalDependencies": { - "chokidar": "^3.4.1", - "watchpack-chokidar2": "^2.0.1" - } - }, - "node_modules/@storybook/core-common/node_modules/webpack": { - "version": "4.47.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.47.0.tgz", - "integrity": "sha512-td7fYwgLSrky3fI1EuU5cneU4+pbH6GgOfuKNS1tNPcfdGinGELAqsb/BP4nnvZyKSG2i/xFGU7+n2PvZA8HJQ==", - "dependencies": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-module-context": "1.9.0", - "@webassemblyjs/wasm-edit": "1.9.0", - "@webassemblyjs/wasm-parser": "1.9.0", - "acorn": "^6.4.1", - "ajv": "^6.10.2", - "ajv-keywords": "^3.4.1", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^4.5.0", - "eslint-scope": "^4.0.3", - "json-parse-better-errors": "^1.0.2", - "loader-runner": "^2.4.0", - "loader-utils": "^1.2.3", - "memory-fs": "^0.4.1", - "micromatch": "^3.1.10", - "mkdirp": "^0.5.3", - "neo-async": "^2.6.1", - "node-libs-browser": "^2.2.1", - "schema-utils": "^1.0.0", - "tapable": "^1.1.3", - "terser-webpack-plugin": "^1.4.3", - "watchpack": "^1.7.4", - "webpack-sources": "^1.4.1" - }, - "bin": { - "webpack": "bin/webpack.js" - }, - "engines": { - "node": ">=6.11.5" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - }, - "webpack-command": { - "optional": true - } - } - }, - "node_modules/@storybook/core-common/node_modules/webpack-sources": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", - "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", - "dependencies": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" - } - }, - "node_modules/@storybook/core-events": { - "version": "6.5.16", - "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-6.5.16.tgz", - "integrity": "sha512-qMZQwmvzpH5F2uwNUllTPg6eZXr2OaYZQRRN8VZJiuorZzDNdAFmiVWMWdkThwmyLEJuQKXxqCL8lMj/7PPM+g==", - "dependencies": { - "core-js": "^3.8.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/csf": { - "version": "0.0.2--canary.4566f4d.1", - "resolved": "https://registry.npmjs.org/@storybook/csf/-/csf-0.0.2--canary.4566f4d.1.tgz", - "integrity": "sha512-9OVvMVh3t9znYZwb0Svf/YQoxX2gVOeQTGe2bses2yj+a3+OJnCrUF3/hGv6Em7KujtOdL2LL+JnG49oMVGFgQ==", - "dependencies": { - "lodash": "^4.17.15" - } - }, - "node_modules/@storybook/instrumenter": { - "version": "6.5.16", - "resolved": "https://registry.npmjs.org/@storybook/instrumenter/-/instrumenter-6.5.16.tgz", - "integrity": "sha512-q8/GaBk8PA/cL7m5OW+ec5t63+Zja9YvYSPGXrYtW17koSv7OnNPmk6RvI7tIHHO0mODBYnaHjF4zQfEGoyR5Q==", - "dependencies": { - "@storybook/addons": "6.5.16", - "@storybook/client-logger": "6.5.16", - "@storybook/core-events": "6.5.16", - "core-js": "^3.8.2", - "global": "^4.4.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/node-logger": { - "version": "6.5.16", - "resolved": "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-6.5.16.tgz", - "integrity": "sha512-YjhBKrclQtjhqFNSO+BZK+RXOx6EQypAELJKoLFaawg331e8VUfvUuRCNB3fcEWp8G9oH13PQQte0OTjLyyOYg==", - "dependencies": { - "@types/npmlog": "^4.1.2", - "chalk": "^4.1.0", - "core-js": "^3.8.2", - "npmlog": "^5.0.1", - "pretty-hrtime": "^1.0.3" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - } - }, - "node_modules/@storybook/router": { - "version": "6.5.16", - "resolved": "https://registry.npmjs.org/@storybook/router/-/router-6.5.16.tgz", - "integrity": "sha512-ZgeP8a5YV/iuKbv31V8DjPxlV4AzorRiR8OuSt/KqaiYXNXlOoQDz/qMmiNcrshrfLpmkzoq7fSo4T8lWo2UwQ==", - "dependencies": { - "@storybook/client-logger": "6.5.16", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "qs": "^6.10.0", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@storybook/semver": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/@storybook/semver/-/semver-7.3.2.tgz", - "integrity": "sha512-SWeszlsiPsMI0Ps0jVNtH64cI5c0UF3f7KgjVKJoNP30crQ6wUSddY2hsdeczZXEKVJGEn50Q60flcGsQGIcrg==", - "dependencies": { - "core-js": "^3.6.5", - "find-up": "^4.1.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@storybook/semver/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@storybook/semver/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@storybook/semver/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@storybook/semver/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@storybook/testing-library": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/@storybook/testing-library/-/testing-library-0.0.11.tgz", - "integrity": "sha512-8KbKx3s1e+uF3oWlPdyXRpZa6xtCsCHtXh1nCTisMA6P5YcSDaCg59NXIOVIQCAwKvjRomlqMJH8JL1WyOzeVg==", - "dependencies": { - "@storybook/client-logger": "^6.4.0 || >=6.5.0-0", - "@storybook/instrumenter": "^6.4.0 || >=6.5.0-0", - "@testing-library/dom": "^8.3.0", - "@testing-library/user-event": "^13.2.1", - "ts-dedent": "^2.2.0" - } - }, - "node_modules/@storybook/theming": { - "version": "6.5.16", - "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-6.5.16.tgz", - "integrity": "sha512-hNLctkjaYLRdk1+xYTkC1mg4dYz2wSv6SqbLpcKMbkPHTE0ElhddGPHQqB362md/w9emYXNkt1LSMD8Xk9JzVQ==", - "dependencies": { - "@storybook/client-logger": "6.5.16", - "core-js": "^3.8.2", - "memoizerific": "^1.11.3", - "regenerator-runtime": "^0.13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/storybook" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "node_modules/@surecart/components": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@surecart/components/-/components-1.0.0.tgz", - "integrity": "sha512-Gl6h622Ht62J3KsSNV/D/4SUPUek7YFiY/2h0d1SndDuoavJgUjAf8SA55lF6cVC89pA8vz/M3Hq2H9Usab2EA==", - "dependencies": { - "@babel/plugin-transform-react-jsx": "^7.17.3", - "@floating-ui/dom": "^0.5.0", - "@paypal/paypal-js": "^5.0.4", - "@stencil/store": "^2.0.0", - "@storybook/addon-a11y": "^6.5.6", - "@storybook/addon-interactions": "^6.5.6", - "@storybook/testing-library": "^0.0.11", - "@wordpress/api-fetch": "^6.11.0", - "@wordpress/hooks": "^3.2.1", - "@wordpress/i18n": "^4.2.3", - "@wordpress/url": "^3.1.1", - "@xstate/fsm": "^1.6.2", - "clsx": "^1.1.1", - "country-region-data": "^2.0.0", - "fuse.js": "^6.4.6", - "import": "^0.0.6", - "localized-address-format": "^1.1.0", - "sass": "^1.29.0", - "stencil-store-storage": "^0.2.0", - "stencil-wormhole": "^3.4.1" - } - }, - "node_modules/@surecart/components-react": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@surecart/components-react/-/components-react-1.0.1.tgz", - "integrity": "sha512-/Vzbf2XBIqce6uxItxepIscxVSnN5Oys+urkk3th88zi4JG5VhtW5XBEngb83IXfWyMIJFRBIszr/5I/VLJVmA==", - "dependencies": { - "@surecart/components": "^1.0.0" - }, - "peerDependencies": { - "react": "^17.0.2", - "react-dom": "^17.0.2" - } - }, - "node_modules/@surecart/components/node_modules/@floating-ui/core": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-0.7.3.tgz", - "integrity": "sha512-buc8BXHmG9l82+OQXOFU3Kr2XQx9ys01U/Q9HMIrZ300iLc8HLMgh7dcCqgYzAzf4BkoQvDcXf5Y+CuEZ5JBYg==" - }, - "node_modules/@surecart/components/node_modules/@floating-ui/dom": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-0.5.4.tgz", - "integrity": "sha512-419BMceRLq0RrmTSDxn8hf9R3VCJv2K9PUfugh5JyEFmdjzDo+e8U5EdR8nzKq8Yj1htzLm3b6eQEEam3/rrtg==", - "dependencies": { - "@floating-ui/core": "^0.7.3" - } - }, - "node_modules/@surecart/components/node_modules/clsx": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", - "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==", - "engines": { - "node": ">=6" - } - }, - "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", - "integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@svgr/babel-plugin-remove-jsx-attribute": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz", - "integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz", - "integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz", - "integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@svgr/babel-plugin-svg-dynamic-title": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz", - "integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@svgr/babel-plugin-svg-em-dimensions": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz", - "integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, "node_modules/@svgr/babel-plugin-transform-react-native-svg": { @@ -5736,55 +4463,6 @@ "react": "^18 || ^19" } }, - "node_modules/@testing-library/dom": { - "version": "8.20.1", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.20.1.tgz", - "integrity": "sha512-/DiOQ5xBxgdYRC8LNk7U+RWat0S3qRLeIw3ZIkMQ9kkVlRmwD/Eg8k8CqIpD6GW7u20JIUOfMKbxtiLutpjQ4g==", - "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/runtime": "^7.12.5", - "@types/aria-query": "^5.0.1", - "aria-query": "5.1.3", - "chalk": "^4.1.0", - "dom-accessibility-api": "^0.5.9", - "lz-string": "^1.5.0", - "pretty-format": "^27.0.2" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@testing-library/dom/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/@testing-library/user-event": { - "version": "13.5.0", - "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-13.5.0.tgz", - "integrity": "sha512-5Kwtbo3Y/NowpkbRuSepbyMFkZmHgD+vPzYB/RJ4oxt5Gj/avFFBYjhw27cqSVPVw/3a67NK1PbiIr9k4Gwmdg==", - "dependencies": { - "@babel/runtime": "^7.12.5" - }, - "engines": { - "node": ">=10", - "npm": ">=6" - }, - "peerDependencies": { - "@testing-library/dom": ">=7.21.4" - } - }, - "node_modules/@testing-library/user-event/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/@tomickigrzegorz/react-circular-progress-bar": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@tomickigrzegorz/react-circular-progress-bar/-/react-circular-progress-bar-1.1.2.tgz", @@ -5819,11 +4497,6 @@ "node": ">=10.13.0" } }, - "node_modules/@types/aria-query": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", - "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==" - }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -5973,6 +4646,7 @@ "version": "9.6.1", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", + "dev": true, "dependencies": { "@types/estree": "*", "@types/json-schema": "*" @@ -5982,6 +4656,7 @@ "version": "3.7.7", "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "dev": true, "dependencies": { "@types/eslint": "*", "@types/estree": "*" @@ -5990,7 +4665,8 @@ "node_modules/@types/estree": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", - "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==" + "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==", + "dev": true }, "node_modules/@types/express": { "version": "4.17.21", @@ -6077,20 +4753,17 @@ "@types/node": "*" } }, - "node_modules/@types/is-function": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@types/is-function/-/is-function-1.0.3.tgz", - "integrity": "sha512-/CLhCW79JUeLKznI6mbVieGbl4QU5Hfn+6udw1YHZoofASjbQ5zaP5LzAUZYDpRYEjS4/P+DhEgyJ/PQmGGTWw==" - }, "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", - "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==" + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true }, "node_modules/@types/istanbul-lib-report": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dev": true, "dependencies": { "@types/istanbul-lib-coverage": "*" } @@ -6099,6 +4772,7 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dev": true, "dependencies": { "@types/istanbul-lib-report": "*" } @@ -6117,7 +4791,8 @@ "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true }, "node_modules/@types/json5": { "version": "0.0.29", @@ -6153,9 +4828,13 @@ "dev": true }, "node_modules/@types/node": { - "version": "16.18.126", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.126.tgz", - "integrity": "sha512-OTcgaiwfGFBKacvfwuHzzn1KLxH/er8mluiy8/uM3sGXHaRe73RrSIj01jow9t4kJEW633Ov+cOexXeiApTyAw==" + "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" + } }, "node_modules/@types/node-forge": { "version": "1.3.11", @@ -6172,24 +4851,11 @@ "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", "dev": true }, - "node_modules/@types/npmlog": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@types/npmlog/-/npmlog-4.1.6.tgz", - "integrity": "sha512-0l3z16vnlJGl2Mi/rgJFrdwfLZ4jfNYgE6ZShEpjqhHuGTqdEzNles03NpYHwUMVYZa+Tj46UxKIEpE78lQ3DQ==", - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/parse-json": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==" }, - "node_modules/@types/pretty-hrtime": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@types/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", - "integrity": "sha512-nj39q0wAIdhwn7DGUyT9irmsKK1tV0bd5WFEhgpqNTMFZ8cE+jieuTphCW0tfdm47S2zVT5mr09B28b1chmQMA==" - }, "node_modules/@types/prop-types": { "version": "15.7.14", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz", @@ -6379,11 +5045,6 @@ "source-map": "^0.6.0" } }, - "node_modules/@types/webpack-env": { - "version": "1.18.8", - "resolved": "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.18.8.tgz", - "integrity": "sha512-G9eAoJRMLjcvN4I08wB5I7YofOb/kaJNd5uoCMX+LbKXTPCF+ZIHuqTnFaK9Jz1rgs035f9JUPUhNFtqgucy/A==" - }, "node_modules/@types/webpack-sources": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-3.2.3.tgz", @@ -6425,7 +5086,8 @@ "node_modules/@types/yargs-parser": { "version": "21.0.3", "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", - "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==" + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true }, "node_modules/@types/yauzl": { "version": "2.10.3", @@ -6679,12 +5341,13 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", - "devOptional": true + "dev": true }, "node_modules/@webassemblyjs/ast": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", + "dev": true, "dependencies": { "@webassemblyjs/helper-numbers": "1.13.2", "@webassemblyjs/helper-wasm-bytecode": "1.13.2" @@ -6693,83 +5356,26 @@ "node_modules/@webassemblyjs/floating-point-hex-parser": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", - "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==" + "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", + "dev": true }, "node_modules/@webassemblyjs/helper-api-error": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", - "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==" + "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", + "dev": true }, "node_modules/@webassemblyjs/helper-buffer": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", - "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==" - }, - "node_modules/@webassemblyjs/helper-code-frame": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz", - "integrity": "sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==", - "dependencies": { - "@webassemblyjs/wast-printer": "1.9.0" - } - }, - "node_modules/@webassemblyjs/helper-code-frame/node_modules/@webassemblyjs/ast": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", - "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", - "dependencies": { - "@webassemblyjs/helper-module-context": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/wast-parser": "1.9.0" - } - }, - "node_modules/@webassemblyjs/helper-code-frame/node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", - "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==" - }, - "node_modules/@webassemblyjs/helper-code-frame/node_modules/@webassemblyjs/wast-printer": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", - "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", - "dependencies": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/wast-parser": "1.9.0", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/helper-fsm": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz", - "integrity": "sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==" - }, - "node_modules/@webassemblyjs/helper-module-context": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz", - "integrity": "sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==", - "dependencies": { - "@webassemblyjs/ast": "1.9.0" - } - }, - "node_modules/@webassemblyjs/helper-module-context/node_modules/@webassemblyjs/ast": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", - "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", - "dependencies": { - "@webassemblyjs/helper-module-context": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/wast-parser": "1.9.0" - } - }, - "node_modules/@webassemblyjs/helper-module-context/node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", - "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==" + "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", + "dev": true }, "node_modules/@webassemblyjs/helper-numbers": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", + "dev": true, "dependencies": { "@webassemblyjs/floating-point-hex-parser": "1.13.2", "@webassemblyjs/helper-api-error": "1.13.2", @@ -6779,12 +5385,14 @@ "node_modules/@webassemblyjs/helper-wasm-bytecode": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", - "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==" + "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", + "dev": true }, "node_modules/@webassemblyjs/helper-wasm-section": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", + "dev": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", @@ -6796,6 +5404,7 @@ "version": "1.13.2", "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", + "dev": true, "dependencies": { "@xtuc/ieee754": "^1.2.0" } @@ -6804,6 +5413,7 @@ "version": "1.13.2", "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", + "dev": true, "dependencies": { "@xtuc/long": "4.2.2" } @@ -6811,12 +5421,14 @@ "node_modules/@webassemblyjs/utf8": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", - "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==" + "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", + "dev": true }, "node_modules/@webassemblyjs/wasm-edit": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", + "dev": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", @@ -6832,6 +5444,7 @@ "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", + "dev": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-wasm-bytecode": "1.13.2", @@ -6844,6 +5457,7 @@ "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", + "dev": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", @@ -6855,6 +5469,7 @@ "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", + "dev": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-api-error": "1.13.2", @@ -6864,48 +5479,11 @@ "@webassemblyjs/utf8": "1.13.2" } }, - "node_modules/@webassemblyjs/wast-parser": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz", - "integrity": "sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==", - "dependencies": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/floating-point-hex-parser": "1.9.0", - "@webassemblyjs/helper-api-error": "1.9.0", - "@webassemblyjs/helper-code-frame": "1.9.0", - "@webassemblyjs/helper-fsm": "1.9.0", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/wast-parser/node_modules/@webassemblyjs/ast": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", - "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", - "dependencies": { - "@webassemblyjs/helper-module-context": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/wast-parser": "1.9.0" - } - }, - "node_modules/@webassemblyjs/wast-parser/node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz", - "integrity": "sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==" - }, - "node_modules/@webassemblyjs/wast-parser/node_modules/@webassemblyjs/helper-api-error": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", - "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==" - }, - "node_modules/@webassemblyjs/wast-parser/node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", - "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==" - }, "node_modules/@webassemblyjs/wast-printer": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", + "dev": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@xtuc/long": "4.2.2" @@ -7524,17 +6102,6 @@ } } }, - "node_modules/@wordpress/env/node_modules/@types/node": { - "version": "24.10.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.1.tgz", - "integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "undici-types": "~7.16.0" - } - }, "node_modules/@wordpress/env/node_modules/mute-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", @@ -8941,20 +7508,17 @@ "node": ">=12" } }, - "node_modules/@xstate/fsm": { - "version": "1.6.5", - "resolved": "https://registry.npmjs.org/@xstate/fsm/-/fsm-1.6.5.tgz", - "integrity": "sha512-b5o1I6aLNeYlU/3CPlj/Z91ybk1gUsKT+5NAJI+2W4UjvS5KLG28K9v5UvNoFVjHV8PajVZ00RH3vnjyQO7ZAw==" - }, "node_modules/@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true }, "node_modules/@xtuc/long": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true }, "node_modules/abab": { "version": "2.0.6", @@ -8983,6 +7547,7 @@ "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" @@ -8995,6 +7560,7 @@ "version": "8.14.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", + "dev": true, "bin": { "acorn": "bin/acorn" }, @@ -9016,7 +7582,7 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "devOptional": true, + "dev": true, "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } @@ -9058,6 +7624,7 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -9073,6 +7640,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", + "dev": true, "peerDependencies": { "ajv": ">=5.0.0" } @@ -9081,6 +7649,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, "dependencies": { "ajv": "^8.0.0" }, @@ -9097,6 +7666,7 @@ "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -9111,12 +7681,14 @@ "node_modules/ajv-formats/node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true }, "node_modules/ajv-keywords": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, "peerDependencies": { "ajv": "^6.9.1" } @@ -9208,16 +7780,6 @@ "node": ">= 8" } }, - "node_modules/app-root-dir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/app-root-dir/-/app-root-dir-1.0.2.tgz", - "integrity": "sha512-jlpIfsOoNoafl92Sz//64uQHGSyMrD2vYG5d8o2a4qGvyNCvXur7bzIsWtAC/6flI2RYAp3kv8rsfBtaLm7w0g==" - }, - "node_modules/aproba": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" - }, "node_modules/archiver": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.2.tgz", @@ -9280,32 +7842,6 @@ "node": ">=14" } }, - "node_modules/are-we-there-yet": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", - "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", - "deprecated": "This package is no longer supported.", - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/are-we-there-yet/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/arg": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", @@ -9324,34 +7860,11 @@ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" }, - "node_modules/aria-query": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", - "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", - "dependencies": { - "deep-equal": "^2.0.5" - } - }, - "node_modules/arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/arr-union": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", "integrity": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -9360,6 +7873,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "dev": true, "dependencies": { "call-bound": "^1.0.3", "is-array-buffer": "^3.0.5" @@ -9382,7 +7896,8 @@ "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "dev": true }, "node_modules/array-includes": { "version": "3.1.8", @@ -9425,15 +7940,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -9561,51 +8068,6 @@ "node": ">=0.10.0" } }, - "node_modules/asn1.js": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", - "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", - "dependencies": { - "bn.js": "^4.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" - } - }, - "node_modules/asn1.js/node_modules/bn.js": { - "version": "4.12.2", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", - "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==" - }, - "node_modules/assert": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.1.tgz", - "integrity": "sha512-zzw1uCAgLbsKwBfFc8CX78DDg+xZeBksSO3vwVIDDN5i94eOrPsSSyiVhmsSABFDM/OcpE2aagCat9dnWQLG1A==", - "dependencies": { - "object.assign": "^4.1.4", - "util": "^0.10.4" - } - }, - "node_modules/assert/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==" - }, - "node_modules/assert/node_modules/util": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", - "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", - "dependencies": { - "inherits": "2.0.3" - } - }, - "node_modules/assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/ast-types": { "version": "0.13.4", "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", @@ -9638,18 +8100,6 @@ "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==" }, - "node_modules/async-each": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.6.tgz", - "integrity": "sha512-c646jH1avxr+aVpndVMeAfYw7wAa6idufrlN3LPA4PmKS0QEGp6PIC9nwz0WQkkvBGAMEki3pFdtxaF39J9vvg==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "optional": true - }, "node_modules/async-function": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", @@ -9664,25 +8114,6 @@ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, - "node_modules/at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "bin": { - "atob": "bin/atob.js" - }, - "engines": { - "node": ">= 4.5.0" - } - }, "node_modules/autoprefixer": { "version": "10.4.21", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.21.tgz", @@ -9723,6 +8154,7 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, "dependencies": { "possible-typed-array-names": "^1.0.0" }, @@ -9737,6 +8169,7 @@ "version": "4.10.3", "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.3.tgz", "integrity": "sha512-Xm7bpRXnDSX2YE2YFfBk2FnF0ep6tmG7xPh8iHee8MIcrgq762Nkce856dYtJYLkuIoYZvGfTs/PbZhideTcEg==", + "dev": true, "engines": { "node": ">=4" } @@ -9792,6 +8225,7 @@ "version": "8.4.1", "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.4.1.tgz", "integrity": "sha512-nXzRChX+Z1GoE6yWavBQg6jDslyFF3SDjl2paADuoQtQW10JqShJt62R6eJQ5m/pjJFDT8xgKIWSP85OY8eXeA==", + "dev": true, "dependencies": { "find-cache-dir": "^3.3.1", "loader-utils": "^2.0.4", @@ -9810,6 +8244,7 @@ "version": "3.3.2", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "dev": true, "dependencies": { "commondir": "^1.0.1", "make-dir": "^3.0.2", @@ -9826,6 +8261,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -9838,6 +8274,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, "dependencies": { "p-locate": "^4.1.0" }, @@ -9849,6 +8286,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, "dependencies": { "semver": "^6.0.0" }, @@ -9863,6 +8301,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, "dependencies": { "p-try": "^2.0.0" }, @@ -9877,6 +8316,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, "dependencies": { "p-limit": "^2.2.0" }, @@ -9888,6 +8328,7 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, "dependencies": { "find-up": "^4.0.0" }, @@ -9899,6 +8340,7 @@ "version": "2.7.1", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "dev": true, "dependencies": { "@types/json-schema": "^7.0.5", "ajv": "^6.12.4", @@ -9992,6 +8434,7 @@ "version": "0.4.13", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.13.tgz", "integrity": "sha512-3sX/eOms8kd3q2KZ6DAhKPc0dgm525Gqq5NtWKZ7QYYZEv57OQ54KtblzJzH1lQF/eQxO8KjWGIK9IPUJNus5g==", + "dev": true, "dependencies": { "@babel/compat-data": "^7.22.6", "@babel/helper-define-polyfill-provider": "^0.6.4", @@ -10001,40 +8444,11 @@ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, - "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.1.7.tgz", - "integrity": "sha512-u+gbS9bbPhZWEeyy1oR/YaaSpod/KDT07arZHb80aTpl8H5ZBq+uN1nN9/xtX7jQyfLdPfoqI4Rue/MQSWJquw==", - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.1.5", - "core-js-compat": "^3.8.1" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/babel-plugin-polyfill-corejs3/node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.1.5.tgz", - "integrity": "sha512-nXuzCSwlJ/WKr8qxzW816gwyT6VZgiJG17zR40fou70yfAcqjoNyTLl/DQ+FExw5Hx5KNqshmN8Ldl/r2N7cTg==", - "dependencies": { - "@babel/helper-compilation-targets": "^7.13.0", - "@babel/helper-module-imports": "^7.12.13", - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/traverse": "^7.13.0", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2", - "semver": "^6.1.2" - }, - "peerDependencies": { - "@babel/core": "^7.4.0-0" - } - }, "node_modules/babel-plugin-polyfill-regenerator": { "version": "0.6.4", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.4.tgz", "integrity": "sha512-7gD3pRadPrbjhjLyxebmx/WrFYcuSjZ0XbdUujQMZ/fcE9oeewk2U/7PCvez84UeuK3oSjmPZ0Ch0dlupQvGzw==", + "dev": true, "dependencies": { "@babel/helper-define-polyfill-provider": "^0.6.4" }, @@ -10161,34 +8575,6 @@ } } }, - "node_modules/base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dependencies": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/base/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", - "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -10223,15 +8609,11 @@ "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", "dev": true }, - "node_modules/batch-processor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/batch-processor/-/batch-processor-1.0.0.tgz", - "integrity": "sha512-xoLQD8gmmR32MeuBHgH0Tzd5PuSZx71ZsbhVxOCRbgktZEPe4SQy7s9Z50uPp0F/f7iw2XmkHN2xkgbMfckMDA==" - }, "node_modules/big.js": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true, "engines": { "node": "*" } @@ -10247,15 +8629,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "optional": true, - "dependencies": { - "file-uri-to-path": "1.0.0" - } - }, "node_modules/bl": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", @@ -10281,20 +8654,11 @@ "node": ">= 6" } }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" - }, - "node_modules/bn.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.2.tgz", - "integrity": "sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw==" - }, "node_modules/body-parser": { "version": "1.20.3", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "dev": true, "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.5", @@ -10318,6 +8682,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, "dependencies": { "ms": "2.0.0" } @@ -10325,12 +8690,14 @@ "node_modules/body-parser/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true }, "node_modules/body-parser/node_modules/qs": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "dev": true, "dependencies": { "side-channel": "^1.0.6" }, @@ -10375,86 +8742,6 @@ "node": ">=8" } }, - "node_modules/brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==" - }, - "node_modules/browserify-aes": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", - "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "dependencies": { - "buffer-xor": "^1.0.3", - "cipher-base": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.3", - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/browserify-cipher": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", - "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", - "dependencies": { - "browserify-aes": "^1.0.4", - "browserify-des": "^1.0.0", - "evp_bytestokey": "^1.0.0" - } - }, - "node_modules/browserify-des": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", - "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", - "dependencies": { - "cipher-base": "^1.0.1", - "des.js": "^1.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/browserify-rsa": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.1.tgz", - "integrity": "sha512-YBjSAiTqM04ZVei6sXighu679a3SqWORA3qZTEqZImnlkDIFtKc6pNutpjyZ8RJTjQtuYfeetkxM11GwoYXMIQ==", - "dependencies": { - "bn.js": "^5.2.1", - "randombytes": "^2.1.0", - "safe-buffer": "^5.2.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/browserify-sign": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.3.tgz", - "integrity": "sha512-JWCZW6SKhfhjJxO8Tyiiy+XYB7cqd2S5/+WeYHsKdNKFlCBhKbblba1A/HN/90YwtxKc8tCErjffZl++UNmGiw==", - "dependencies": { - "bn.js": "^5.2.1", - "browserify-rsa": "^4.1.0", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "elliptic": "^6.5.5", - "hash-base": "~3.0", - "inherits": "^2.0.4", - "parse-asn1": "^5.1.7", - "readable-stream": "^2.3.8", - "safe-buffer": "^5.2.1" - }, - "engines": { - "node": ">= 0.12" - } - }, - "node_modules/browserify-zlib": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", - "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", - "dependencies": { - "pako": "~1.0.5" - } - }, "node_modules/browserslist": { "version": "4.24.5", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.5.tgz", @@ -10531,12 +8818,8 @@ "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" - }, - "node_modules/buffer-xor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==" + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true }, "node_modules/builtin-modules": { "version": "3.3.0", @@ -10550,77 +8833,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/builtin-status-codes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", - "integrity": "sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==" - }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, "engines": { "node": ">= 0.8" } }, - "node_modules/cacache": { - "version": "12.0.4", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", - "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", - "dependencies": { - "bluebird": "^3.5.5", - "chownr": "^1.1.1", - "figgy-pudding": "^3.5.1", - "glob": "^7.1.4", - "graceful-fs": "^4.1.15", - "infer-owner": "^1.0.3", - "lru-cache": "^5.1.1", - "mississippi": "^3.0.0", - "mkdirp": "^0.5.1", - "move-concurrently": "^1.0.1", - "promise-inflight": "^1.0.1", - "rimraf": "^2.6.3", - "ssri": "^6.0.1", - "unique-filename": "^1.1.1", - "y18n": "^4.0.0" - } - }, - "node_modules/cacache/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/cacache/node_modules/y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" - }, - "node_modules/cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dependencies": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/cacheable-lookup": { "version": "5.0.4", "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", @@ -10784,9 +9005,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001718", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001718.tgz", - "integrity": "sha512-AflseV1ahcSunK53NfEs9gFWgOEmzr0f+kaMFA4xiLZlr9Hzt7HxcSpIFcnNCUkz6R6dWKa54rUz3HUmI3nVcw==", + "version": "1.0.30001780", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001780.tgz", + "integrity": "sha512-llngX0E7nQci5BPJDqoZSbuZ5Bcs9F5db7EtgfwBerX9XGtkkiO4NwfDDIRzHTTwcYC8vC7bmeUEPGrKlR/TkQ==", "funding": [ { "type": "opencollective", @@ -10800,7 +9021,8 @@ "type": "github", "url": "https://github.com/sponsors/ai" } - ] + ], + "license": "CC-BY-4.0" }, "node_modules/capital-case": { "version": "1.0.4", @@ -10931,7 +9153,8 @@ "node_modules/chownr": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true }, "node_modules/chrome-launcher": { "version": "1.2.0", @@ -10955,6 +9178,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", + "dev": true, "engines": { "node": ">=6.0" } @@ -10987,61 +9211,12 @@ "node": ">=8" } }, - "node_modules/cipher-base": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.6.tgz", - "integrity": "sha512-3Ek9H3X6pj5TgenXYtNWdaBon1tgYCaebd+XPg0keyjEbEfkD4KkmAxkQ/i1vYvxdcT5nscLBfq9VJRmCBcFSw==", - "dependencies": { - "inherits": "^2.0.4", - "safe-buffer": "^5.2.1" - }, - "engines": { - "node": ">= 0.10" - } - }, "node_modules/cjs-module-lexer": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", "dev": true }, - "node_modules/class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dependencies": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/class-utils/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/class-utils/node_modules/is-descriptor": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.7.tgz", - "integrity": "sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==", - "dependencies": { - "is-accessor-descriptor": "^1.0.1", - "is-data-descriptor": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/classnames": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", @@ -11143,6 +9318,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, "dependencies": { "is-plain-object": "^2.0.4", "kind-of": "^6.0.2", @@ -11156,6 +9332,7 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, "dependencies": { "isobject": "^3.0.1" }, @@ -11199,18 +9376,6 @@ "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", "dev": true }, - "node_modules/collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==", - "dependencies": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -11227,14 +9392,6 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, - "node_modules/color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "bin": { - "color-support": "bin.js" - } - }, "node_modules/colord": { "version": "2.9.3", "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", @@ -11286,15 +9443,8 @@ "node_modules/commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==" - }, - "node_modules/component-emitter": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz", - "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==", - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "dev": true }, "node_modules/compress-commons": { "version": "4.1.2", @@ -11388,6 +9538,7 @@ "version": "1.6.2", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, "engines": [ "node >= 0.8" ], @@ -11451,16 +9602,6 @@ "node": ">=0.8" } }, - "node_modules/console-browserify": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", - "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==" - }, - "node_modules/console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" - }, "node_modules/constant-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/constant-case/-/constant-case-3.0.4.tgz", @@ -11471,15 +9612,11 @@ "upper-case": "^2.0.2" } }, - "node_modules/constants-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", - "integrity": "sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==" - }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dev": true, "dependencies": { "safe-buffer": "5.2.1" }, @@ -11498,60 +9635,24 @@ "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true }, "node_modules/cookie": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "dev": true, "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" - }, - "node_modules/copy-concurrently": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", - "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", - "deprecated": "This package is no longer supported.", - "dependencies": { - "aproba": "^1.1.1", - "fs-write-stream-atomic": "^1.0.8", - "iferr": "^0.1.5", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.0" - } - }, - "node_modules/copy-concurrently/node_modules/aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" - }, - "node_modules/copy-concurrently/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==", - "engines": { - "node": ">=0.10.0" + "node": ">= 0.6" } }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "dev": true + }, "node_modules/copy-dir": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/copy-dir/-/copy-dir-1.3.0.tgz", @@ -11617,6 +9718,7 @@ "version": "3.42.0", "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.42.0.tgz", "integrity": "sha512-Sz4PP4ZA+Rq4II21qkNqOEDTDrCvcANId3xpIgB34NDkWc3UduWj2dqEtN9yZIq8Dk3HyPI33x9sqqU5C8sr0g==", + "dev": true, "hasInstallScript": true, "funding": { "type": "opencollective", @@ -11627,6 +9729,7 @@ "version": "3.42.0", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.42.0.tgz", "integrity": "sha512-bQasjMfyDGyaeWKBIu33lHh9qlSR0MFE/Nmc6nMjf/iU9b3rSMdAYz1Baxrv4lPdGUsTqZudHA4jIGSJy0SWZQ==", + "dev": true, "dependencies": { "browserslist": "^4.24.4" }, @@ -11649,7 +9752,8 @@ "node_modules/core-util-is": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true }, "node_modules/cosmiconfig": { "version": "8.3.6", @@ -11695,11 +9799,6 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/country-region-data": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/country-region-data/-/country-region-data-2.7.0.tgz", - "integrity": "sha512-bBh+6PMt2uMCL4pPMYeR6GnoyOFgiITXPAdLU86gYOTOVvdgUyQtCaoIwdySDOUaFIEKXT94yuw+ldx614IUcA==" - }, "node_modules/crc-32": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", @@ -11739,45 +9838,6 @@ "node": ">= 6" } }, - "node_modules/create-ecdh": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", - "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", - "dependencies": { - "bn.js": "^4.1.0", - "elliptic": "^6.5.3" - } - }, - "node_modules/create-ecdh/node_modules/bn.js": { - "version": "4.12.2", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", - "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==" - }, - "node_modules/create-hash": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "dependencies": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } - }, - "node_modules/create-hmac": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "dependencies": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, "node_modules/create-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", @@ -11877,31 +9937,6 @@ "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", "dev": true }, - "node_modules/crypto-browserify": { - "version": "3.12.1", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.1.tgz", - "integrity": "sha512-r4ESw/IlusD17lgQi1O20Fa3qNnsckR126TdUuBgAu7GBYSIPvdNyONd3Zrxh0xCwA4+6w/TDArBPsMvhur+KQ==", - "dependencies": { - "browserify-cipher": "^1.0.1", - "browserify-sign": "^4.2.3", - "create-ecdh": "^4.0.4", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "diffie-hellman": "^5.0.3", - "hash-base": "~3.0.4", - "inherits": "^2.0.4", - "pbkdf2": "^3.1.2", - "public-encrypt": "^4.0.3", - "randombytes": "^2.1.0", - "randomfill": "^1.0.4" - }, - "engines": { - "node": ">= 0.10" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/crypto-random-string": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", @@ -12204,11 +10239,6 @@ "node": ">=0.8" } }, - "node_modules/cyclist": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.2.tgz", - "integrity": "sha512-0sVXIohTfLqVIW3kb/0n6IiWF3Ifj5nm2XaSrLq2DI6fKIGa2fYAZdk917rUneaeLVpYfFcyXE2ft0fe3remsA==" - }, "node_modules/d3-array": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", @@ -12488,14 +10518,6 @@ "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz", "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==" }, - "node_modules/decode-uri-component": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", - "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", - "engines": { - "node": ">=0.10" - } - }, "node_modules/decompress-response": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", @@ -12537,37 +10559,6 @@ } } }, - "node_modules/deep-equal": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz", - "integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==", - "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.5", - "es-get-iterator": "^1.1.3", - "get-intrinsic": "^1.2.2", - "is-arguments": "^1.1.1", - "is-array-buffer": "^3.0.2", - "is-date-object": "^1.0.5", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "isarray": "^2.0.5", - "object-is": "^1.1.5", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.1", - "side-channel": "^1.0.4", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", @@ -12581,7 +10572,7 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "devOptional": true + "dev": true }, "node_modules/deepmerge": { "version": "4.3.1", @@ -12674,18 +10665,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dependencies": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/degenerator": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", @@ -12776,32 +10755,20 @@ "node": ">=0.4.0" } }, - "node_modules/delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" - }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, "engines": { "node": ">= 0.8" } }, - "node_modules/des.js": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.1.0.tgz", - "integrity": "sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==", - "dependencies": { - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" - } - }, "node_modules/destroy": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "dev": true, "engines": { "node": ">= 0.8", "npm": "1.2.8000 || >= 1.4.16" @@ -12819,6 +10786,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", + "dev": true, "optional": true, "bin": { "detect-libc": "bin/detect-libc.js" @@ -12870,21 +10838,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/diffie-hellman": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", - "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", - "dependencies": { - "bn.js": "^4.1.0", - "miller-rabin": "^4.0.0", - "randombytes": "^2.0.0" - } - }, - "node_modules/diffie-hellman/node_modules/bn.js": { - "version": "4.12.2", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", - "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==" - }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -12930,7 +10883,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "devOptional": true, + "dev": true, "dependencies": { "esutils": "^2.0.2" }, @@ -12938,11 +10891,6 @@ "node": ">=6.0.0" } }, - "node_modules/dom-accessibility-api": { - "version": "0.5.16", - "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", - "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==" - }, "node_modules/dom-helpers": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", @@ -12973,20 +10921,6 @@ "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" } }, - "node_modules/dom-walk": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", - "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==" - }, - "node_modules/domain-browser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", - "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", - "engines": { - "node": ">=0.4", - "npm": ">=1.2" - } - }, "node_modules/domelementtype": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", @@ -13026,10 +10960,9 @@ } }, "node_modules/dompurify": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.3.0.tgz", - "integrity": "sha512-r+f6MYR1gGN1eJv0TVQbhA7if/U7P87cdPl3HN5rikqaBSBxLiCb/b9O+2eG0cxz0ghyU+mU1QkbsOwERMYlWQ==", - "license": "(MPL-2.0 OR Apache-2.0)", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.3.3.tgz", + "integrity": "sha512-Oj6pzI2+RqBfFG+qOaOLbFXLQ90ARpcGG6UePL82bJLtdsa6CYJD7nmiU8MW9nQNOtCHV3lZ/Bzq1X0QYbBZCA==", "optionalDependencies": { "@types/trusted-types": "^2.0.7" } @@ -13068,19 +11001,6 @@ "node": ">=8" } }, - "node_modules/dotenv": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", - "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==", - "engines": { - "node": ">=10" - } - }, - "node_modules/dotenv-expand": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", - "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==" - }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", @@ -13099,17 +11019,6 @@ "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" }, - "node_modules/duplexify": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", - "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", - "dependencies": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - } - }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -13118,40 +11027,14 @@ "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "dev": true }, "node_modules/electron-to-chromium": { "version": "1.5.152", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.152.tgz", "integrity": "sha512-xBOfg/EBaIlVsHipHl2VdTPJRSvErNUaqW8ejTq5OlOlIYx1wOllCHsAvAIrr55jD1IYEfdR86miUEt8H5IeJg==" }, - "node_modules/element-resize-detector": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/element-resize-detector/-/element-resize-detector-1.2.4.tgz", - "integrity": "sha512-Fl5Ftk6WwXE0wqCgNoseKWndjzZlDCwuPTcoVZfCP9R3EHQF8qUtr3YUPNETegRBOKqQKPW3n4kiIWngGi8tKg==", - "dependencies": { - "batch-processor": "1.0.0" - } - }, - "node_modules/elliptic": { - "version": "6.6.1", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.1.tgz", - "integrity": "sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==", - "dependencies": { - "bn.js": "^4.11.9", - "brorand": "^1.1.0", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.1", - "inherits": "^2.0.4", - "minimalistic-assert": "^1.0.1", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/elliptic/node_modules/bn.js": { - "version": "4.12.2", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", - "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==" - }, "node_modules/emittery": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", @@ -13173,6 +11056,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true, "engines": { "node": ">= 4" } @@ -13181,6 +11065,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "dev": true, "engines": { "node": ">= 0.8" } @@ -13208,6 +11093,7 @@ "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, "dependencies": { "once": "^1.4.0" } @@ -13216,6 +11102,7 @@ "version": "5.18.1", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz", "integrity": "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==", + "dev": true, "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -13228,6 +11115,7 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, "engines": { "node": ">=6" } @@ -13268,17 +11156,6 @@ "node": ">=4" } }, - "node_modules/errno": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", - "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", - "dependencies": { - "prr": "~1.0.1" - }, - "bin": { - "errno": "cli.js" - } - }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -13377,25 +11254,6 @@ "node": ">= 0.4" } }, - "node_modules/es-get-iterator": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", - "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "has-symbols": "^1.0.3", - "is-arguments": "^1.1.1", - "is-map": "^2.0.2", - "is-set": "^2.0.2", - "is-string": "^1.0.7", - "isarray": "^2.0.5", - "stop-iteration-iterator": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/es-iterator-helpers": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.1.tgz", @@ -13426,7 +11284,8 @@ "node_modules/es-module-lexer": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", - "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==" + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "dev": true }, "node_modules/es-object-atoms": { "version": "1.1.1", @@ -13493,7 +11352,8 @@ "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true }, "node_modules/escape-string-regexp": { "version": "4.0.0", @@ -13542,7 +11402,7 @@ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", - "devOptional": true, + "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -14115,6 +11975,7 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" @@ -14127,6 +11988,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, "engines": { "node": ">=4.0" } @@ -14144,13 +12006,13 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "devOptional": true + "dev": true }, "node_modules/eslint/node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "devOptional": true, + "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -14160,7 +12022,7 @@ "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "devOptional": true, + "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -14174,7 +12036,7 @@ "version": "7.2.2", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "devOptional": true, + "dev": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" @@ -14190,7 +12052,7 @@ "version": "3.4.3", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "devOptional": true, + "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -14202,7 +12064,7 @@ "version": "13.24.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "devOptional": true, + "dev": true, "dependencies": { "type-fest": "^0.20.2" }, @@ -14217,7 +12079,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "devOptional": true, + "dev": true, "dependencies": { "argparse": "^2.0.1" }, @@ -14229,7 +12091,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "devOptional": true, + "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -14241,7 +12103,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "devOptional": true, + "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -14253,7 +12115,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "devOptional": true, + "dev": true, "engines": { "node": ">=8" } @@ -14262,7 +12124,7 @@ "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "devOptional": true, + "dev": true, "engines": { "node": ">=10" }, @@ -14274,7 +12136,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "devOptional": true, + "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -14289,7 +12151,7 @@ "version": "9.6.1", "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "devOptional": true, + "dev": true, "dependencies": { "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", @@ -14306,7 +12168,7 @@ "version": "3.4.3", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "devOptional": true, + "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -14330,7 +12192,7 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", - "devOptional": true, + "dev": true, "dependencies": { "estraverse": "^5.1.0" }, @@ -14342,6 +12204,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, "dependencies": { "estraverse": "^5.2.0" }, @@ -14353,6 +12216,7 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, "engines": { "node": ">=4.0" } @@ -14361,6 +12225,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -14369,6 +12234,7 @@ "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "dev": true, "engines": { "node": ">= 0.6" } @@ -14399,15 +12265,6 @@ "node": ">=0.8.x" } }, - "node_modules/evp_bytestokey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", - "dependencies": { - "md5.js": "^1.3.4", - "safe-buffer": "^5.1.1" - } - }, "node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -14501,78 +12358,6 @@ "node": ">= 0.8.0" } }, - "node_modules/expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==", - "dependencies": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/expand-brackets/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/is-descriptor": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.7.tgz", - "integrity": "sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==", - "dependencies": { - "is-accessor-descriptor": "^1.0.1", - "is-data-descriptor": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/expand-brackets/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, "node_modules/expand-tilde": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", @@ -14610,6 +12395,7 @@ "version": "4.21.2", "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "dev": true, "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", @@ -14655,6 +12441,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, "dependencies": { "ms": "2.0.0" } @@ -14662,12 +12449,14 @@ "node_modules/express/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true }, "node_modules/express/node_modules/qs": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "dev": true, "dependencies": { "side-channel": "^1.0.6" }, @@ -14683,18 +12472,6 @@ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" }, - "node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/external-editor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", @@ -14709,54 +12486,6 @@ "node": ">=4" } }, - "node_modules/extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dependencies": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", - "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/extract-zip": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz", @@ -14790,7 +12519,8 @@ "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true }, "node_modules/fast-diff": { "version": "1.3.0", @@ -14841,18 +12571,20 @@ "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true }, "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "devOptional": true + "dev": true }, "node_modules/fast-uri": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", + "dev": true, "funding": [ { "type": "github", @@ -14909,13 +12641,7 @@ "dev": true, "dependencies": { "pend": "~1.2.0" - } - }, - "node_modules/figgy-pudding": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", - "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==", - "deprecated": "This module is no longer supported." + } }, "node_modules/figures": { "version": "3.2.0", @@ -14943,7 +12669,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "devOptional": true, + "dev": true, "dependencies": { "flat-cache": "^3.0.4" }, @@ -14957,34 +12683,6 @@ "integrity": "sha512-0k45oWBokCqh2MOexeYKpyqmGKG+8mQ2Wd8iawx+uWd/weWJQAZ6SoPybagdCI4xFisag8iAR77WPm4h3pTfxA==", "dev": true }, - "node_modules/file-system-cache": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/file-system-cache/-/file-system-cache-1.1.0.tgz", - "integrity": "sha512-IzF5MBq+5CR0jXx5RxPe4BICl/oEhBSXKaL9fLhAXrIfIUS77Hr4vzrYyqYMHN6uTt+BOqi3fDCTjjEBCjERKw==", - "dependencies": { - "fs-extra": "^10.1.0", - "ramda": "^0.28.0" - } - }, - "node_modules/file-system-cache/node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "optional": true - }, "node_modules/filename-reserved-regex": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", @@ -15026,6 +12724,7 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "dev": true, "dependencies": { "debug": "2.6.9", "encodeurl": "~2.0.0", @@ -15043,6 +12742,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, "dependencies": { "ms": "2.0.0" } @@ -15050,87 +12750,8 @@ "node_modules/finalhandler/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/find-cache-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", - "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", - "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^2.0.0", - "pkg-dir": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/find-cache-dir/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/find-cache-dir/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/find-cache-dir/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/find-cache-dir/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/find-cache-dir/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "engines": { - "node": ">=4" - } - }, - "node_modules/find-cache-dir/node_modules/pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "dependencies": { - "find-up": "^3.0.0" - }, - "engines": { - "node": ">=6" - } + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true }, "node_modules/find-file-up": { "version": "0.1.3", @@ -15186,6 +12807,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -15298,7 +12920,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", - "devOptional": true, + "dev": true, "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.3", @@ -15313,7 +12935,7 @@ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "deprecated": "Rimraf versions prior to v4 are no longer supported", - "devOptional": true, + "dev": true, "dependencies": { "glob": "^7.1.3" }, @@ -15328,32 +12950,7 @@ "version": "3.3.3", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", - "devOptional": true - }, - "node_modules/flush-write-stream": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", - "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", - "dependencies": { - "inherits": "^2.0.3", - "readable-stream": "^2.3.6" - } - }, - "node_modules/focus-lock": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/focus-lock/-/focus-lock-0.8.1.tgz", - "integrity": "sha512-/LFZOIo82WDsyyv7h7oc0MJF9ACOvDRdx9rWPZ2pgMfNWu/z8hQDBtOchuB/0BVLmuFOZjV02YwUVzNsWx/EzA==", - "dependencies": { - "tslib": "^1.9.3" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/focus-lock/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "dev": true }, "node_modules/follow-redirects": { "version": "1.15.9", @@ -15378,6 +12975,7 @@ "version": "0.3.5", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "dev": true, "dependencies": { "is-callable": "^1.2.7" }, @@ -15479,115 +13077,6 @@ "node": ">= 8" } }, - "node_modules/fork-ts-checker-webpack-plugin": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.3.tgz", - "integrity": "sha512-SbH/l9ikmMWycd5puHJKTkZJKddF4iRLyW3DeZ08HTI7NGyLS38MXd/KGgeWumQO7YNQbW2u/NtPT2YowbPaGQ==", - "dependencies": { - "@babel/code-frame": "^7.8.3", - "@types/json-schema": "^7.0.5", - "chalk": "^4.1.0", - "chokidar": "^3.4.2", - "cosmiconfig": "^6.0.0", - "deepmerge": "^4.2.2", - "fs-extra": "^9.0.0", - "glob": "^7.1.6", - "memfs": "^3.1.2", - "minimatch": "^3.0.4", - "schema-utils": "2.7.0", - "semver": "^7.3.2", - "tapable": "^1.0.0" - }, - "engines": { - "node": ">=10", - "yarn": ">=1.0.0" - }, - "peerDependencies": { - "eslint": ">= 6", - "typescript": ">= 2.7", - "vue-template-compiler": "*", - "webpack": ">= 4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - }, - "vue-template-compiler": { - "optional": true - } - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/cosmiconfig": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", - "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", - "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.1.0", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.7.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/schema-utils": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", - "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", - "dependencies": { - "@types/json-schema": "^7.0.4", - "ajv": "^6.12.2", - "ajv-keywords": "^3.4.1" - }, - "engines": { - "node": ">= 8.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "engines": { - "node": ">= 6" - } - }, "node_modules/form-data": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", @@ -15606,6 +13095,7 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true, "engines": { "node": ">= 0.6" } @@ -15622,17 +13112,6 @@ "url": "https://github.com/sponsors/rawify" } }, - "node_modules/fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==", - "dependencies": { - "map-cache": "^0.2.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/framer-motion": { "version": "11.18.2", "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-11.18.2.tgz", @@ -15663,19 +13142,11 @@ "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "dev": true, "engines": { "node": ">= 0.6" } }, - "node_modules/from2": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", - "integrity": "sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==", - "dependencies": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.0" - } - }, "node_modules/fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", @@ -15691,36 +13162,11 @@ "node": ">=0.10.0" } }, - "node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/fs-monkey": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.6.tgz", - "integrity": "sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==" - }, - "node_modules/fs-write-stream-atomic": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", - "integrity": "sha512-gehEzmPn2nAwr39eay+x3X34Ra+M2QlVUTLhkXPjWdeO8RF9kszk116avgBJM3ZyNHgHXBNx+VmPaFC36k0PzA==", - "deprecated": "This package is no longer supported.", - "dependencies": { - "graceful-fs": "^4.1.2", - "iferr": "^0.1.5", - "imurmurhash": "^0.1.4", - "readable-stream": "1 || 2" - } + "integrity": "sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==", + "dev": true }, "node_modules/fs.realpath": { "version": "1.0.0", @@ -15776,38 +13222,11 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/fuse.js": { - "version": "6.6.2", - "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-6.6.2.tgz", - "integrity": "sha512-cJaJkxCCxC8qIIcPBF9yGxY0W/tVZS3uEISDxhYIdtk8OL93pe+6Zj7LjCqVV4dzbqcriOZ+kQ/NE4RXZHsIGA==", - "engines": { - "node": ">=10" - } - }, - "node_modules/gauge": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", - "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", - "deprecated": "This package is no longer supported.", - "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.2", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.1", - "object-assign": "^4.1.1", - "signal-exit": "^3.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.2" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, "engines": { "node": ">=6.9.0" } @@ -15935,14 +13354,6 @@ "node": ">= 14" } }, - "node_modules/get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/getobject": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/getobject/-/getobject-1.0.2.tgz", @@ -15965,6 +13376,7 @@ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -15994,12 +13406,14 @@ "node_modules/glob-to-regexp": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true }, "node_modules/glob/node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -16009,6 +13423,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -16016,15 +13431,6 @@ "node": "*" } }, - "node_modules/global": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz", - "integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==", - "dependencies": { - "min-document": "^2.19.0", - "process": "^0.11.10" - } - }, "node_modules/global-modules": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-0.2.3.tgz", @@ -16249,13 +13655,14 @@ "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true }, "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "devOptional": true + "dev": true }, "node_modules/grunt": { "version": "1.6.1", @@ -16781,43 +14188,15 @@ "pify": "^4.0.1" }, "engines": { - "node": ">=6" - } - }, - "node_modules/handle-thing": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", - "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", - "dev": true - }, - "node_modules/handlebars": { - "version": "4.7.8", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", - "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", - "dependencies": { - "minimist": "^1.2.5", - "neo-async": "^2.6.2", - "source-map": "^0.6.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "handlebars": "bin/handlebars" - }, - "engines": { - "node": ">=0.4.7" - }, - "optionalDependencies": { - "uglify-js": "^3.1.4" - } - }, - "node_modules/handlebars/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, + "node_modules/handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", + "dev": true + }, "node_modules/hard-rejection": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", @@ -16852,6 +14231,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "dev": true, "engines": { "node": ">= 0.4" }, @@ -16918,90 +14298,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" - }, - "node_modules/has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw==", - "dependencies": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==", - "dependencies": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-values/node_modules/is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-values/node_modules/is-number/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-values/node_modules/kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==", - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/hash-base": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.5.tgz", - "integrity": "sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg==", - "dependencies": { - "inherits": "^2.0.4", - "safe-buffer": "^5.2.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "dependencies": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -17022,16 +14318,6 @@ "tslib": "^2.0.3" } }, - "node_modules/hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", - "dependencies": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, "node_modules/hoist-non-react-statics": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", @@ -17226,6 +14512,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", @@ -17323,11 +14610,6 @@ "node": ">=10.19.0" } }, - "node_modules/https-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", - "integrity": "sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==" - }, "node_modules/https-proxy-agent": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", @@ -17354,6 +14636,7 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -17392,16 +14675,11 @@ } ] }, - "node_modules/iferr": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", - "integrity": "sha512-DUNFN5j7Tln0D+TxzloUjKB+CtVu6myn0JEFak6dG18mNt9YkQ6lzGCdafwofISZ1lLF3xRHJ98VKy9ynkcFaA==" - }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "devOptional": true, + "dev": true, "engines": { "node": ">= 4" } @@ -17455,21 +14733,8 @@ "node_modules/immutable": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.2.tgz", - "integrity": "sha512-qHKXW1q6liAk1Oys6umoaZbDRqjcjgSrbnrifHsfsttza7zcvRAsL7mMV6xWcyhwQy7Xj5v4hhbr6b+iDYwlmQ==" - }, - "node_modules/import": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/import/-/import-0.0.6.tgz", - "integrity": "sha512-QPhTdjy9J4wUzmWSG7APkSgMFuPGPw+iJTYUblcfc2AfpqaatbwgCldK1HoLYx+v/+lWvab63GWZtNkcnj9JcQ==", - "dependencies": { - "optimist": "0.3.x" - }, - "bin": { - "import": "import" - }, - "engines": { - "node": ">=0.10.0" - } + "integrity": "sha512-qHKXW1q6liAk1Oys6umoaZbDRqjcjgSrbnrifHsfsttza7zcvRAsL7mMV6xWcyhwQy7Xj5v4hhbr6b+iDYwlmQ==", + "dev": true }, "node_modules/import-fresh": { "version": "3.3.1", @@ -17590,6 +14855,7 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, "engines": { "node": ">=0.8.19" } @@ -17603,11 +14869,6 @@ "node": ">=8" } }, - "node_modules/infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==" - }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -17637,6 +14898,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "dev": true, "dependencies": { "es-errors": "^1.3.0", "hasown": "^2.0.2", @@ -17654,14 +14916,6 @@ "node": ">=12" } }, - "node_modules/interpret": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", - "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", - "engines": { - "node": ">= 0.10" - } - }, "node_modules/intl-messageformat": { "version": "10.7.16", "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-10.7.16.tgz", @@ -17686,14 +14940,6 @@ "resolved": "https://registry.npmjs.org/intl-tel-input/-/intl-tel-input-25.14.0.tgz", "integrity": "sha512-DxAHr9N46Vu5hEduPqqRKizhdqwnSVj7ulpUi5tfzYfn56Y6R0bNxuL8o4nt7kAXHH107uDUcxrhjHQ1aj+avA==" }, - "node_modules/invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "dependencies": { - "loose-envify": "^1.0.0" - } - }, "node_modules/ip-address": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", @@ -17711,6 +14957,7 @@ "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true, "engines": { "node": ">= 0.10" } @@ -17736,17 +14983,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-accessor-descriptor": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.1.tgz", - "integrity": "sha512-YBUanLI8Yoihw923YeFUS5fs0fF2f5TSFTNiYAAzhhDscDa3lEqYuz1pDOEP5KvX94I9ey3vsqjJcLVFVU+3QA==", - "dependencies": { - "hasown": "^2.0.0" - }, - "engines": { - "node": ">= 0.10" - } - }, "node_modules/is-arguments": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz", @@ -17766,6 +15002,7 @@ "version": "3.0.5", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "dev": true, "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", @@ -17806,6 +15043,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "dev": true, "dependencies": { "has-bigints": "^1.0.2" }, @@ -17831,6 +15069,7 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "dev": true, "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" @@ -17845,7 +15084,8 @@ "node_modules/is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true }, "node_modules/is-builtin-module": { "version": "3.2.1", @@ -17866,6 +15106,7 @@ "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, "engines": { "node": ">= 0.4" }, @@ -17887,17 +15128,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-data-descriptor": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.1.tgz", - "integrity": "sha512-bc4NlCDiCr28U4aEsQ3Qs2491gVq4V8G7MQyws968ImqjKuYtTJXrl7Vq7jsN7Ly/C3xj5KWFrY7sHNeDkAzXw==", - "dependencies": { - "hasown": "^2.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/is-data-view": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", @@ -17930,18 +15160,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-descriptor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.3.tgz", - "integrity": "sha512-JCNNGbwWZEVaSPtS45mdtrneRWJFp07LLmykxeFV5F6oBvNF8vHSfJuJgoT472pSfk+Mf8VnlrspaFBHWM8JAw==", - "dependencies": { - "is-accessor-descriptor": "^1.0.1", - "is-data-descriptor": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/is-docker": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", @@ -17957,28 +15175,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-extendable/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -18010,11 +15206,6 @@ "node": ">=8" } }, - "node_modules/is-function": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz", - "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==" - }, "node_modules/is-generator-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", @@ -18066,6 +15257,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, "engines": { "node": ">= 0.4" }, @@ -18085,6 +15277,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "dev": true, "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" @@ -18142,7 +15335,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "devOptional": true, + "dev": true, "engines": { "node": ">=8" } @@ -18205,6 +15398,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, "engines": { "node": ">= 0.4" }, @@ -18216,6 +15410,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "dev": true, "dependencies": { "call-bound": "^1.0.3" }, @@ -18242,6 +15437,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "dev": true, "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" @@ -18257,6 +15453,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "dev": true, "dependencies": { "call-bound": "^1.0.2", "has-symbols": "^1.1.0", @@ -18317,6 +15514,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, "engines": { "node": ">= 0.4" }, @@ -18343,6 +15541,7 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "dev": true, "dependencies": { "call-bound": "^1.0.3", "get-intrinsic": "^1.2.6" @@ -18377,7 +15576,8 @@ "node_modules/isarray": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true }, "node_modules/isexe": { "version": "2.0.0", @@ -19123,41 +16323,6 @@ "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "dev": true }, - "node_modules/jest-mock": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", - "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", - "dependencies": { - "@jest/types": "^27.5.1", - "@types/node": "*" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-mock/node_modules/@jest/types": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", - "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", - "dependencies": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^16.0.0", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-mock/node_modules/@types/yargs": { - "version": "16.0.9", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", - "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", - "dependencies": { - "@types/yargs-parser": "*" - } - }, "node_modules/jest-pnp-resolver": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", @@ -19633,12 +16798,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "devOptional": true - }, - "node_modules/json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" + "dev": true }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", @@ -19648,13 +16808,14 @@ "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "devOptional": true + "dev": true }, "node_modules/json2php": { "version": "0.0.7", @@ -19666,6 +16827,7 @@ "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, "bin": { "json5": "lib/cli.js" }, @@ -19679,17 +16841,6 @@ "integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==", "dev": true }, - "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, "node_modules/jsx-ast-utils": { "version": "3.3.5", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", @@ -19709,7 +16860,7 @@ "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "devOptional": true, + "dev": true, "dependencies": { "json-buffer": "3.0.1" } @@ -19783,23 +16934,6 @@ "node": ">=0.10.0" } }, - "node_modules/lazy-universal-dotenv": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lazy-universal-dotenv/-/lazy-universal-dotenv-3.0.1.tgz", - "integrity": "sha512-prXSYk799h3GY3iOWnC6ZigYzMPjxN2svgjJ9shk7oMadSNX3wXy0B6F32PMJv7qtMnrIbUxoEHzbutvxR2LBQ==", - "dependencies": { - "@babel/runtime": "^7.5.0", - "app-root-dir": "^1.0.2", - "core-js": "^3.0.4", - "dotenv": "^8.0.0", - "dotenv-expand": "^5.1.0" - }, - "engines": { - "node": ">=6.0.0", - "npm": ">=6.0.0", - "yarn": ">=1.0.0" - } - }, "node_modules/lazystream": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", @@ -19831,7 +16965,7 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "devOptional": true, + "dev": true, "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -20092,6 +17226,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "dev": true, "engines": { "node": ">=6.11.5" } @@ -20100,6 +17235,7 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dev": true, "dependencies": { "big.js": "^5.2.2", "emojis-list": "^3.0.0", @@ -20118,15 +17254,11 @@ "lie": "3.1.1" } }, - "node_modules/localized-address-format": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/localized-address-format/-/localized-address-format-1.3.1.tgz", - "integrity": "sha512-kfwbtrN+VhlWDiEbUDNDLtuweFoe5F69n2qNERzO5tbINKrtdhw643Zgyy8HNjg8iwDxH7qjw9thHPx7G+NwDA==" - }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, "dependencies": { "p-locate": "^5.0.0" }, @@ -20151,7 +17283,8 @@ "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "dev": true }, "node_modules/lodash.defaults": { "version": "4.2.0", @@ -20186,7 +17319,7 @@ "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "devOptional": true + "dev": true }, "node_modules/lodash.truncate": { "version": "4.4.2", @@ -20278,6 +17411,7 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, "dependencies": { "yallist": "^3.0.2" } @@ -20290,34 +17424,6 @@ "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, - "node_modules/lz-string": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", - "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", - "bin": { - "lz-string": "bin/bin.js" - } - }, - "node_modules/make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dependencies": { - "pify": "^4.0.1", - "semver": "^5.6.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/make-dir/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "bin": { - "semver": "bin/semver" - } - }, "node_modules/make-iterator": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", @@ -20358,28 +17464,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/map-or-similar": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/map-or-similar/-/map-or-similar-1.5.0.tgz", - "integrity": "sha512-0aF7ZmVon1igznGI4VS30yugpduQW3y3GkcgGJOp7d8x8QrizhigUxjI/m2UojsXXto+jLAH3KSz+xOJTiORjg==" - }, "node_modules/map-values": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/map-values/-/map-values-1.0.1.tgz", "integrity": "sha512-BbShUnr5OartXJe1GeccAWtfro11hhgNJg6G9/UtWKjVGvV5U4C09cg5nk8JUevhXODaXY+hQ3xxMUKSs62ONQ==", "dev": true }, - "node_modules/map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==", - "dependencies": { - "object-visit": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/markdown-it": { "version": "12.3.2", "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", @@ -20552,16 +17642,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, "node_modules/mdn-data": { "version": "2.0.30", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", @@ -20577,6 +17657,7 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "dev": true, "engines": { "node": ">= 0.6" } @@ -20585,6 +17666,7 @@ "version": "3.5.3", "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", + "dev": true, "dependencies": { "fs-monkey": "^1.0.4" }, @@ -20602,23 +17684,6 @@ "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==" }, - "node_modules/memoizerific": { - "version": "1.11.3", - "resolved": "https://registry.npmjs.org/memoizerific/-/memoizerific-1.11.3.tgz", - "integrity": "sha512-/EuHYwAPdLtXwAwSZkh/Gutery6pD2KYd44oQLhAvQp/50mpyduZh8Q7PYHXTCJ+wuXxt7oij2LXyIJOOYFPog==", - "dependencies": { - "map-or-similar": "^1.5.0" - } - }, - "node_modules/memory-fs": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", - "integrity": "sha512-cda4JKCxReDXFXRqOHPQscuIYg1PvxbE2S2GP45rnwfEK+vZaXC8C1OFvdHIbgw0DLzowXGVoxLaAmlgRy14GQ==", - "dependencies": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" - } - }, "node_modules/meow": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz", @@ -20781,6 +17846,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "dev": true, "funding": { "url": "https://github.com/sponsors/sindresorhus" } @@ -20788,7 +17854,8 @@ "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true }, "node_modules/merge2": { "version": "1.4.1", @@ -20808,6 +17875,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "dev": true, "engines": { "node": ">= 0.6" } @@ -20818,29 +17886,12 @@ "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dependencies": { "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/miller-rabin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", - "dependencies": { - "bn.js": "^4.0.0", - "brorand": "^1.0.1" + "picomatch": "^2.3.1" }, - "bin": { - "miller-rabin": "bin/miller-rabin" + "engines": { + "node": ">=8.6" } }, - "node_modules/miller-rabin/node_modules/bn.js": { - "version": "4.12.2", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", - "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==" - }, "node_modules/mime": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", @@ -20890,14 +17941,6 @@ "node": ">=4" } }, - "node_modules/min-document": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", - "integrity": "sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ==", - "dependencies": { - "dom-walk": "^0.1.0" - } - }, "node_modules/min-indent": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", @@ -20948,12 +17991,8 @@ "node_modules/minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" - }, - "node_modules/minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==" + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true }, "node_modules/minimatch": { "version": "9.0.3", @@ -20974,6 +18013,7 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -21009,44 +18049,12 @@ "node": ">=16 || 14 >=14.17" } }, - "node_modules/mississippi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", - "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", - "dependencies": { - "concat-stream": "^1.5.0", - "duplexify": "^3.4.2", - "end-of-stream": "^1.1.0", - "flush-write-stream": "^1.0.0", - "from2": "^2.1.0", - "parallel-transform": "^1.1.0", - "pump": "^3.0.0", - "pumpify": "^1.3.3", - "stream-each": "^1.1.0", - "through2": "^2.0.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, "node_modules/mitt": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", "dev": true }, - "node_modules/mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "dependencies": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/mixin-object": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/mixin-object/-/mixin-object-2.0.1.tgz", @@ -21082,6 +18090,7 @@ "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, "dependencies": { "minimist": "^1.2.6" }, @@ -21117,37 +18126,6 @@ "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-11.18.1.tgz", "integrity": "sha512-49Kt+HKjtbJKLtgO/LKj9Ld+6vw9BjH5d9sc40R/kVyH8GLAXgT42M2NnuPcJNuA3s9ZfZBUcwIgpmZWGEE+hA==" }, - "node_modules/move-concurrently": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", - "integrity": "sha512-hdrFxZOycD/g6A6SoI2bB5NA/5NEqD0569+S47WZhPvm46sD50ZHdYaFmnua5lndde9rCHGjmfK7Z8BuCt/PcQ==", - "deprecated": "This package is no longer supported.", - "dependencies": { - "aproba": "^1.1.1", - "copy-concurrently": "^1.0.0", - "fs-write-stream-atomic": "^1.0.8", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.3" - } - }, - "node_modules/move-concurrently/node_modules/aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" - }, - "node_modules/move-concurrently/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, "node_modules/mrmime": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", @@ -21191,12 +18169,6 @@ "thenify-all": "^1.0.0" } }, - "node_modules/nan": { - "version": "2.22.2", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.22.2.tgz", - "integrity": "sha512-DANghxFkS1plDdRsX0X9pm0Z6SJNN6gBdtXfanwoZ8hooC5gosGFSBGRYHUVPz1asKA/kMRqDRdHrluZ61SpBQ==", - "optional": true - }, "node_modules/nanoid": { "version": "5.1.5", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.5.tgz", @@ -21214,37 +18186,17 @@ "node": "^18 || >=20" } }, - "node_modules/nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "devOptional": true + "dev": true }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true, "engines": { "node": ">= 0.6" } @@ -21252,7 +18204,8 @@ "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true }, "node_modules/netmask": { "version": "2.0.2", @@ -21276,6 +18229,7 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "dev": true, "optional": true }, "node_modules/node-fetch": { @@ -21335,56 +18289,6 @@ "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", "dev": true }, - "node_modules/node-libs-browser": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", - "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", - "dependencies": { - "assert": "^1.1.1", - "browserify-zlib": "^0.2.0", - "buffer": "^4.3.0", - "console-browserify": "^1.1.0", - "constants-browserify": "^1.0.0", - "crypto-browserify": "^3.11.0", - "domain-browser": "^1.1.1", - "events": "^3.0.0", - "https-browserify": "^1.0.0", - "os-browserify": "^0.3.0", - "path-browserify": "0.0.1", - "process": "^0.11.10", - "punycode": "^1.2.4", - "querystring-es3": "^0.2.0", - "readable-stream": "^2.3.3", - "stream-browserify": "^2.0.1", - "stream-http": "^2.7.2", - "string_decoder": "^1.0.0", - "timers-browserify": "^2.0.4", - "tty-browserify": "0.0.0", - "url": "^0.11.0", - "util": "^0.11.0", - "vm-browserify": "^1.0.1" - } - }, - "node_modules/node-libs-browser/node_modules/buffer": { - "version": "4.9.2", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", - "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", - "dependencies": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" - } - }, - "node_modules/node-libs-browser/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" - }, - "node_modules/node-libs-browser/node_modules/punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==" - }, "node_modules/node-releases": { "version": "2.0.19", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", @@ -21563,18 +18467,6 @@ "node": ">=8" } }, - "node_modules/npmlog": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", - "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", - "deprecated": "This package is no longer supported.", - "dependencies": { - "are-we-there-yet": "^2.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^3.0.0", - "set-blocking": "^2.0.0" - } - }, "node_modules/nth-check": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", @@ -21600,53 +18492,6 @@ "node": ">=0.10.0" } }, - "node_modules/object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==", - "dependencies": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/is-descriptor": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.7.tgz", - "integrity": "sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==", - "dependencies": { - "is-accessor-descriptor": "^1.0.1", - "is-data-descriptor": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object-copy/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/object-filter": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/object-filter/-/object-filter-1.0.2.tgz", @@ -21665,6 +18510,7 @@ "version": "1.13.4", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true, "engines": { "node": ">= 0.4" }, @@ -21695,21 +18541,11 @@ "node": ">= 0.4" } }, - "node_modules/object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==", - "dependencies": { - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/object.assign": { "version": "4.1.7", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "dev": true, "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", @@ -21837,6 +18673,7 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dev": true, "dependencies": { "ee-first": "1.1.1" }, @@ -21919,27 +18756,11 @@ "opener": "bin/opener-bin.js" } }, - "node_modules/optimist": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz", - "integrity": "sha512-TCx0dXQzVtSCg2OgY/bO9hjM9cV4XYx09TVK+s3+FhkjT6LovsLe+pPMzpWf+6yXK/hUizs2gUoTw3jHM0VaTQ==", - "dependencies": { - "wordwrap": "~0.0.2" - } - }, - "node_modules/optimist/node_modules/wordwrap": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha512-1tMA907+V4QmxV7dbRvb4/8MaRALK6q9Abid3ndMYnbyo8piisCmeONVqVSXqQA3KaP4SLt5b7ud6E2sqP8TFw==", - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", - "devOptional": true, + "dev": true, "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", @@ -22070,11 +18891,6 @@ "node": ">=4" } }, - "node_modules/os-browserify": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", - "integrity": "sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==" - }, "node_modules/os-homedir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", @@ -22131,6 +18947,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, "dependencies": { "yocto-queue": "^0.1.0" }, @@ -22145,6 +18962,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, "dependencies": { "p-limit": "^3.0.2" }, @@ -22181,6 +18999,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, "engines": { "node": ">=6" } @@ -22257,21 +19076,6 @@ "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==" }, - "node_modules/pako": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" - }, - "node_modules/parallel-transform": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", - "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", - "dependencies": { - "cyclist": "^1.0.1", - "inherits": "^2.0.3", - "readable-stream": "^2.1.5" - } - }, "node_modules/param-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", @@ -22297,22 +19101,6 @@ "node": ">=6" } }, - "node_modules/parse-asn1": { - "version": "5.1.7", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.7.tgz", - "integrity": "sha512-CTM5kuWR3sx9IFamcl5ErfPl6ea/N8IYwiJ+vpeB2g+1iknv7zBl5uPwbMbRVznRVbrNY6lGuDoE5b30grmbqg==", - "dependencies": { - "asn1.js": "^4.10.1", - "browserify-aes": "^1.2.0", - "evp_bytestokey": "^1.0.3", - "hash-base": "~3.0", - "pbkdf2": "^3.1.2", - "safe-buffer": "^5.2.1" - }, - "engines": { - "node": ">= 0.10" - } - }, "node_modules/parse-cache-control": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parse-cache-control/-/parse-cache-control-1.0.1.tgz", @@ -22385,6 +19173,7 @@ "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, "engines": { "node": ">= 0.8" } @@ -22398,19 +19187,6 @@ "tslib": "^2.0.3" } }, - "node_modules/pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-browserify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", - "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==" - }, "node_modules/path-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/path-case/-/path-case-3.0.4.tgz", @@ -22420,16 +19196,11 @@ "tslib": "^2.0.3" } }, - "node_modules/path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q==", - "optional": true - }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, "engines": { "node": ">=8" } @@ -22503,7 +19274,8 @@ "node_modules/path-to-regexp": { "version": "0.1.12", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==" + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "dev": true }, "node_modules/path-type": { "version": "4.0.0", @@ -22513,21 +19285,6 @@ "node": ">=8" } }, - "node_modules/pbkdf2": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", - "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", - "dependencies": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - }, - "engines": { - "node": ">=0.12" - } - }, "node_modules/pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", @@ -22587,17 +19344,6 @@ "node": ">= 6" } }, - "node_modules/pkg-dir": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", - "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", - "dependencies": { - "find-up": "^5.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/playwright": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.52.0.tgz", @@ -22669,37 +19415,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/polished": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/polished/-/polished-4.3.1.tgz", - "integrity": "sha512-OBatVyC/N7SCW/FaDHrSd+vn0o5cS855TOmYi4OkdWUMSJCET/xip//ch8xGUvtr3i44X9LVyWwQlRMTN3pwSA==", - "dependencies": { - "@babel/runtime": "^7.17.8" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/polished/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/posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/possible-typed-array-names": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "dev": true, "engines": { "node": ">= 0.4" } @@ -23439,7 +20159,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "devOptional": true, + "dev": true, "engines": { "node": ">= 0.8.0" } @@ -23483,38 +20203,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/pretty-format": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", - "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", - "dependencies": { - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^17.0.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/pretty-hrtime": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", - "integrity": "sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/prismjs": { "version": "1.30.0", "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz", @@ -23534,7 +20222,8 @@ "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true }, "node_modules/progress": { "version": "2.0.3", @@ -23545,16 +20234,6 @@ "node": ">=0.4.0" } }, - "node_modules/promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==" - }, - "node_modules/promise-polyfill": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-8.3.0.tgz", - "integrity": "sha512-H5oELycFml5yto/atYqmjyigJoAo3+OXwolYiH7OfQuYlAqhxNvTfiNMbV9hsC6Yp83yE5r2KTVmtrG6R9i6Pg==" - }, "node_modules/prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", @@ -23587,6 +20266,7 @@ "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" @@ -23664,11 +20344,6 @@ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "dev": true }, - "node_modules/prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==" - }, "node_modules/ps-list": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/ps-list/-/ps-list-8.1.1.tgz", @@ -23699,47 +20374,11 @@ "url": "https://github.com/sponsors/lupomontero" } }, - "node_modules/public-encrypt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", - "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", - "dependencies": { - "bn.js": "^4.1.0", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "parse-asn1": "^5.0.0", - "randombytes": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/public-encrypt/node_modules/bn.js": { - "version": "4.12.2", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", - "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==" - }, "node_modules/pump": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/pumpify": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "dependencies": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - } - }, - "node_modules/pumpify/node_modules/pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -23749,6 +20388,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, "engines": { "node": ">=6" } @@ -23792,28 +20432,6 @@ } ] }, - "node_modules/qs": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", - "dependencies": { - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/querystring-es3": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", - "integrity": "sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==", - "engines": { - "node": ">=0.4.x" - } - }, "node_modules/querystringify": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", @@ -23923,38 +20541,22 @@ "node_modules/raf-schd": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.3.tgz", - "integrity": "sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==" - }, - "node_modules/ramda": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.28.0.tgz", - "integrity": "sha512-9QnLuG/kPVgWvMQ4aODhsBUFKOUmnbUnsSXACv+NCQZcHbeb+v8Lodp8OVxtRULN1/xOyYLLaL6npE6dMq5QTA==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ramda" - } + "integrity": "sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==" }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, "dependencies": { "safe-buffer": "^5.1.0" } }, - "node_modules/randomfill": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", - "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", - "dependencies": { - "randombytes": "^2.0.5", - "safe-buffer": "^5.1.0" - } - }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, "engines": { "node": ">= 0.6" } @@ -23963,6 +20565,7 @@ "version": "2.5.2", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dev": true, "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -24108,15 +20711,6 @@ "react": ">=16.8.0" } }, - "node_modules/react-merge-refs": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/react-merge-refs/-/react-merge-refs-1.1.0.tgz", - "integrity": "sha512-alTKsjEL0dKH/ru1Iyn7vliS2QRcBp9zZPGoWxUOvRGWPUYgjo+V01is7p04It6KhgrzhJGnIj9GgX8W4bZoCQ==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - } - }, "node_modules/react-property": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/react-property/-/react-property-2.0.2.tgz", @@ -24178,11 +20772,11 @@ } }, "node_modules/react-router": { - "version": "6.30.0", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.0.tgz", - "integrity": "sha512-D3X8FyH9nBcTSHGdEKurK7r8OYE1kKFn3d/CF+CoxbSHkxU7o37+Uh7eAHRXr6k2tSExXYO++07PeXJtA/dEhQ==", + "version": "6.30.3", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.3.tgz", + "integrity": "sha512-XRnlbKMTmktBkjCLE8/XcZFlnHvr2Ltdr1eJX4idL55/9BbORzyZEaIkBFDhFGCEWBBItsVrDxwx3gnisMitdw==", "dependencies": { - "@remix-run/router": "1.23.0" + "@remix-run/router": "1.23.2" }, "engines": { "node": ">=14.0.0" @@ -24192,12 +20786,12 @@ } }, "node_modules/react-router-dom": { - "version": "6.30.0", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.30.0.tgz", - "integrity": "sha512-x30B78HV5tFk8ex0ITwzC9TTZMua4jGyA9IUlH1JLQYQTFyxr/ZxwOJq7evg1JX1qGVUcvhsmQSKdPncQrjTgA==", + "version": "6.30.3", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.30.3.tgz", + "integrity": "sha512-pxPcv1AczD4vso7G4Z3TKcvlxK7g7TNt3/FNGMhfqyntocvYKj+GCatfigGDjbLozC4baguJ0ReCigoDJXb0ag==", "dependencies": { - "@remix-run/router": "1.23.0", - "react-router": "6.30.0" + "@remix-run/router": "1.23.2", + "react-router": "6.30.3" }, "engines": { "node": ">=14.0.0" @@ -24240,17 +20834,6 @@ "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==" }, - "node_modules/react-sizeme": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/react-sizeme/-/react-sizeme-3.0.2.tgz", - "integrity": "sha512-xOIAOqqSSmKlKFJLO3inBQBdymzDuXx4iuwkNcJmC96jeiOg5ojByvL+g3MW9LPEsojLbC6pf68zOfobK8IPlw==", - "dependencies": { - "element-resize-detector": "^1.2.2", - "invariant": "^2.2.4", - "shallowequal": "^1.1.0", - "throttle-debounce": "^3.0.1" - } - }, "node_modules/react-smooth": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-4.0.4.tgz", @@ -24454,6 +21037,7 @@ "version": "2.3.8", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -24467,12 +21051,14 @@ "node_modules/readable-stream/node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true }, "node_modules/readable-stream/node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true }, "node_modules/readdir-glob": { "version": "1.1.3", @@ -24611,12 +21197,14 @@ "node_modules/regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true }, "node_modules/regenerate-unicode-properties": { "version": "10.2.0", "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.0.tgz", "integrity": "sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==", + "dev": true, "dependencies": { "regenerate": "^1.4.2" }, @@ -24629,18 +21217,6 @@ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" }, - "node_modules/regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dependencies": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/regexp.prototype.flags": { "version": "1.5.4", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", @@ -24664,6 +21240,7 @@ "version": "6.2.0", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.2.0.tgz", "integrity": "sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA==", + "dev": true, "dependencies": { "regenerate": "^1.4.2", "regenerate-unicode-properties": "^10.2.0", @@ -24679,12 +21256,14 @@ "node_modules/regjsgen": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz", - "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==" + "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==", + "dev": true }, "node_modules/regjsparser": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.12.0.tgz", "integrity": "sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==", + "dev": true, "dependencies": { "jsesc": "~3.0.2" }, @@ -24696,6 +21275,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", + "dev": true, "bin": { "jsesc": "bin/jsesc" }, @@ -24708,28 +21288,6 @@ "resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.5.0.tgz", "integrity": "sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A==" }, - "node_modules/remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==", - "optional": true - }, - "node_modules/repeat-element": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", - "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", - "engines": { - "node": ">=0.10" - } - }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -24743,6 +21301,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -24837,16 +21396,11 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, "engines": { "node": ">=8" } }, - "node_modules/resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==", - "deprecated": "https://github.com/lydell/resolve-url#deprecated" - }, "node_modules/resolve.exports": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", @@ -24881,14 +21435,6 @@ "node": ">=8" } }, - "node_modules/ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "engines": { - "node": ">=0.12" - } - }, "node_modules/retry": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", @@ -24957,15 +21503,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } - }, "node_modules/robots-parser": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/robots-parser/-/robots-parser-3.0.1.tgz", @@ -25140,19 +21677,6 @@ "queue-microtask": "^1.2.2" } }, - "node_modules/run-queue": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", - "integrity": "sha512-ntymy489o0/QQplUDnpYAYUsO50K9SBrIVaKCWDOJzYJts0f9WH9RFJkyagebkw5+y1oi00R7ynNW/d12GBumg==", - "dependencies": { - "aproba": "^1.1.1" - } - }, - "node_modules/run-queue/node_modules/aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" - }, "node_modules/rxjs": { "version": "7.8.2", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", @@ -25216,18 +21740,11 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==", - "dependencies": { - "ret": "~0.1.10" - } - }, "node_modules/safe-regex-test": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "dev": true, "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", @@ -25249,6 +21766,7 @@ "version": "1.88.0", "resolved": "https://registry.npmjs.org/sass/-/sass-1.88.0.tgz", "integrity": "sha512-sF6TWQqjFvr4JILXzG4ucGOLELkESHL+I5QJhh7CNaE+Yge0SI+ehCatsXhJ7ymU1hAFcIS3/PBpjdIbXoyVbg==", + "dev": true, "dependencies": { "chokidar": "^4.0.0", "immutable": "^5.0.2", @@ -25305,6 +21823,7 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dev": true, "dependencies": { "readdirp": "^4.0.1" }, @@ -25319,6 +21838,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true, "engines": { "node": ">= 14.18.0" }, @@ -25351,6 +21871,7 @@ "version": "4.3.2", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.2.tgz", "integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==", + "dev": true, "dependencies": { "@types/json-schema": "^7.0.9", "ajv": "^8.9.0", @@ -25369,6 +21890,7 @@ "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -25384,6 +21906,7 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, "dependencies": { "fast-deep-equal": "^3.1.3" }, @@ -25394,7 +21917,8 @@ "node_modules/schema-utils/node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true }, "node_modules/select-hose": { "version": "2.0.0", @@ -25419,6 +21943,7 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, "bin": { "semver": "bin/semver.js" } @@ -25427,6 +21952,7 @@ "version": "0.19.0", "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "dev": true, "dependencies": { "debug": "2.6.9", "depd": "2.0.0", @@ -25450,6 +21976,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, "dependencies": { "ms": "2.0.0" } @@ -25457,12 +21984,14 @@ "node_modules/send/node_modules/debug/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true }, "node_modules/send/node_modules/encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "dev": true, "engines": { "node": ">= 0.8" } @@ -25471,6 +22000,7 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, "bin": { "mime": "cli.js" }, @@ -25492,6 +22022,7 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, "dependencies": { "randombytes": "^2.1.0" } @@ -25578,6 +22109,7 @@ "version": "1.16.2", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "dev": true, "dependencies": { "encodeurl": "~2.0.0", "escape-html": "~1.0.3", @@ -25588,11 +22120,6 @@ "node": ">= 0.8.0" } }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" - }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", @@ -25637,76 +22164,17 @@ "node": ">= 0.4" } }, - "node_modules/set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "dependencies": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/set-value/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/set-value/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/set-value/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==" - }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" - }, - "node_modules/sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - }, - "bin": { - "sha.js": "bin.js" - } + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true }, "node_modules/shallow-clone": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, "dependencies": { "kind-of": "^6.0.2" }, @@ -25756,6 +22224,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dev": true, "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", @@ -25774,6 +22243,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dev": true, "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3" @@ -25789,6 +22259,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", @@ -25806,6 +22277,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", @@ -25823,212 +22295,87 @@ "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" - }, - "node_modules/simple-git": { - "version": "3.27.0", - "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.27.0.tgz", - "integrity": "sha512-ivHoFS9Yi9GY49ogc6/YAi3Fl9ROnF4VyubNylgCkA+RVqLaKWnDSzXOVzya8csELIaWaYNutsEuAhZrtOjozA==", - "dev": true, - "dependencies": { - "@kwsites/file-exists": "^1.1.1", - "@kwsites/promise-deferred": "^1.1.1", - "debug": "^4.3.5" - }, - "funding": { - "type": "github", - "url": "https://github.com/steveukx/git-js?sponsor=1" - } - }, - "node_modules/sirv": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.4.tgz", - "integrity": "sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==", - "dev": true, - "dependencies": { - "@polka/url": "^1.0.0-next.24", - "mrmime": "^2.0.0", - "totalist": "^3.0.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "engines": { - "node": ">=8" - } - }, - "node_modules/slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "dev": true, - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/snake-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", - "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", - "dependencies": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dependencies": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dependencies": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", - "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dependencies": { - "kind-of": "^3.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-util/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/simple-git": { + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.27.0.tgz", + "integrity": "sha512-ivHoFS9Yi9GY49ogc6/YAi3Fl9ROnF4VyubNylgCkA+RVqLaKWnDSzXOVzya8csELIaWaYNutsEuAhZrtOjozA==", + "dev": true, "dependencies": { - "ms": "2.0.0" + "@kwsites/file-exists": "^1.1.1", + "@kwsites/promise-deferred": "^1.1.1", + "debug": "^4.3.5" + }, + "funding": { + "type": "github", + "url": "https://github.com/steveukx/git-js?sponsor=1" } }, - "node_modules/snapdragon/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "node_modules/sirv": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.4.tgz", + "integrity": "sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==", + "dev": true, "dependencies": { - "is-descriptor": "^0.1.0" + "@polka/url": "^1.0.0-next.24", + "mrmime": "^2.0.0", + "totalist": "^3.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">= 10" } }, - "node_modules/snapdragon/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dependencies": { - "is-extendable": "^0.1.0" - }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/snapdragon/node_modules/is-descriptor": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.7.tgz", - "integrity": "sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==", + "node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, "dependencies": { - "is-accessor-descriptor": "^1.0.1", - "is-data-descriptor": "^1.0.1" + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, - "node_modules/snapdragon/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">= 6.0.0", + "npm": ">= 3.0.0" } }, - "node_modules/snapdragon/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/snapdragon/node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", - "engines": { - "node": ">=0.10.0" + "node_modules/snake-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", + "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" } }, "node_modules/sockjs": { @@ -26079,11 +22426,6 @@ "node": ">= 14" } }, - "node_modules/source-list-map": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", - "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==" - }, "node_modules/source-map": { "version": "0.7.4", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", @@ -26134,23 +22476,11 @@ "node": ">=0.10.0" } }, - "node_modules/source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "deprecated": "See https://github.com/lydell/source-map-resolve#deprecated", - "dependencies": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, "node_modules/source-map-support": { "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -26160,16 +22490,11 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, "engines": { "node": ">=0.10.0" } }, - "node_modules/source-map-url": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", - "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", - "deprecated": "See https://github.com/lydell/source-map-url#deprecated" - }, "node_modules/spawnd": { "version": "9.0.2", "resolved": "https://registry.npmjs.org/spawnd/-/spawnd-9.0.2.tgz", @@ -26295,30 +22620,11 @@ "node": ">=8.0" } }, - "node_modules/split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dependencies": { - "extend-shallow": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/sprintf-js": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==" }, - "node_modules/ssri": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz", - "integrity": "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==", - "dependencies": { - "figgy-pudding": "^3.5.1" - } - }, "node_modules/stack-utils": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", @@ -26346,88 +22652,15 @@ "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==", "dev": true }, - "node_modules/static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==", - "dependencies": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-extend/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-extend/node_modules/is-descriptor": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.7.tgz", - "integrity": "sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==", - "dependencies": { - "is-accessor-descriptor": "^1.0.1", - "is-data-descriptor": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, "engines": { "node": ">= 0.8" } }, - "node_modules/stencil-store-storage": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/stencil-store-storage/-/stencil-store-storage-0.2.0.tgz", - "integrity": "sha512-4cnlgfPfQtdBi2Ulpc63ERvi3N3GidwDqx2hiZjR3VsPRQdYPxSgqCVRlD+Tsnx8BkF412FIxudh6ap2KiWGyw==", - "peerDependencies": { - "@stencil/store": ">1.3.0" - } - }, - "node_modules/stencil-wormhole": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/stencil-wormhole/-/stencil-wormhole-3.4.1.tgz", - "integrity": "sha512-ppYTcWTJnIl4ZAKwF39LTA9f/ypHfbVefsHdN2hpMQGrR57wt1TieZo9tlCM/r1Y4SFiZ5yz/cjho564C921Xw==" - }, - "node_modules/stop-iteration-iterator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", - "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", - "dependencies": { - "es-errors": "^1.3.0", - "internal-slot": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/store2": { - "version": "2.14.4", - "resolved": "https://registry.npmjs.org/store2/-/store2-2.14.4.tgz", - "integrity": "sha512-srTItn1GOvyvOycgxjAnPA63FZNwy0PTyUBFMHRM+hVFltAeoh0LmNBz9SZqUS9mMqGk8rfyWyXn3GH5ReJ8Zw==" - }, - "node_modules/stream-browserify": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", - "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", - "dependencies": { - "inherits": "~2.0.1", - "readable-stream": "^2.0.2" - } - }, "node_modules/stream-buffers": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-3.0.3.tgz", @@ -26437,32 +22670,6 @@ "node": ">= 0.10.0" } }, - "node_modules/stream-each": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", - "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", - "dependencies": { - "end-of-stream": "^1.1.0", - "stream-shift": "^1.0.0" - } - }, - "node_modules/stream-http": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", - "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", - "dependencies": { - "builtin-status-codes": "^3.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.3.6", - "to-arraybuffer": "^1.0.0", - "xtend": "^4.0.0" - } - }, - "node_modules/stream-shift": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz", - "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==" - }, "node_modules/streamx": { "version": "2.22.0", "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.22.0.tgz", @@ -26480,6 +22687,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, "dependencies": { "safe-buffer": "~5.1.0" } @@ -26487,7 +22695,8 @@ "node_modules/string_decoder/node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true }, "node_modules/string-length": { "version": "4.0.2", @@ -26703,7 +22912,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "devOptional": true, + "dev": true, "engines": { "node": ">=8" }, @@ -27309,14 +23518,6 @@ "@tannin/plural-forms": "^1.1.0" } }, - "node_modules/tapable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", - "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", - "engines": { - "node": ">=6" - } - }, "node_modules/tar-fs": { "version": "3.0.8", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.8.tgz", @@ -27372,29 +23573,6 @@ "node": ">= 6" } }, - "node_modules/telejson": { - "version": "6.0.8", - "resolved": "https://registry.npmjs.org/telejson/-/telejson-6.0.8.tgz", - "integrity": "sha512-nerNXi+j8NK1QEfBHtZUN/aLdDcyupA//9kAboYLrtzZlPLpUfqbVGWb9zz91f/mIjRbAYhbgtnJHY8I1b5MBg==", - "dependencies": { - "@types/is-function": "^1.0.0", - "global": "^4.4.0", - "is-function": "^1.0.2", - "is-regex": "^1.1.2", - "is-symbol": "^1.0.3", - "isobject": "^4.0.0", - "lodash": "^4.17.21", - "memoizerific": "^1.11.3" - } - }, - "node_modules/telejson/node_modules/isobject": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-4.0.0.tgz", - "integrity": "sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/terminal-link": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", @@ -27415,6 +23593,7 @@ "version": "5.39.0", "resolved": "https://registry.npmjs.org/terser/-/terser-5.39.0.tgz", "integrity": "sha512-LBAhFyLho16harJoWMg/nZsQYgTrg5jXOn2nCYjRUcZZEdE3qa2zb8QEDRUGVZBW4rlazf2fxkg8tztybTaqWw==", + "dev": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.8.2", @@ -27432,6 +23611,7 @@ "version": "5.3.14", "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.14.tgz", "integrity": "sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw==", + "dev": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", "jest-worker": "^27.4.5", @@ -27465,6 +23645,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, "dependencies": { "@types/node": "*", "merge-stream": "^2.0.0", @@ -27478,6 +23659,7 @@ "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -27491,7 +23673,8 @@ "node_modules/terser/node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true }, "node_modules/test-exclude": { "version": "6.0.0", @@ -27542,7 +23725,7 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "devOptional": true + "dev": true }, "node_modules/thenify": { "version": "3.3.1", @@ -27569,46 +23752,18 @@ "integrity": "sha512-GsjP92xycMK8qLTcQCacgzvffYzEqe29wyz3zdKVXlfRD5Kz1NatCTOZEeDaSd6uCZXvGd2CNVtQ89RNIhJWvA==", "dev": true }, - "node_modules/throttle-debounce": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-3.0.1.tgz", - "integrity": "sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg==", - "engines": { - "node": ">=10" - } - }, "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", "dev": true }, - "node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, "node_modules/thunky": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", "dev": true }, - "node_modules/timers-browserify": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz", - "integrity": "sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==", - "dependencies": { - "setimmediate": "^1.0.4" - }, - "engines": { - "node": ">=0.6.0" - } - }, "node_modules/tiny-invariant": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", @@ -27647,47 +23802,6 @@ "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", "dev": true }, - "node_modules/to-arraybuffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", - "integrity": "sha512-okFlQcoGTi4LQBG/PgSYblw9VOyptsz2KJZqc6qtgGdes8VktzUQkj4BI2blit072iS8VODNcMA+tvnS9dnuMA==" - }, - "node_modules/to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==", - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-object-path/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dependencies": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -27703,6 +23817,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true, "engines": { "node": ">=0.6" } @@ -27803,14 +23918,6 @@ "typescript": ">=4.2.0" } }, - "node_modules/ts-dedent": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz", - "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==", - "engines": { - "node": ">=6.10" - } - }, "node_modules/ts-interface-checker": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", @@ -27875,16 +23982,11 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true }, - "node_modules/tty-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", - "integrity": "sha512-JVa5ijo+j/sOoHGjw0sxw734b1LhBkQ3bvUGNdxnVXDCX81Yx7TFgnZygxrIIWn23hbfTaMYLwRmAxFyDuFmIw==" - }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "devOptional": true, + "dev": true, "dependencies": { "prelude-ls": "^1.2.1" }, @@ -27917,6 +24019,7 @@ "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" @@ -28008,7 +24111,8 @@ "node_modules/typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", + "dev": true }, "node_modules/typedarray-to-buffer": { "version": "3.1.5", @@ -28023,6 +24127,7 @@ "version": "5.9.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, "peer": true, "bin": { "tsc": "bin/tsc", @@ -28042,7 +24147,7 @@ "version": "3.19.3", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", - "devOptional": true, + "dev": true, "bin": { "uglifyjs": "bin/uglifyjs" }, @@ -28099,17 +24204,16 @@ } }, "node_modules/undici-types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", - "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", - "dev": true, - "optional": true, - "peer": true + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz", + "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", + "dev": true }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", + "dev": true, "engines": { "node": ">=4" } @@ -28118,6 +24222,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dev": true, "dependencies": { "unicode-canonical-property-names-ecmascript": "^2.0.0", "unicode-property-aliases-ecmascript": "^2.0.0" @@ -28130,54 +24235,18 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.0.tgz", "integrity": "sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==", + "dev": true, "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-property-aliases-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", - "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", - "engines": { - "node": ">=4" - } - }, - "node_modules/union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "dependencies": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/union-value/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unique-filename": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", - "dependencies": { - "unique-slug": "^2.0.0" + "node": ">=4" } }, - "node_modules/unique-slug": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", - "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", - "dependencies": { - "imurmurhash": "^0.1.4" + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "dev": true, + "engines": { + "node": ">=4" } }, "node_modules/unique-string": { @@ -28192,81 +24261,15 @@ "node": ">=8" } }, - "node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "engines": { - "node": ">= 10.0.0" - } - }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "dev": true, "engines": { "node": ">= 0.8" } }, - "node_modules/unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ==", - "dependencies": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unset-value/node_modules/has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==", - "dependencies": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unset-value/node_modules/has-value/node_modules/isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==", - "dependencies": { - "isarray": "1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unset-value/node_modules/has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unset-value/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" - }, - "node_modules/upath": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", - "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", - "optional": true, - "engines": { - "node": ">=4", - "yarn": "*" - } - }, "node_modules/update-browserslist-db": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", @@ -28316,6 +24319,7 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, "dependencies": { "punycode": "^2.1.0" } @@ -28329,24 +24333,6 @@ "node": ">= 0.10" } }, - "node_modules/urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==", - "deprecated": "Please see https://github.com/lydell/urix#deprecated" - }, - "node_modules/url": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.4.tgz", - "integrity": "sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==", - "dependencies": { - "punycode": "^1.4.1", - "qs": "^6.12.3" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/url-loader": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-4.1.1.tgz", @@ -28402,19 +24388,6 @@ "requires-port": "^1.0.0" } }, - "node_modules/url/node_modules/punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==" - }, - "node_modules/use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/use-debounce": { "version": "10.0.4", "resolved": "https://registry.npmjs.org/use-debounce/-/use-debounce-10.0.4.tgz", @@ -28447,28 +24420,16 @@ "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, - "node_modules/util": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", - "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", - "dependencies": { - "inherits": "2.0.3" - } - }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, - "node_modules/util/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==" - }, "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "dev": true, "engines": { "node": ">= 0.4.0" } @@ -28544,6 +24505,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "dev": true, "engines": { "node": ">= 0.8" } @@ -28569,11 +24531,6 @@ "d3-timer": "^3.0.1" } }, - "node_modules/vm-browserify": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", - "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==" - }, "node_modules/w3c-xmlserializer": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", @@ -28618,6 +24575,7 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", + "dev": true, "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" @@ -28626,264 +24584,6 @@ "node": ">=10.13.0" } }, - "node_modules/watchpack-chokidar2": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz", - "integrity": "sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww==", - "optional": true, - "dependencies": { - "chokidar": "^2.1.8" - } - }, - "node_modules/watchpack-chokidar2/node_modules/anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "optional": true, - "dependencies": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - } - }, - "node_modules/watchpack-chokidar2/node_modules/anymatch/node_modules/normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", - "optional": true, - "dependencies": { - "remove-trailing-separator": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/watchpack-chokidar2/node_modules/binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/watchpack-chokidar2/node_modules/braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "optional": true, - "dependencies": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/watchpack-chokidar2/node_modules/braces/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "optional": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/watchpack-chokidar2/node_modules/chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", - "optional": true, - "dependencies": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - }, - "optionalDependencies": { - "fsevents": "^1.2.7" - } - }, - "node_modules/watchpack-chokidar2/node_modules/fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", - "optional": true, - "dependencies": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/watchpack-chokidar2/node_modules/fill-range/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "optional": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/watchpack-chokidar2/node_modules/fsevents": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", - "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", - "deprecated": "Upgrade to fsevents v2 to mitigate potential security issues", - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "dependencies": { - "bindings": "^1.5.0", - "nan": "^2.12.1" - }, - "engines": { - "node": ">= 4.0" - } - }, - "node_modules/watchpack-chokidar2/node_modules/glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", - "optional": true, - "dependencies": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - } - }, - "node_modules/watchpack-chokidar2/node_modules/glob-parent/node_modules/is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", - "optional": true, - "dependencies": { - "is-extglob": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/watchpack-chokidar2/node_modules/is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q==", - "optional": true, - "dependencies": { - "binary-extensions": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/watchpack-chokidar2/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/watchpack-chokidar2/node_modules/is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", - "optional": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/watchpack-chokidar2/node_modules/is-number/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "optional": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/watchpack-chokidar2/node_modules/micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "optional": true, - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/watchpack-chokidar2/node_modules/readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "optional": true, - "dependencies": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/watchpack-chokidar2/node_modules/to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", - "optional": true, - "dependencies": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/wbuf": { "version": "1.7.3", "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", @@ -28921,6 +24621,7 @@ "version": "5.99.8", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.99.8.tgz", "integrity": "sha512-lQ3CPiSTpfOnrEGeXDwoq5hIGzSjmwD72GdfVzF7CQAI7t47rJG9eDWvcEkEn3CUQymAElVvDg3YNTlCYj+qUQ==", + "dev": true, "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.6", @@ -29284,6 +24985,7 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "dev": true, "engines": { "node": ">=10.13.0" } @@ -29292,6 +24994,7 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, "engines": { "node": ">=6" } @@ -29380,6 +25083,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "dev": true, "dependencies": { "is-bigint": "^1.1.0", "is-boolean-object": "^1.2.1", @@ -29425,6 +25129,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, "dependencies": { "is-map": "^2.0.3", "is-set": "^2.0.3", @@ -29442,6 +25147,7 @@ "version": "1.1.19", "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", + "dev": true, "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", @@ -29458,14 +25164,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "dependencies": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, "node_modules/wildcard": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", @@ -29476,24 +25174,11 @@ "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "devOptional": true, + "dev": true, "engines": { "node": ">=0.10.0" } }, - "node_modules/wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==" - }, - "node_modules/worker-farm": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", - "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", - "dependencies": { - "errno": "~0.1.7" - } - }, "node_modules/wp-prettier": { "version": "2.8.5", "resolved": "https://registry.npmjs.org/wp-prettier/-/wp-prettier-2.8.5.tgz", @@ -29606,14 +25291,6 @@ "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", "dev": true }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "engines": { - "node": ">=0.4" - } - }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -29626,7 +25303,8 @@ "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true }, "node_modules/yaml": { "version": "2.7.1", @@ -29677,9 +25355,9 @@ } }, "node_modules/yjs": { - "version": "13.6.29", - "resolved": "https://registry.npmjs.org/yjs/-/yjs-13.6.29.tgz", - "integrity": "sha512-kHqDPdltoXH+X4w1lVmMtddE3Oeqq48nM40FD5ojTd8xYhQpzIDcfE2keMSU5bAgRPJBe225WTUdyUgj1DtbiQ==", + "version": "13.6.30", + "resolved": "https://registry.npmjs.org/yjs/-/yjs-13.6.30.tgz", + "integrity": "sha512-vv/9h42eCMC81ZHDFswuu/MKzkl/vyq1BhaNGfHyOonwlG4CJbQF4oiBBJPvfdeCt/PlVDWh7Nov9D34YY09uQ==", "peer": true, "dependencies": { "lib0": "^0.2.99" @@ -29697,6 +25375,7 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, "engines": { "node": ">=10" }, diff --git a/package.json b/package.json index 701ad5377..a75ea54ac 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,11 @@ { "name": "sureforms", - "version": "2.8.1", + "version": "2.8.2", "description": "A simple yet powerful way to add forms to your website.", "main": "index.js", "scripts": { "start": "wp-scripts start", - "build": "wp-scripts build && npm run build:sass && grunt minify", + "build": "export SASS_SILENCE_DEPRECATION=legacy-js-api:import:global-builtin && wp-scripts build && npm run build:sass && grunt minify", "build:script": "wp-scripts build", "build:sass": "node scripts/generate-assets-files.js", "makepot": "wp i18n make-pot . --skip-audit --exclude='.dev,.github,.wordpress-org,docs,src,node_modules,tests,vendor,wordpress' languages/sureforms.pot", @@ -54,6 +54,7 @@ }, "homepage": "https://github.com/brainstormforce/sureforms#readme", "devDependencies": { + "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@emotion/core": "^11.0.0", "@playwright/test": "^1.48.2", "@tailwindcss/forms": "^0.5.3", @@ -89,7 +90,6 @@ "@fortawesome/free-solid-svg-icons": "^6.4.0", "@fortawesome/react-fontawesome": "^0.2.0", "@lodder/grunt-postcss": "^3.1.1", - "@surecart/components-react": "^1.0.1", "@tanstack/react-query": "^5.90.5", "@tomickigrzegorz/react-circular-progress-bar": "^1.1.2", "@wordpress/api-fetch": "^6.42.0", @@ -99,7 +99,7 @@ "clsx": "^2.1.1", "cssnano": "^6.0.1", "date-fns": "^4.1.0", - "dompurify": "^3.3.0", + "dompurify": "^3.3.3", "gpt-po": "1.1.1", "html-react-parser": "^5.0.7", "intl-tel-input": "^25.14.0", @@ -119,6 +119,6 @@ "use-debounce": "^10.0.0" }, "volta": { - "node": "18.15.0" + "node": "20.20.1" } } \ No newline at end of file diff --git a/plugin-loader.php b/plugin-loader.php index ff0166a1d..67086b906 100644 --- a/plugin-loader.php +++ b/plugin-loader.php @@ -13,6 +13,7 @@ use SRFM\Admin\Notice_Manager; use SRFM\Inc\Abilities\Abilities_Registrar; use SRFM\Inc\Activator; +use SRFM\Inc\Admin\Editor_Nudge; use SRFM\Inc\Admin_Ajax; use SRFM\Inc\AI_Form_Builder\AI_Auth; use SRFM\Inc\AI_Form_Builder\AI_Form_Builder; @@ -212,6 +213,7 @@ public function load_classes() { Admin::get_instance(); // phpcs:ignore /** @phpstan-ignore-next-line */ -- Class is loaded dynamically in WordPress Notice_Manager::get_instance(); + Editor_Nudge::get_instance(); } Payments::get_instance(); Duplicate_Form::get_instance(); diff --git a/readme.txt b/readme.txt index 6bb34ee06..fdd93df0b 100644 --- a/readme.txt +++ b/readme.txt @@ -4,7 +4,7 @@ Tags: forms, contact form, custom form, payment form, form builder Requires at least: 6.4 Tested up to: 6.9.4 Requires PHP: 7.4 -Stable tag: 2.8.1 +Stable tag: 2.8.2 License: GPLv2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html @@ -478,6 +478,13 @@ You can collect payments securely through Stripe in the free version. PayPal pay You can report the issue 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.8.2 - 5th May 2026 = +* New: Added "Both" payment type so a single form can collect one-time and subscription payments together. +* New: Added Hidden field support for the payment block's dynamic amount. +* New: Added minimum character limit support for the Textarea field. +* Improvement: Added extension hooks for windowed entry caps in form restriction. +* Fix: Fixed AI Form Builder silent failures and replaced generic error messages with clearer feedback. +* Fix: Resolved an issue where the Confirm Email field could silently block form submission when the Email field was not marked as required. = 2.8.1 - 27th April 2026 = * New: Added support for dynamic default values on Dropdown and Multi-Choice fields. * New: Added {entry_id} smart tag for use in email templates, confirmations, and dynamic content. @@ -493,15 +500,6 @@ You can report the issue through our [Bug Bounty Program](https://brainstormforc * Fix: Fixed crash when saving a form containing the Register block. * Fix: Fixed inability to deselect a preselected option in single-selection controls (radio, dropdown) within the editor. * Fix: Fixed Quill rich text editor toolbar strings not being translatable. -= 2.7.1 - 9th April 2026 = -* New: Added a customizable Field Slug panel to all form blocks. -* New: Added Payment Description field to the Stripe payment block with smart tag support. -* Fix: Fixed Elementor form title toggle working in reverse. -* Fix: Fixed non-Latin character field labels generating unstable slugs that broke conditional confirmation logic. -* Fix: Fixed PHP warnings for undefined array keys in compliance settings and AI field mapping. -* Fix: Fixed slugs with underscores not mapping correctly during smart tag and integration processing. -* Fix: Fixed textarea values losing line breaks in {form:field} smart tags. -* Fix: Fixed {current_page_url} smart tag resolving to REST API URL in email notifications. The full changelog is available [here](https://sureforms.com/whats-new/). == Upgrade Notice == diff --git a/sass/blocks/default/components/payment-type-chooser.scss b/sass/blocks/default/components/payment-type-chooser.scss new file mode 100644 index 000000000..93f99b090 --- /dev/null +++ b/sass/blocks/default/components/payment-type-chooser.scss @@ -0,0 +1,100 @@ +@import "../utils/mixins.scss"; + +// BOTH MODE: dual-mode payment-type chooser. +// Mirrors the multi-choice block exactly so the visual language (border, +// padding, font-size, circle radio icons, primary-tinted checked state) is +// consistent with the rest of the form. + +.srfm-form-container { + .srfm-form { + .srfm-payment-block { + // Top-level chooser wrapper — flex row of two cards. + .srfm-payment-type-chooser { + @include srfm-multi-choice-wrap-styles; + margin-bottom: 16px; + } + + // Each pill — same DOM shape as `.srfm-multi-choice-single`. + .srfm-payment-type-choice { + @include srfm-multi-choice-single-styles; + transition: 0.2s ease-out; + + input { + position: absolute; + opacity: 0; + + &:checked + .srfm-block-content-wrap { + box-shadow: none; + border-color: var( --srfm-color-input-border-hover ); + background: var( --srfm-color-input-selected ); + + .srfm-payment-icon { + opacity: 1; + width: var( --srfm-multi-choice-horizontal-svg-size ); + border-color: transparent; + + svg { + opacity: 1; + + path { + stroke: var( --srfm-color-scheme-primary ); + } + } + } + + .srfm-payment-icon-unchecked { + opacity: 0; + width: 0; + + svg { + opacity: 0; + } + } + } + + &:focus + .srfm-block-content-wrap { + box-shadow: 0px 0px 0px 3px var( --srfm-color-input-border-focus-glow ); + border-color: var( --srfm-color-input-border-hover ); + } + } + + .srfm-block-content-wrap { + @include srfm-multi-choice-block-content-wrap-styles(); + transition: 0.2s ease-out; + + &:hover { + border-color: var( --srfm-color-input-border-hover ); + background-color: var( --srfm-color-input-background-hover ); + } + + .srfm-icon-container { + display: flex; + + .srfm-payment-icon, + .srfm-payment-icon-unchecked { + @include srfm-multi-choice-icon-styles; + + svg { + transition: opacity 0.2s ease-out; + transform: translate3d( 0, 0, 0 ); + } + } + + .srfm-payment-icon { + opacity: 0; + width: 0; + + svg { + opacity: 0; + } + } + } + } + + @media ( max-width: 480px ) { + width: 100%; + } + } + } + } +} diff --git a/sass/blocks/default/frontend.scss b/sass/blocks/default/frontend.scss index ea001b2c7..b93e7ba7b 100644 --- a/sass/blocks/default/frontend.scss +++ b/sass/blocks/default/frontend.scss @@ -3,6 +3,7 @@ @import "./components/common"; @import "./components/dropdown"; @import "./components/multi-choice"; +@import "./components/payment-type-chooser"; @import "./components/number"; @import "./components/phone"; @import "./components/textarea"; diff --git a/sass/common.scss b/sass/common.scss index cbf92bc88..e153eef65 100644 --- a/sass/common.scss +++ b/sass/common.scss @@ -119,8 +119,31 @@ body.post-type-sureforms_form .is-root-container, } // Add top margin to confirm email field. - .srfm-email-confirm-block { - margin-top: var( --srfm-row-gap-between-blocks ); + // Selector is wrapped under `.srfm-block` (the email outer wrapper has it) + // so the show rule has specificity (0,5,0) — one class higher than the + // base `.srfm-form .srfm-block .srfm-error-message { display: none }` + // rule in `frontend/form.scss`. With identical (0,4,0) the hide rule + // would win on load order (common.css enqueues before frontend/form.css). + .srfm-block { + .srfm-email-confirm-block { + margin-top: var( --srfm-row-gap-between-blocks ); + + &.srfm-error { + .srfm-block-wrap { + .srfm-input-common { + border-color: var( --srfm-error-color-border ); + + &:focus { + box-shadow: 0px 0px 0px 3px var( --srfm-error-color-border-glow ); + } + } + } + + .srfm-error-message { + display: block; + } + } + } } .srfm-block { diff --git a/sass/editor-nudge.scss b/sass/editor-nudge.scss new file mode 100644 index 000000000..3bbf2549c --- /dev/null +++ b/sass/editor-nudge.scss @@ -0,0 +1,71 @@ +/** + * SureForms — Editor Nudge. + * + * Styles for the dismissible notice shown in the block editor when the + * post title hints at a form. Scoped to the `.srfm-editor-nudge` class + * so we never affect other Gutenberg notices. + */ + +$srfm-nudge-bg: #fff8f3; +$srfm-nudge-border: #f9d0b0; +$srfm-nudge-text: #1e1e1e; +$srfm-nudge-cta-bg: #e8580c; +$srfm-nudge-cta-bg-hover: #cf4a06; +$srfm-nudge-cta-color: #fff; + +.components-notice.srfm-editor-nudge { + background-color: $srfm-nudge-bg; + border-left: 4px solid $srfm-nudge-cta-bg; + box-shadow: 0 1px 2px rgba( 0, 0, 0, 0.04 ); + padding: 10px 14px; + + .srfm-editor-nudge__icon { + width: 22px; + height: 22px; + flex-shrink: 0; + border-radius: 4px; + margin-right: 10px; + align-self: center; + display: block; + } + + .components-notice__content { + color: $srfm-nudge-text; + font-size: 13px; + line-height: 1.5; + display: flex; + justify-content: space-between; + align-items: center; + margin: 0 25px 0 0; + } + + .components-notice__dismiss { + color: #757575; + + &:hover, + &:focus { + color: $srfm-nudge-text; + } + } + + .srfm-editor-nudge__cta { + background-color: $srfm-nudge-cta-bg; + border-color: $srfm-nudge-cta-bg; + color: $srfm-nudge-cta-color; + font-weight: 600; + display: inline-flex; + padding: 5px 14px; + border-radius: 4px; + text-decoration: none; + font-size: 12px; + line-height: 1; + margin: 0; + + &:hover, + &:focus { + background-color: $srfm-nudge-cta-bg-hover; + border-color: $srfm-nudge-cta-bg-hover; + color: $srfm-nudge-cta-color; + } + } +} diff --git a/src/admin/components/PageHeader.js b/src/admin/components/PageHeader.js index 3985a761d..39a6c2920 100644 --- a/src/admin/components/PageHeader.js +++ b/src/admin/components/PageHeader.js @@ -1,4 +1,4 @@ -import { render } from '@wordpress/element'; +import { createRoot } from '@wordpress/element'; import { cn } from '@Utils/Helpers'; import Header from './Header'; @@ -15,7 +15,8 @@ const FormPageHeader = ( { className } ) => { function renderApp() { if ( null !== app ) { - render( , app ); + const root = createRoot( app ); + root.render( ); } } diff --git a/src/admin/components/template-picker/TemplatePicker.js b/src/admin/components/template-picker/TemplatePicker.js index 70b705446..8b96738ac 100644 --- a/src/admin/components/template-picker/TemplatePicker.js +++ b/src/admin/components/template-picker/TemplatePicker.js @@ -1,4 +1,4 @@ -import { useEffect, render } from '@wordpress/element'; +import { useEffect, createRoot } from '@wordpress/element'; import { BrowserRouter as Router } from 'react-router-dom'; import AiFormBuilder from './components/AiFormBuilder.js'; @@ -28,7 +28,8 @@ export default TemplatePicker; function renderApp() { if ( null !== app ) { - render( , app ); + const root = createRoot( app ); + root.render( ); } } diff --git a/src/admin/components/template-picker/ai-form-builder-components/AiFormBuilderForm.js b/src/admin/components/template-picker/ai-form-builder-components/AiFormBuilderForm.js index 2de5beaa7..8fc7d700c 100644 --- a/src/admin/components/template-picker/ai-form-builder-components/AiFormBuilderForm.js +++ b/src/admin/components/template-picker/ai-form-builder-components/AiFormBuilderForm.js @@ -53,7 +53,6 @@ const VoiceToggleButton = memo( ( { isListening, toggleListening } ) => { export default ( props ) => { const { handleCreateAiForm, - setIsBuildingForm, formTypeObj, setFormTypeObj, setFormType, @@ -476,9 +475,6 @@ export default ( props ) => { [], true ); - setIsBuildingForm( - true - ); } } > { __( diff --git a/src/admin/components/template-picker/components/AiFormBuilder.js b/src/admin/components/template-picker/components/AiFormBuilder.js index 27354e392..943f53375 100644 --- a/src/admin/components/template-picker/components/AiFormBuilder.js +++ b/src/admin/components/template-picker/components/AiFormBuilder.js @@ -22,8 +22,22 @@ const AiFormBuilder = () => { ); const [ isBuildingForm, setIsBuildingForm ] = useState( false ); const [ percentBuild, setPercentBuild ] = useState( 0 ); - const [ showFormCreationErr, setShowFormCreationErr ] = useState( false ); + const [ formCreationErr, setFormCreationErr ] = useState( '' ); const [ showAuthErrorPopup, setShowAuthErrorPopup ] = useState( false ); + + const handleFormCreationError = ( errorMessage ) => { + setFormCreationErr( + errorMessage || + __( 'Something went wrong. Please try again.', 'sureforms' ) + ); + setIsBuildingForm( false ); + setPercentBuild( 0 ); + }; + + const resetFormCreationError = () => { + setFormCreationErr( '' ); + setPercentBuild( 0 ); + }; const [ formTypeObj, setFormTypeObj ] = useState( {} ); const [ formType, setFormType ] = useState( 'simple' ); @@ -42,10 +56,11 @@ const AiFormBuilder = () => { previousMessages, useSystemMessage ) => { - setPercentBuild( 0 ); // Check if the user has permission to create posts. if ( '1' !== srfm_admin.capability ) { - console.error( 'User does not have permission to create posts' ); + handleFormCreationError( + __( 'You do not have permission to create forms.', 'sureforms' ) + ); return; } @@ -63,80 +78,131 @@ const AiFormBuilder = () => { form_type: formType, }; - // add a pause of 2 seconds and set percentBuild to 25 without using setTimeout + setIsBuildingForm( true ); setPercentBuild( 50 ); setMessage( __( 'Generating fields', 'sureforms' ) ); + let response; try { - const response = await apiFetch( { + response = await apiFetch( { path: 'sureforms/v1/generate-form', method: 'POST', data: postData, } ); + } catch ( error ) { + console.error( 'Error generating AI form:', error ); + handleFormCreationError( + error?.message || + __( + 'Unable to reach the SureForms AI service. Please check your connection and try again.', + 'sureforms' + ) + ); + return; + } + + if ( ! response ) { + handleFormCreationError( + __( + 'The AI service did not return a response. Please try again.', + 'sureforms' + ) + ); + return; + } + + setMessage( __( 'Finalizing your form', 'sureforms' ) ); + setPercentBuild( 75 ); + + if ( response?.success === false ) { + handleFormCreationError( + response?.data?.message || + response?.message || + __( + 'Form generation failed. Please try again.', + 'sureforms' + ) + ); + return; + } + + const content = response?.data; + + if ( ! content ) { + handleFormCreationError( + __( + 'The AI response was empty. Please refine your prompt and try again.', + 'sureforms' + ) + ); + return; + } - if ( response ) { - /** - * If the response contains an error code, handle it. - * This is the most common error that can occur when the AI response is not in the expected format. - */ - if ( response?.code === 'invalid_json' ) { - setShowFormCreationErr( true ); - return; - } - setMessage( __( 'Finalizing your form', 'sureforms' ) ); - setPercentBuild( 75 ); - - if ( response?.success === false ) { - setShowFormCreationErr( true ); - return; - } - - const content = response?.data; - - if ( ! content ) { - setShowFormCreationErr( true ); - return; - } - - const postContent = await apiFetch( { - path: 'sureforms/v1/map-fields', - method: 'POST', - data: { - form_data: content, - is_conversional: formTypeObj?.isConversationalForm, - }, - } ); - - if ( postContent ) { - setMessage( __( 'Opening form editor', 'sureforms' ) ); - setPercentBuild( 100 ); - const formTitle = content?.form?.formTitle; - const metasToUpdate = applyFilters( - 'srfm.aiFormScreen.metasToUpdate', - {}, - formTypeObj, - content - ); - handleAddNewPost( - postContent, - formTitle, - metasToUpdate, - formTypeObj?.isConversationalForm, - formType - ); - } else { - setShowFormCreationErr( true ); - } - } else { - setShowFormCreationErr( true ); - console.error( - 'Error creating sureforms form using AI: ', - response.message - ); - } + let postContent; + try { + postContent = await apiFetch( { + path: 'sureforms/v1/map-fields', + method: 'POST', + data: { + form_data: content, + is_conversional: formTypeObj?.isConversationalForm, + }, + } ); } catch ( error ) { - console.log( error ); + console.error( 'Error mapping AI form fields:', error ); + handleFormCreationError( + error?.message || + __( + 'Unable to build form fields from the AI response.', + 'sureforms' + ) + ); + return; + } + + // field-mapping returns a WP_Error serialised as { code, message } on failure. + if ( + postContent && + typeof postContent === 'object' && + postContent.code + ) { + handleFormCreationError( + postContent.message || + __( + 'Unable to build form fields from the AI response.', + 'sureforms' + ) + ); + return; + } + + if ( ! postContent ) { + handleFormCreationError( + __( + 'Unable to build form fields from the AI response.', + 'sureforms' + ) + ); + return; } + + setMessage( __( 'Opening form editor', 'sureforms' ) ); + setPercentBuild( 100 ); + const formTitle = content?.form?.formTitle; + const metasToUpdate = applyFilters( + 'srfm.aiFormScreen.metasToUpdate', + {}, + formTypeObj, + content + ); + handleAddNewPost( + postContent, + formTitle, + metasToUpdate, + formTypeObj?.isConversationalForm, + formType, + handleFormCreationError + ); }; const handleAccessKey = async () => { @@ -310,18 +376,19 @@ const AiFormBuilder = () => { } }; - // shows while the form is being built + // shows while the form is being built. The error popup is intentionally + // rendered only at the bottom of the component (outer return) — when + // handleFormCreationError fires it sets isBuildingForm=false in the same + // batch as setFormCreationErr, so the early-return here never coincides + // with a non-empty formCreationErr; an inner ErrorPopup would be dead code. if ( isBuildingForm ) { return ( - <> - - - - { showFormCreationErr && } - + + + ); } @@ -348,7 +415,6 @@ const AiFormBuilder = () => {
{ srfm_admin?.srfm_ai_usage_details?.code ? getLimitReachedPopup() : null } + + { formCreationErr && ( + + ) }
); }; diff --git a/src/admin/components/template-picker/components/ErrorPopup.js b/src/admin/components/template-picker/components/ErrorPopup.js index c6ec5b603..225a19c51 100644 --- a/src/admin/components/template-picker/components/ErrorPopup.js +++ b/src/admin/components/template-picker/components/ErrorPopup.js @@ -1,52 +1,102 @@ import { __ } from '@wordpress/i18n'; +import { useEffect, useRef, useId } from '@wordpress/element'; import ICONS from './icons.js'; import { Button, Container, Label } from '@bsf/force-ui'; -const ErrorPopup = () => { +const ErrorPopup = ( { errorMessage = '', onRetry } ) => { + const dialogRef = useRef( null ); + const titleId = useId(); + const descId = useId(); + + const handleRetry = + typeof onRetry === 'function' + ? onRetry + : () => window.location.reload(); + + const bodyText = + errorMessage || + __( 'Something went wrong. Please try again.', 'sureforms' ); + + // Move focus into the dialog on mount so screen readers announce it and + // keyboard users can act on it without first tabbing through the page. + useEffect( () => { + const node = dialogRef.current; + if ( ! node ) { + return; + } + // Prefer focusing the primary action button if present; fall back to + // the dialog wrapper itself (it's tabIndex=-1 so it's focusable). + const primaryButton = node.querySelector( 'button' ); + if ( primaryButton ) { + primaryButton.focus(); + } else { + node.focus(); + } + }, [] ); + + // Escape closes the dialog by invoking the retry/close handler — there's + // only one action, so Esc and Try Again converge to the same behavior. + useEffect( () => { + const onKeyDown = ( event ) => { + if ( event.key === 'Escape' ) { + event.stopPropagation(); + handleRetry(); + } + }; + document.addEventListener( 'keydown', onKeyDown ); + return () => document.removeEventListener( 'keydown', onKeyDown ); + }, [ handleRetry ] ); + return ( - - - - - - - - - - + + + + + + + + + + + - +
); }; diff --git a/src/admin/editor-nudge/index.js b/src/admin/editor-nudge/index.js new file mode 100644 index 000000000..39ba7dc78 --- /dev/null +++ b/src/admin/editor-nudge/index.js @@ -0,0 +1,418 @@ +/** + * SureForms — Editor Nudge. + * + * Shows a dismissible notice in the block editor when the user is editing + * a post/page whose title hints at a form ("contact", "form", "forms") + * AND the post does not already contain a `srfm/form` block. + * + * Uses the native Gutenberg notice API (core/notices) so we do not have + * to touch the editor iframe DOM. Dismissal is persisted server-side via + * AJAX so the banner does not reappear across sessions. Inserting a + * `srfm/form` block auto-hides the notice without persisting dismissal. + */ + +import domReady from '@wordpress/dom-ready'; +import { dispatch, select, subscribe } from '@wordpress/data'; + +const NOTICE_ID = 'srfm-editor-nudge'; +const NOTICE_CLASS = 'srfm-editor-nudge'; +const CTA_CLASS = 'srfm-editor-nudge__cta'; +const ICON_CLASS = 'srfm-editor-nudge__icon'; +const TITLE_KEYWORDS = /\b(contact|forms?)\b/i; +const FORM_BLOCK_NAME = 'srfm/form'; +const SUREFORMS_CPT = 'sureforms_form'; +const DECORATE_INTERVAL_MS = 100; +const DECORATE_MAX_ATTEMPTS = 30; + +const CORE_EDITOR = 'core/editor'; +const CORE_EDIT_SITE = 'core/edit-site'; +const CORE_BLOCK_EDITOR = 'core/block-editor'; +const CORE_NOTICES = 'core/notices'; +const CORE = 'core'; + +let isNoticeVisible = false; +let hasDismissed = false; +let isProgrammaticRemoval = false; +let noticeWatcher = null; +let decorateInterval = null; + +/** + * Normalize a title value to a plain string. + * + * The REST entity record can expose `title` as `{ raw, rendered }` rather + * than a string in some Gutenberg/WP versions, which would otherwise slip + * past `isTitleMatch` silently. + * + * @param {*} value Raw title value pulled from a store. + * @return {string} Normalized title string. + */ +function normalizeTitle( value ) { + if ( typeof value === 'string' ) { + return value; + } + if ( value && typeof value === 'object' ) { + return value.raw ?? value.rendered ?? ''; + } + return ''; +} + +/** + * Read the post title from whichever editor store is active. + * + * @return {string} Current post title, empty string when unavailable. + */ +function getEditorTitle() { + if ( select( CORE_EDIT_SITE ) && typeof select( CORE_EDIT_SITE ).getPage === 'function' ) { + const context = select( CORE_EDIT_SITE ).getPage()?.context; + if ( context?.postType && context?.postId ) { + const record = select( CORE ).getEditedEntityRecord( + 'postType', + context.postType, + context.postId + ); + return normalizeTitle( record?.title ); + } + } + + return normalizeTitle( select( CORE_EDITOR )?.getEditedPostAttribute( 'title' ) ); +} + +/** + * Read the current post type — used to skip the SureForms form editor. + * + * @return {string} Current post type slug, empty string when unavailable. + */ +function getEditorPostType() { + if ( select( CORE_EDIT_SITE ) && typeof select( CORE_EDIT_SITE ).getPage === 'function' ) { + const context = select( CORE_EDIT_SITE ).getPage()?.context; + if ( context?.postType ) { + return context.postType; + } + } + + return select( CORE_EDITOR )?.getCurrentPostType() ?? ''; +} + +/** + * Read the current post ID — used to scope dismissal persistence per-post. + * + * @return {number} Current post ID, or 0 when unavailable. + */ +function getEditorPostId() { + if ( select( CORE_EDIT_SITE ) && typeof select( CORE_EDIT_SITE ).getPage === 'function' ) { + const context = select( CORE_EDIT_SITE ).getPage()?.context; + if ( context?.postId ) { + return Number( context.postId ) || 0; + } + } + + return Number( select( CORE_EDITOR )?.getCurrentPostId() ?? 0 ) || 0; +} + +/** + * Read the top-level block list from the block-editor store. Returns the + * memoized array reference so callers can reference-compare across ticks + * to skip a redundant tree walk when the list has not changed. + * + * @return {Array} Top-level blocks, empty array when the store is missing. + */ +function getEditorBlocks() { + return select( CORE_BLOCK_EDITOR )?.getBlocks() ?? []; +} + +/** + * Recursively check whether a `srfm/form` block is present anywhere in + * the given block list — including nested inside group/columns blocks. + * + * @param {Array} blocks Block list from `getBlocks()`. + * @return {boolean} True when a `srfm/form` block is found. + */ +function walkForSrfmFormBlock( blocks ) { + for ( const block of blocks ) { + if ( block?.name === FORM_BLOCK_NAME ) { + return true; + } + if ( block?.innerBlocks?.length && walkForSrfmFormBlock( block.innerBlocks ) ) { + return true; + } + } + return false; +} + +function isTitleMatch( title ) { + return typeof title === 'string' && TITLE_KEYWORDS.test( title ); +} + +/** + * Mark the nudge as dismissed in-memory and tear down the user-dismissal + * watcher in the same step. Centralizing both side effects makes it + * impossible for a future caller to set `hasDismissed = true` while + * leaving the watcher subscribed indefinitely. + */ +function markDismissed() { + hasDismissed = true; + if ( noticeWatcher ) { + noticeWatcher(); + noticeWatcher = null; + } +} + +/** + * Persist the dismissed state for the current post. + * + * Resolves to true only when the server confirmed the dismissal — on + * network failures, non-2xx responses, or `success: false` payloads we + * resolve to false so the caller can keep the in-memory flag clear and + * stay consistent with the server (the nudge will reappear on reload). + * + * Bails early when no post ID is in scope (e.g. before an auto-draft + * has materialized) — the caller leaves the in-memory flag clear so the + * nudge can re-evaluate once the post settles. + * + * @return {Promise} True when the dismissal was persisted. + */ +function persistDismissal() { + const settings = window.srfm_editor_nudge; + if ( ! settings?.ajax_url ) { + return Promise.resolve( false ); + } + + const postId = getEditorPostId(); + if ( postId <= 0 ) { + return Promise.resolve( false ); + } + + const body = new URLSearchParams(); + body.append( 'action', 'srfm_editor_nudge_dismiss' ); + body.append( 'nonce', settings.nonce ?? '' ); + body.append( 'post_id', String( postId ) ); + + return window + .fetch( settings.ajax_url, { + method: 'POST', + credentials: 'same-origin', + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + body: body.toString(), + } ) + .then( ( response ) => { + if ( ! response.ok ) { + return false; + } + return response.json().then( ( data ) => !! data?.success ); + } ) + .catch( () => false ); +} + +/** + * Show the notice and start watching specifically for the user clicking + * its dismiss button. The watcher unsubscribes itself once the notice + * is gone from the store. + */ +function showNotice() { + const settings = window.srfm_editor_nudge; + if ( ! settings?.message || isNoticeVisible ) { + return; + } + + dispatch( CORE_NOTICES ).createInfoNotice( settings.message, { + id: NOTICE_ID, + isDismissible: true, + actions: [ + { + label: settings.button_label, + url: settings.create_form_url, + variant: 'primary', + className: CTA_CLASS, + }, + ], + } ); + + isNoticeVisible = true; + decorateWrapper(); + + if ( noticeWatcher ) { + noticeWatcher(); + noticeWatcher = null; + } + + noticeWatcher = subscribe( () => { + const notices = select( CORE_NOTICES )?.getNotices() ?? []; + const stillVisible = notices.some( ( notice ) => notice.id === NOTICE_ID ); + + if ( stillVisible ) { + return; + } + + const wasProgrammatic = isProgrammaticRemoval; + isProgrammaticRemoval = false; + isNoticeVisible = false; + stopDecorating(); + + if ( noticeWatcher ) { + noticeWatcher(); + noticeWatcher = null; + } + + if ( ! wasProgrammatic ) { + persistDismissal().then( ( ok ) => { + if ( ok ) { + markDismissed(); + } + // On failure leave hasDismissed false: the server has + // not stored anything, so the next reload will surface + // the notice again — matching server state. + } ); + } + } ); +} + +/** + * Remove the notice programmatically — e.g. after the user inserted a + * `srfm/form` block. Flagged so the user-dismissal watcher does not + * treat this as a user dismissal. + */ +function hideNotice() { + if ( ! isNoticeVisible ) { + return; + } + isProgrammaticRemoval = true; + stopDecorating(); + dispatch( CORE_NOTICES ).removeNotice( NOTICE_ID ); +} + +/** + * The notices store silently drops a `className` option on the wrapper, + * so we add it ourselves after the notice renders. We locate the wrapper + * via the CTA button's class (which IS respected) and walk up the DOM. + */ +function decorateWrapper() { + stopDecorating(); + + const tryDecorate = () => { + const cta = document.querySelector( '.' + CTA_CLASS ); + const wrapper = cta?.closest( '.components-notice' ); + if ( ! wrapper ) { + return false; + } + wrapper.classList.add( NOTICE_CLASS ); + insertIcon( wrapper ); + return true; + }; + + if ( tryDecorate() ) { + return; + } + + let attempts = 0; + decorateInterval = window.setInterval( () => { + attempts += 1; + if ( tryDecorate() || attempts >= DECORATE_MAX_ATTEMPTS ) { + stopDecorating(); + } + }, DECORATE_INTERVAL_MS ); +} + +function stopDecorating() { + if ( decorateInterval ) { + window.clearInterval( decorateInterval ); + decorateInterval = null; + } +} + +/** + * Inject the SureForms logo as the first child of the notice wrapper so + * it renders to the left of the message text. Idempotent — only inserts + * once per wrapper. + * + * @param {HTMLElement} wrapper The .components-notice DOM node. + */ +function insertIcon( wrapper ) { + if ( wrapper.querySelector( '.' + ICON_CLASS ) ) { + return; + } + const logoUrl = window.srfm_editor_nudge?.logo_url; + if ( ! logoUrl ) { + return; + } + const content = wrapper.querySelector( '.components-notice__content' ); + if ( ! content ) { + return; + } + const img = document.createElement( 'img' ); + img.src = logoUrl; + img.alt = ''; + img.className = ICON_CLASS; + wrapper.insertBefore( img, content ); +} + +function evaluate( title, postType, hasForm ) { + if ( hasDismissed ) { + return; + } + + const shouldShow = + SUREFORMS_CPT !== postType && + isTitleMatch( title ) && + ! hasForm; + + if ( shouldShow ) { + showNotice(); + } else { + hideNotice(); + } +} + +/** + * Subscribe to editor state — re-evaluates whether the notice should + * appear whenever the title, post type, or block list changes. + * + * The `@wordpress/data` subscriber fires on every dispatch to any + * registered store (keypresses, sidebar toggles, undo pushes), so we + * fast-path on the block list reference: `getBlocks()` is memoized and + * returns the same array reference until the tree actually changes, + * letting us skip the recursive walk on the vast majority of ticks. + */ +function watchEditorState() { + let lastTitle = getEditorTitle(); + let lastPostType = getEditorPostType(); + let lastBlocks = getEditorBlocks(); + let lastHasForm = walkForSrfmFormBlock( lastBlocks ); + + evaluate( lastTitle, lastPostType, lastHasForm ); + + subscribe( () => { + if ( hasDismissed ) { + return; + } + + const title = getEditorTitle(); + const postType = getEditorPostType(); + const blocks = getEditorBlocks(); + + // Reference-equality fast path — only walk the tree when the + // block list reference has changed since the last evaluation. + let hasForm = lastHasForm; + if ( blocks !== lastBlocks ) { + hasForm = walkForSrfmFormBlock( blocks ); + } + + if ( + title === lastTitle && + postType === lastPostType && + hasForm === lastHasForm + ) { + return; + } + + lastTitle = title; + lastPostType = postType; + lastBlocks = blocks; + lastHasForm = hasForm; + + evaluate( title, postType, hasForm ); + } ); +} + +domReady( () => { + watchEditorState(); +} ); diff --git a/src/admin/payment/enhanced-options.js b/src/admin/payment/enhanced-options.js index b471823b1..f48b50b5d 100644 --- a/src/admin/payment/enhanced-options.js +++ b/src/admin/payment/enhanced-options.js @@ -109,6 +109,7 @@ export const EnhancedMultiChoiceOptions = ( defaultOption, args ) => {
editOption( value, i ) } /> @@ -156,6 +157,7 @@ export const EnhancedDropdownOptions = ( defaultOption, args ) => {
editOption( value, i ) } /> diff --git a/src/admin/settings/settings.js b/src/admin/settings/settings.js index d8f09114e..331ac0578 100644 --- a/src/admin/settings/settings.js +++ b/src/admin/settings/settings.js @@ -1,4 +1,4 @@ -import { render, useEffect, useState } from '@wordpress/element'; +import { createRoot, useEffect, useState } from '@wordpress/element'; import { BrowserRouter as Router, useLocation } from 'react-router-dom'; import FormPageHeader from '../components/PageHeader'; @@ -128,7 +128,8 @@ export default Settings; function renderApp() { if ( null !== app ) { - render( , app ); + const root = createRoot( app ); + root.render( ); } } diff --git a/src/admin/single-form-settings/Editor.js b/src/admin/single-form-settings/Editor.js index 1c843657b..c88249cd5 100644 --- a/src/admin/single-form-settings/Editor.js +++ b/src/admin/single-form-settings/Editor.js @@ -7,7 +7,7 @@ import { TextControl, } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; -import { useState, useEffect, render } from '@wordpress/element'; +import { useState, useEffect, createRoot } from '@wordpress/element'; import { useSelect, useDispatch } from '@wordpress/data'; import { @@ -286,7 +286,7 @@ const SureformsFormSpecificSettings = () => { const newDiv = document.createElement( 'div' ); newDiv.className = 'upgrade-pro-container'; targetElement.appendChild( newDiv ); - render( , newDiv ); + createRoot( newDiv ).render( ); } } }; @@ -629,6 +629,7 @@ const SureformsFormSpecificSettings = () => { >
diff --git a/src/admin/single-form-settings/components/SRFMEditorHeader.js b/src/admin/single-form-settings/components/SRFMEditorHeader.js index 6e0666cd5..2edbc7da0 100644 --- a/src/admin/single-form-settings/components/SRFMEditorHeader.js +++ b/src/admin/single-form-settings/components/SRFMEditorHeader.js @@ -26,6 +26,7 @@ const SRFMEditorHeader = () => { return ( { isEditable && ( { FormRestrictionContext ); + // Read compliance meta directly — it lives in a separate post-meta key + // (`_srfm_compliance`) outside FormRestrictionContext. When GDPR + Never + // Store are both on, `Form_Submit` returns before inserting an entry + // (inc/form-submit.php:538), so the entries-table-driven cap (and any + // recurring extension that hooks `srfm_form_restriction_entries_count`) + // has no row to count and silently does not enforce. + const isNeverStoreEntriesEnabled = useSelect( ( select ) => { + const meta = select( 'core/editor' ).getEditedPostAttribute( 'meta' ); + const compliance = Array.isArray( meta?._srfm_compliance ) + ? meta._srfm_compliance[ 0 ] + : null; + return !! ( compliance?.gdpr && compliance?.do_not_store_entries ); + }, [] ); + // Validate that start date/time is before end date/time const dateTimeValidationError = useMemo( () => { // Only validate if scheduling is enabled and both dates are set @@ -179,7 +194,23 @@ const FormRestriction = ( { setHasValidationErrors } ) => { { preserveMetaData?.status && ( <> -
+ { isNeverStoreEntriesEnabled && ( + + + + + + { __( + '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.', + 'sureforms' + ) } + + + ) } +
{ } } />
+ { /* + * Slot for extensions to render a control aligned + * to the right of the Maximum Entries input — used + * by SureForms Pro to expose a Total / Per Day / + * Per Week / Per Month / Per Year period selector. + * + * Filter contract: callbacks receive whatever the + * previous callback returned (initially `null`) + * and are expected to return a JSX node. To stay + * a good citizen alongside other extensions a + * callback should compose with the previous return + * rather than replacing it, e.g.: + * + * addFilter( + * 'srfm_form_restriction_max_entries_after', + * 'my-plugin/extra', + * ( prev ) => <>{ prev } + * ); + * + * Last-registered-callback-wins is acceptable when + * only one extension is active, which is the + * current single-vendor reality (SureForms Pro). + */ } + { applyFilters( + 'srfm_form_restriction_max_entries_after', + null + ) }
diff --git a/src/admin/single-form-settings/tabs/GeneralSettings.js b/src/admin/single-form-settings/tabs/GeneralSettings.js index a0edab24f..62b0ec89e 100644 --- a/src/admin/single-form-settings/tabs/GeneralSettings.js +++ b/src/admin/single-form-settings/tabs/GeneralSettings.js @@ -306,6 +306,7 @@ function GeneralSettings( props ) { ) } { id: 'input-pattern', component: ( @@ -25,6 +26,7 @@ export default function CustomInspectorControls( { @@ -34,6 +36,7 @@ export default function CustomInspectorControls( { @@ -43,6 +46,7 @@ export default function CustomInspectorControls( { diff --git a/src/blocks/payment-history/edit.js b/src/blocks/payment-history/edit.js index 36208fd54..a21067e4f 100644 --- a/src/blocks/payment-history/edit.js +++ b/src/blocks/payment-history/edit.js @@ -23,6 +23,7 @@ export default function Edit( { attributes, setAttributes } ) { initialOpen={ true } > diff --git a/src/blocks/payment/components/billing-cycles-control.js b/src/blocks/payment/components/billing-cycles-control.js index 50080f8d4..14acc974b 100644 --- a/src/blocks/payment/components/billing-cycles-control.js +++ b/src/blocks/payment/components/billing-cycles-control.js @@ -45,14 +45,23 @@ const BillingCyclesControl = ( { subscriptionPlan, setAttributes } ) => { } ); }; - const isCustomIfBlank = '' === subscriptionPlan?.billingCycles; + // BILLING_CYCLES_NUMERIC_STRING: start + // Normalize billingCycles to a number when it's either a number or a numeric string (e.g. "6"). + const rawBillingCycles = subscriptionPlan?.billingCycles; + const isNumericValue = + typeof rawBillingCycles === 'number' || + ( typeof rawBillingCycles === 'string' && + rawBillingCycles.trim() !== '' && + ! isNaN( Number( rawBillingCycles ) ) ); + const numericBillingCycles = isNumericValue ? Number( rawBillingCycles ) : null; + // BILLING_CYCLES_NUMERIC_STRING: end + + const isCustomIfBlank = '' === rawBillingCycles; const cycleIsNotThree = - typeof subscriptionPlan?.billingCycles === 'number' && - subscriptionPlan?.billingCycles !== 3; + isNumericValue && numericBillingCycles !== 3; const isCustom = isCustomIfBlank || cycleIsNotThree; const showInput = - [ 2, 3, 4, 5 ].includes( Number( subscriptionPlan?.billingCycles ) ) || - isCustom; + [ 2, 3, 4, 5 ].includes( numericBillingCycles ) || isCustom; const defaultOptions = [ { @@ -84,6 +93,7 @@ const BillingCyclesControl = ( { subscriptionPlan, setAttributes } ) => { return ( <> { return nameFieldExists || emailFieldExists; }; - // Check payment type (subscription or one-time) + // Check payment type (subscription, one-time, or both) const paymentType = attributes.paymentType || 'one-time'; const isSubscription = paymentType === 'subscription'; + // BOTH MODE: detect "both" mode + const isBoth = paymentType === 'both'; // Check amount type const amountType = attributes.amountType || 'fixed'; @@ -91,20 +93,57 @@ export const PaymentComponent = ( props ) => { const customerEmail = attributes.customerEmailField || ''; const variableAmountField = attributes.variableAmountField || ''; - // Name field validation: required only for subscriptions + // Name field validation: required for subscriptions AND "both" mode + // BOTH MODE: require name field because user may choose subscription const missingNameField = - isSubscription && + ( isSubscription || isBoth ) && ( ! customerName || ! verifyFieldIsValid( customerName ) ); // Email field validation: required for all payment types const missingEmailField = ! customerEmail || ! verifyFieldIsValid( customerEmail ); - // Variable amount field validation: required when amount type is variable - const missingVariableAmountField = - isVariableAmount && - ( ! variableAmountField || - ! verifyFieldIsValid( variableAmountField, 'variableAmount' ) ); + // Variable amount field validation + let missingVariableAmountField = false; + // BOTH MODE: validate one-time AND subscription variable amount fields independently + if ( isBoth ) { + const oneTimeAmountType = + attributes.oneTimeAmountType || 'fixed'; + if ( oneTimeAmountType === 'variable' ) { + const oneTimeField = + attributes.oneTimeVariableAmountField || ''; + if ( + ! oneTimeField || + ! verifyFieldIsValid( oneTimeField, 'variableAmount' ) + ) { + missingVariableAmountField = true; + } + } + const subscriptionAmountType = + attributes.subscriptionAmountType || 'fixed'; + if ( subscriptionAmountType === 'variable' ) { + const subscriptionField = + attributes.subscriptionVariableAmountField || ''; + if ( + ! subscriptionField || + ! verifyFieldIsValid( + subscriptionField, + 'variableAmount' + ) + ) { + missingVariableAmountField = true; + } + } + } else { + // Existing single-type logic + missingVariableAmountField = + isVariableAmount && + ( ! variableAmountField || + ! verifyFieldIsValid( + variableAmountField, + 'variableAmount' + ) ); + } const hasCustomerFieldsError = missingNameField || missingEmailField || missingVariableAmountField; @@ -130,7 +169,8 @@ export const PaymentComponent = ( props ) => { if ( missingFields.length > 0 ) { const fieldsList = missingFields.join( ' and ' ); - if ( isSubscription && missingFields.length > 1 ) { + // BOTH MODE: treat "both" like "subscription" for plural error message + if ( ( isSubscription || isBoth ) && missingFields.length > 1 ) { errorMessage = sprintf( /* translators: %1$s: a comma-separated list of missing field names */ __( diff --git a/src/blocks/payment/edit.js b/src/blocks/payment/edit.js index eccb6ddf9..4352a2383 100644 --- a/src/blocks/payment/edit.js +++ b/src/blocks/payment/edit.js @@ -22,6 +22,7 @@ import { attributeOptionsWithFilter, afterAttributePanelBody } from '@Components import Separator from '@Components/separator'; import MultiButtonsControl from '@Components/multi-buttons-control'; import BillingCyclesControl from './components/billing-cycles-control.js'; +// BOTH MODE: "both" mode reuses the same single-select controls as subscription mode. const Edit = ( props ) => { const { clientId, attributes, setAttributes, isSelected } = props; @@ -40,6 +41,19 @@ const Edit = ( props ) => { customerEmailField, variableAmountField, paymentDescription, + // BOTH MODE: start — new attributes for "both" payment type + oneTimeLabel, + subscriptionLabel, + defaultPaymentChoice, + oneTimeAmountType, + oneTimeFixedAmount, + oneTimeMinimumAmount, + oneTimeVariableAmountField, + subscriptionAmountType, + subscriptionFixedAmount, + subscriptionMinimumAmount, + subscriptionVariableAmountField, + // BOTH MODE: end } = attributes; const currentFormId = useGetCurrentFormId( clientId ); const [ availableFormFields, setAvailableFormFields ] = useState( { @@ -114,6 +128,12 @@ const Edit = ( props ) => { label: `${ label } (multi-choice)`, type: 'multi-choice', } ); + } else if ( blockName === 'srfm/hidden' ) { + variableAmountFields.push( { + slug, + label: `${ label } (hidden)`, + type: 'hidden', + } ); } } } ); @@ -129,18 +149,22 @@ const Edit = ( props ) => { } }; - // Update available fields when form changes + // Update available fields when the form context or selection changes. + // Depending on currentFormId ensures the field list refreshes when the + // editor switches between forms; the previous length-guard workaround + // hid a stale-closure bug because the effect didn't react to formId changes. useEffect( () => { - if ( isSelected || ! availableFormFields?.emailsFields?.length ) { - const { emailsFields, nameFields, variableAmountFields } = - extractFormFields(); - setAvailableFormFields( { - emailsFields, - nameFields, - variableAmountFields, - } ); - } - }, [ isSelected ] ); + const { emailsFields, nameFields, variableAmountFields } = + extractFormFields(); + setAvailableFormFields( { + emailsFields, + nameFields, + variableAmountFields, + } ); + // extractFormFields is declared inline and closes over the latest + // getBlocks/currentFormId — safe to omit from deps. + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [ isSelected, currentFormId ] ); useEffect( () => { if ( formId !== currentFormId ) { @@ -212,6 +236,12 @@ const Edit = ( props ) => { value: 'subscription', label: __( 'Subscription', 'sureforms' ), }, + // BOTH MODE: start — new "Both" option + { + value: 'both', + label: __( 'Both', 'sureforms' ), + }, + // BOTH MODE: end ] } showIcons={ false } /> @@ -227,7 +257,7 @@ const Edit = ( props ) => { 'Subscription Plan Name', 'sureforms' ) } - value={ subscriptionPlan?.name } + value={ subscriptionPlan?.name || '' } data={ { value: subscriptionPlan?.name || @@ -250,6 +280,7 @@ const Edit = ( props ) => { id: 'subscription-interval', component: ( { }, ] : [] ), - { - id: 'separator', - component: , - }, - { - id: 'amount-type', - component: ( - - ), - }, - ...( amountType === 'fixed' + // BOTH MODE: start — entire settings block for "both" payment type + ...( paymentType === 'both' ? [ { - id: 'fixed-amount', + id: 'both-one-time-label', component: ( - setAttributes( { - fixedAmount: parseFloat( value ) || 0, - } ) + setAttributes( { oneTimeLabel: value } ) } help={ __( - 'Set the exact amount you want to charge. Users won’t be able to change it', + 'Label shown to users for the one-time payment option.', 'sureforms' ) } /> ), }, - ] - : [] ), - ...( amountType === 'variable' - ? [ { - id: 'variable-amount-field', + id: 'both-subscription-label', component: ( - + setAttributes( { subscriptionLabel: value } ) + } + help={ __( + 'Label shown to users for the subscription option.', 'sureforms' ) } - value={ variableAmountField || '' } + /> + ), + }, + { + id: 'both-default-choice', + component: ( + ( { - label: field.label, - value: field.slug, - } ) ), ] } - onChange={ ( value ) => { - setAttributes( { - variableAmountField: value, - } ); + showIcons={ false } + help={ __( + 'Which option is pre-selected when the form loads.', + 'sureforms' + ) } + /> + ), + }, + { + id: 'both-separator-one-time', + component: , + }, + { + id: 'both-one-time-amount-type', + component: ( + + ), + }, + ...( oneTimeAmountType === 'fixed' + ? [ + { + id: 'both-one-time-fixed-amount', + component: ( + + setAttributes( { + oneTimeFixedAmount: + parseFloat( value ) || 0, + } ) + } + help={ __( + 'Amount charged for a one-time payment.', + 'sureforms' + ) } + /> + ), + }, + ] + : [] ), + ...( oneTimeAmountType === 'variable' + ? [ + { + id: 'both-one-time-variable-field', + component: ( + ( { + label: field.label, + value: field.slug, + } ) ), + ] } + onChange={ ( value ) => { + setAttributes( { + oneTimeVariableAmountField: value, + } ); + } } + help={ __( + 'Pick a form field whose value determines the one-time payment amount.', + 'sureforms' + ) } + /> + ), + }, + { + id: 'both-one-time-minimum-amount', + component: ( + + setAttributes( { + oneTimeMinimumAmount: + parseFloat( value ) || 0, + } ) + } + help={ __( + 'Minimum amount users can enter for one-time payment (0 for no minimum).', + 'sureforms' + ) } + /> + ), + }, + ] + : [] ), + { + id: 'both-separator-subscription', + component: , + }, + { + id: 'both-subscription-amount-type', + component: ( + ), }, + ...( subscriptionAmountType === 'fixed' + ? [ + { + id: 'both-subscription-fixed-amount', + component: ( + + setAttributes( { + subscriptionFixedAmount: + parseFloat( value ) || 0, + } ) + } + help={ __( + 'Recurring amount charged per billing interval.', + 'sureforms' + ) } + /> + ), + }, + ] + : [] ), + ...( subscriptionAmountType === 'variable' + ? [ + { + id: 'both-subscription-variable-field', + component: ( + ( { + label: field.label, + value: field.slug, + } ) ), + ] } + onChange={ ( value ) => { + setAttributes( { + subscriptionVariableAmountField: + value, + } ); + } } + help={ __( + 'Pick a form field whose value determines the subscription amount.', + 'sureforms' + ) } + /> + ), + }, + { + id: 'both-subscription-minimum-amount', + component: ( + + setAttributes( { + subscriptionMinimumAmount: + parseFloat( value ) || 0, + } ) + } + help={ __( + 'Minimum amount users can enter for subscription (0 for no minimum).', + 'sureforms' + ) } + /> + ), + }, + ] + : [] ), { - id: 'minimum-amount', + id: 'both-separator-plan', + component: , + }, + { + id: 'both-subscription-plan-name', component: ( + onChange={ ( value ) => { setAttributes( { - minimumAmount: parseFloat( value ) || 0, - } ) - } + subscriptionPlan: { + ...( subscriptionPlan || {} ), + name: value, + }, + } ); + } } + allowReset={ false } + /> + ), + }, + { + id: 'both-subscription-interval', + component: ( + // BOTH MODE: single-select, same as subscription mode. + { + setAttributes( { + subscriptionPlan: { + ...( subscriptionPlan || {} ), + interval: value, + }, + } ); + } } + /> + ), + }, + { + id: 'both-billing-cycles', + component: ( + // BOTH MODE: single-select, same as subscription mode. + + ), + }, + ] + : [] ), + // BOTH MODE: end + // BOTH MODE: shared amount section hidden when paymentType === 'both' + ...( paymentType !== 'both' + ? [ + { + id: 'separator', + component: , + }, + { + id: 'amount-type', + component: ( + ), }, + ...( amountType === 'fixed' + ? [ + { + id: 'fixed-amount', + component: ( + + setAttributes( { + fixedAmount: parseFloat( value ) || 0, + } ) + } + help={ __( + 'Set the exact amount you want to charge. Users won’t be able to change it', + 'sureforms' + ) } + /> + ), + }, + ] + : [] ), + ...( amountType === 'variable' + ? [ + { + id: 'variable-amount-field', + component: ( + ( { + label: field.label, + value: field.slug, + } ) ), + ] } + onChange={ ( value ) => { + setAttributes( { + variableAmountField: value, + } ); + } } + help={ __( + 'Pick a field from your form like a number, dropdown, multichoice, or hidden whose value should decide the payment amount.', + 'sureforms' + ) } + /> + ), + }, + { + id: 'minimum-amount', + component: ( + + setAttributes( { + minimumAmount: parseFloat( value ) || 0, + } ) + } + help={ __( + 'Set the minimum amount users can enter (0 for no minimum)', + 'sureforms' + ) } + /> + ), + }, + ] + : [] ), ] : [] ), + // BOTH MODE: end of shared amount guard { id: 'separator-2', component: , @@ -427,8 +873,11 @@ const Edit = ( props ) => { id: 'customer-name-field', component: ( { setAttributes( { customerNameField: value } ); } } help={ - paymentType === 'subscription' + // BOTH MODE: treat "both" like "subscription" for help text + paymentType === 'subscription' || + paymentType === 'both' ? __( 'Select the input field that contains the customer name (Required for subscriptions)', 'sureforms' @@ -472,6 +923,7 @@ const Edit = ( props ) => { id: 'customer-email-field', component: ( { { showTitle && ( { @@ -369,6 +370,7 @@ export default ( { attributes, setAttributes, clientId } ) => { ) } { label, placeholder, required, + minLength, maxLength, defaultValue, rows, @@ -75,6 +76,7 @@ export const TextareaComponent = ( { attributes, blockID, setAttributes } ) => { value={ defaultValue } rows={ rows } cols={ cols } + data-minlength={ minLength || undefined } maxLength={ maxLength } className={ `srfm-input-common srfm-input-${ slug }` } > diff --git a/src/blocks/textarea/edit.js b/src/blocks/textarea/edit.js index 188d98a43..1c69e221d 100644 --- a/src/blocks/textarea/edit.js +++ b/src/blocks/textarea/edit.js @@ -27,6 +27,7 @@ const Edit = ( props ) => { const { help, required, + minLength, maxLength, block_id, defaultValue, @@ -171,6 +172,32 @@ const Edit = ( props ) => { id: 'max-length', component: ! isRichText && ( <> + { + setAttributes( { + minLength: Number( value ), + } ); + } } + min={ 0 } + showControlHeader={ false } + help={ + Number( minLength ) > 0 && + Number( maxLength ) > 0 && + Number( minLength ) > Number( maxLength ) + ? __( + 'Minimum characters cannot exceed Maximum characters.', + 'sureforms' + ) + : false + } + /> { <>
{
@@ -344,6 +346,7 @@ const Background = ( props ) => {
@@ -382,6 +385,7 @@ const Background = ( props ) => {
diff --git a/src/components/conditional-logic/index.js b/src/components/conditional-logic/index.js index d40954bbf..ea9779157 100644 --- a/src/components/conditional-logic/index.js +++ b/src/components/conditional-logic/index.js @@ -43,6 +43,7 @@ const ConditionalLogicPreview = () => { />
{
@@ -251,6 +252,7 @@ const Background = ( props ) => {
@@ -309,6 +311,7 @@ const Background = ( props ) => {
@@ -348,6 +351,7 @@ const Background = ( props ) => {
@@ -579,6 +583,7 @@ const Background = ( props ) => {
@@ -601,6 +606,7 @@ const Background = ( props ) => {
@@ -639,6 +645,7 @@ const Background = ( props ) => {
diff --git a/src/components/misc/ComponentKeyValueUI.js b/src/components/misc/ComponentKeyValueUI.js index 9764d910e..028b7eac8 100644 --- a/src/components/misc/ComponentKeyValueUI.js +++ b/src/components/misc/ComponentKeyValueUI.js @@ -84,6 +84,7 @@ const ComponentKeyValueUI = ( { >
{ { ! isEnableDynamicContent() && ( <> { const presetDropdown = ( {
{ /> { withInputField && isNumberControlSupported && ( { const output = {}; output.Desktop = ( setAttributes( { [ data.desktop.label ]: value } ) @@ -53,6 +54,7 @@ const ResponsiveSelectControl = ( props ) => { ); output.Tablet = ( setAttributes( { [ data.tablet.label ]: value } ) @@ -62,6 +64,7 @@ const ResponsiveSelectControl = ( props ) => { ); output.Mobile = ( setAttributes( { [ data.mobile.label ]: value } ) diff --git a/src/components/select-control/index.js b/src/components/select-control/index.js index 9acfe0e61..9f5402937 100644 --- a/src/components/select-control/index.js +++ b/src/components/select-control/index.js @@ -93,6 +93,7 @@ export default function SRFMSelectControl( { { controlBeforeDomElement } { children ? ( @@ -106,6 +107,7 @@ export default function SRFMSelectControl( { ) : ( diff --git a/src/components/text-control/index.js b/src/components/text-control/index.js index 50c08f28f..4dde907a9 100644 --- a/src/components/text-control/index.js +++ b/src/components/text-control/index.js @@ -153,6 +153,7 @@ const SRFMTextControl = ( props ) => { <> { props?.variant !== 'textarea' && ( { + const reportError = ( message ) => { + if ( typeof onError === 'function' ) { + onError( message ); + } + }; + if ( '1' !== srfm_admin.capability ) { - console.error( 'User does not have permission to create posts' ); + const message = __( + 'You do not have permission to create forms.', + 'sureforms' + ); + console.error( message ); + reportError( message ); return; } @@ -90,7 +102,7 @@ export const handleAddNewPost = async ( }, } ); - if ( response.id ) { + if ( response?.id ) { const postId = response.id; // Store the post ID so the Learn section Lesson 2 can open this form directly. @@ -101,11 +113,23 @@ export const handleAddNewPost = async ( // Redirect to the newly created post window.location.href = `${ srfm_admin.site_url }/wp-admin/post.php?post=${ postId }&action=edit`; - } else { - console.error( 'Error creating sureforms_form:', response.message ); + return; } + + const message = + response?.message || + __( 'The form could not be saved. Please try again.', 'sureforms' ); + console.error( 'Error creating sureforms_form:', message ); + reportError( message ); } catch ( error ) { - console.log( error ); + console.error( 'Error creating sureforms_form:', error ); + reportError( + error?.message || + __( + 'The form could not be saved. Please try again.', + 'sureforms' + ) + ); } }; @@ -669,7 +693,9 @@ const generateSlug = ( label, existingSlugs, blockName = '' ) => { // cleanForSlug() preserves them but PHP sanitize_title() will percent-encode them, // causing slug mismatch. Fall back to block name for a stable ASCII slug. if ( /[^\x00-\x7F]/.test( baseSlug ) ) { - baseSlug = blockName ? cleanForSlug( blockName.replace( /^srfm\//, '' ) ) : ''; + baseSlug = blockName + ? cleanForSlug( blockName.replace( /^srfm\//, '' ) ) + : ''; } let slug = baseSlug; @@ -716,7 +742,10 @@ export const prepareBlockSlugs = ( updateBlockAttributes, srfmBlocks ) => { if ( slug && ! isAutoAndChanged ) { existingSlugs.add( slug ); } - if ( Array.isArray( block.innerBlocks ) && block.innerBlocks.length > 0 ) { + if ( + Array.isArray( block.innerBlocks ) && + block.innerBlocks.length > 0 + ) { seedExisting( block.innerBlocks ); } } diff --git a/sureforms.php b/sureforms.php index 6681276cc..5fd4f2caa 100644 --- a/sureforms.php +++ b/sureforms.php @@ -7,7 +7,7 @@ * Requires PHP: 7.4 * Author: SureForms * Author URI: https://sureforms.com/ - * Version: 2.8.1 + * Version: 2.8.2 * License: GPLv2 or later * Text Domain: sureforms * @@ -25,7 +25,7 @@ define( 'SRFM_BASENAME', plugin_basename( SRFM_FILE ) ); define( 'SRFM_DIR', plugin_dir_path( SRFM_FILE ) ); define( 'SRFM_URL', plugins_url( '/', SRFM_FILE ) ); -define( 'SRFM_VER', '2.8.1' ); +define( 'SRFM_VER', '2.8.2' ); define( 'SRFM_SLUG', 'srfm' ); // ------ ADDITIONAL CONSTANTS ------- // define( 'SRFM_FORMS_POST_TYPE', 'sureforms_form' ); @@ -35,7 +35,7 @@ define( 'SRFM_AI_MIDDLEWARE', 'https://credits.startertemplates.com/sureforms/' ); define( 'SRFM_MIDDLEWARE_BASE_URL', 'https://api.sureforms.com/' ); define( 'SRFM_BILLING_PORTAL', 'https://billing.sureforms.com/' ); -define( 'SRFM_PRO_RECOMMENDED_VER', '2.8.2' ); +define( 'SRFM_PRO_RECOMMENDED_VER', '2.8.3' ); define( 'SRFM_SURETRIGGERS_INTEGRATION_BASE_URL', 'https://app.ottokit.com/' ); diff --git a/tests/unit/inc/admin/test-editor-nudge.php b/tests/unit/inc/admin/test-editor-nudge.php new file mode 100644 index 000000000..8e5018456 --- /dev/null +++ b/tests/unit/inc/admin/test-editor-nudge.php @@ -0,0 +1,592 @@ +nudge = Editor_Nudge::get_instance(); + $this->admin_id = self::factory()->user->create( [ 'role' => 'administrator' ] ); + $this->subscriber_id = self::factory()->user->create( [ 'role' => 'subscriber' ] ); + $this->post_id = self::factory()->post->create( [ 'post_type' => 'page', 'post_title' => 'Contact Us' ] ); + $this->other_post_id = self::factory()->post->create( [ 'post_type' => 'page', 'post_title' => 'About' ] ); + } + + protected function tearDown(): void { + wp_set_current_user( 0 ); + delete_post_meta( $this->post_id, Editor_Nudge::DISMISS_META_KEY ); + delete_post_meta( $this->other_post_id, Editor_Nudge::DISMISS_META_KEY ); + wp_delete_post( $this->post_id, true ); + wp_delete_post( $this->other_post_id, true ); + wp_delete_user( $this->admin_id ); + wp_delete_user( $this->subscriber_id ); + unset( $_POST['nonce'], $_POST['post_id'] ); + $GLOBALS['post'] = null; + $GLOBALS['current_screen'] = null; + parent::tearDown(); + } + + /** + * Configure a block-editor screen for the given post type so allow_load() + * can pass the screen + post-type checks under PHPUnit. + * + * @param string $post_type Post type slug, e.g. 'page' or SRFM_FORMS_POST_TYPE. + */ + protected function force_block_editor_screen( $post_type ) { + $screen = \WP_Screen::get( $post_type ); + $screen->id = $post_type; + $screen->post_type = $post_type; + $screen->is_block_editor( true ); + set_current_screen( $screen ); + } + + /** + * Bind the global $post to a given post so allow_load()'s + * get_current_post_id() resolves to that post. + * + * @param int $post_id Post ID to bind. + */ + protected function set_current_post( $post_id ) { + $GLOBALS['post'] = get_post( $post_id ); + } + + // --------------------------------------------------------------- + // get_current_post_id() + // --------------------------------------------------------------- + + /** + * Invoke the protected `get_current_post_id` helper via reflection so + * the coverage tool registers a direct test for it. Covers three + * branches: no `$post` global, non-WP_Post `$post`, and a valid + * `WP_Post` instance. + */ + public function test_get_current_post_id() { + $method = new \ReflectionMethod( Editor_Nudge::class, 'get_current_post_id' ); + $method->setAccessible( true ); + + // No $post global → 0. + $GLOBALS['post'] = null; + $this->assertSame( + 0, + $method->invoke( $this->nudge ), + 'get_current_post_id() must return 0 when no $post global is set.' + ); + + // Non-WP_Post value (e.g. left-over array) → 0. + $GLOBALS['post'] = [ 'ID' => $this->post_id ]; + $this->assertSame( + 0, + $method->invoke( $this->nudge ), + 'get_current_post_id() must return 0 when $post is not a WP_Post.' + ); + + // Valid WP_Post → the post ID. + $GLOBALS['post'] = get_post( $this->post_id ); + $this->assertSame( + (int) $this->post_id, + $method->invoke( $this->nudge ), + 'get_current_post_id() must return the post ID when $post is a valid WP_Post.' + ); + } + + // --------------------------------------------------------------- + // allow_load() + // --------------------------------------------------------------- + + /** + * Non-admin context should always bail out early. + */ + public function test_allow_load_returns_false_outside_admin() { + wp_set_current_user( $this->admin_id ); + + // PHPUnit runs without is_admin() true by default. + $this->assertFalse( $this->nudge->allow_load() ); + } + + /** + * Users without the required capability should not see the nudge. + */ + public function test_allow_load_returns_false_for_user_without_capability() { + wp_set_current_user( $this->subscriber_id ); + $this->assertFalse( $this->nudge->allow_load() ); + } + + /** + * A post with an active dismissal meta should suppress the nudge. + */ + public function test_allow_load_returns_false_when_post_already_dismissed() { + wp_set_current_user( $this->admin_id ); + + if ( ! defined( 'WP_ADMIN' ) ) { + define( 'WP_ADMIN', true ); + } + + $this->force_block_editor_screen( 'page' ); + $this->set_current_post( $this->post_id ); + update_post_meta( $this->post_id, Editor_Nudge::DISMISS_META_KEY, time() ); + + $this->assertFalse( + $this->nudge->allow_load(), + 'allow_load() must return false when the current post has a fresh dismissal recorded.' + ); + } + + /** + * After the user dismisses the nudge on Post A, navigating to Post B + * (which has no dismissal of its own) must still show the nudge — + * dismissal is scoped to the post, not the user. + */ + public function test_allow_load_isolated_per_post() { + wp_set_current_user( $this->admin_id ); + + if ( ! defined( 'WP_ADMIN' ) ) { + define( 'WP_ADMIN', true ); + } + + $this->force_block_editor_screen( 'page' ); + + // Dismiss on Post A. + update_post_meta( $this->post_id, Editor_Nudge::DISMISS_META_KEY, time() ); + + // Editing Post B — no dismissal — must still allow the nudge. + $this->set_current_post( $this->other_post_id ); + + $this->assertTrue( + $this->nudge->allow_load(), + 'A dismissal on one post must not silence the nudge on a different post.' + ); + } + + /** + * A dismissal older than the expiry window should no longer suppress + * the nudge — guards against the "permanent dismissal with no recovery" + * footgun. Asserts both the helper and allow_load() to lock the + * rollover behavior end-to-end. + */ + public function test_allow_load_treats_expired_dismissal_as_inactive() { + wp_set_current_user( $this->admin_id ); + + if ( ! defined( 'WP_ADMIN' ) ) { + define( 'WP_ADMIN', true ); + } + + $this->force_block_editor_screen( 'page' ); + $this->set_current_post( $this->post_id ); + + $expired_at = time() - Editor_Nudge::DISMISS_EXPIRY_SECONDS - DAY_IN_SECONDS; + update_post_meta( $this->post_id, Editor_Nudge::DISMISS_META_KEY, $expired_at ); + + $this->assertFalse( + $this->nudge->is_dismissal_active( $this->post_id ), + 'Expired dismissal timestamp must not count as active.' + ); + + $this->assertTrue( + $this->nudge->allow_load(), + 'allow_load() must surface the nudge again once the dismissal expires.' + ); + } + + /** + * Sanity check that a fresh dismissal is treated as active for the post. + */ + public function test_is_dismissal_active_returns_true_for_recent_timestamp() { + update_post_meta( $this->post_id, Editor_Nudge::DISMISS_META_KEY, time() ); + + $this->assertTrue( $this->nudge->is_dismissal_active( $this->post_id ) ); + } + + /** + * Positive-path coverage: when capability + block-editor screen + + * non-SureForms post type + no active dismissal all align, + * allow_load() must return true. + */ + public function test_allow_load_returns_true_when_all_conditions_met() { + wp_set_current_user( $this->admin_id ); + + if ( ! defined( 'WP_ADMIN' ) ) { + define( 'WP_ADMIN', true ); + } + + $this->force_block_editor_screen( 'page' ); + $this->set_current_post( $this->post_id ); + + $this->assertTrue( + $this->nudge->allow_load(), + 'allow_load() must return true on a block-editor screen for a capable user with no active dismissal.' + ); + } + + /** + * The SureForms form CPT editor must never show the nudge — even when + * every other condition is satisfied. + */ + public function test_allow_load_returns_false_on_sureforms_form_screen() { + wp_set_current_user( $this->admin_id ); + + if ( ! defined( 'WP_ADMIN' ) ) { + define( 'WP_ADMIN', true ); + } + + $this->force_block_editor_screen( SRFM_FORMS_POST_TYPE ); + + $this->assertFalse( + $this->nudge->allow_load(), + 'allow_load() must return false on the SureForms form CPT screen.' + ); + } + + /** + * Logged-out visitor should never load the nudge script. + */ + public function test_allow_load_returns_false_for_logged_out_user() { + wp_set_current_user( 0 ); + $this->assertFalse( $this->nudge->allow_load() ); + } + + // --------------------------------------------------------------- + // End-to-end "once dismissed, won't show again on this post" + // --------------------------------------------------------------- + + /** + * Dismissing the nudge via the AJAX handler must immediately mark + * subsequent allow_load() calls for the same post as false — the user + * dismisses, reloads, and the nudge does not return. + */ + public function test_nudge_does_not_show_after_successful_dismissal() { + wp_set_current_user( $this->admin_id ); + + if ( ! defined( 'WP_ADMIN' ) ) { + define( 'WP_ADMIN', true ); + } + + $this->force_block_editor_screen( 'page' ); + $this->set_current_post( $this->post_id ); + + // Pre-condition: with no dismissal recorded, the nudge is allowed. + $this->assertTrue( + $this->nudge->allow_load(), + 'Pre-condition failed — nudge should be allowed before dismissal.' + ); + + // Simulate the dismissal AJAX flow. + $_POST['nonce'] = wp_create_nonce( Editor_Nudge::NONCE_ACTION ); + $_POST['post_id'] = $this->post_id; + + ob_start(); + try { + $this->nudge->handle_dismiss(); + } catch ( \WPDieException $e ) { + ob_end_clean(); + } + + // Post-condition: the same post must no longer surface the nudge. + $this->assertFalse( + $this->nudge->allow_load(), + 'Once dismissed, allow_load() must return false for the same post on subsequent calls.' + ); + $this->assertTrue( + $this->nudge->is_dismissal_active( $this->post_id ), + 'Dismissal timestamp must be persisted on the post meta.' + ); + } + + // --------------------------------------------------------------- + // enqueue_scripts() + // --------------------------------------------------------------- + + /** + * enqueue_scripts() must no-op when allow_load() is false. + */ + public function test_enqueue_scripts_noops_when_not_allowed() { + wp_set_current_user( 0 ); + + $handle = SRFM_SLUG . '-editor-nudge'; + + $this->nudge->enqueue_scripts(); + + $this->assertFalse( + wp_script_is( $handle, 'enqueued' ), + 'Nudge script should not be enqueued when allow_load() is false.' + ); + $this->assertFalse( + wp_style_is( $handle, 'enqueued' ), + 'Nudge stylesheet should not be enqueued when allow_load() is false.' + ); + } + + /** + * enqueue_scripts should be wired to admin_enqueue_scripts in the constructor. + */ + public function test_enqueue_scripts_is_hooked_to_admin_enqueue_scripts() { + $this->assertNotFalse( + has_action( 'admin_enqueue_scripts', [ $this->nudge, 'enqueue_scripts' ] ), + 'enqueue_scripts must be registered on admin_enqueue_scripts.' + ); + } + + // --------------------------------------------------------------- + // handle_dismiss() + // --------------------------------------------------------------- + + /** + * Dismiss AJAX action should be registered. + */ + public function test_handle_dismiss_is_hooked_to_ajax_action() { + $this->assertNotFalse( + has_action( 'wp_ajax_srfm_editor_nudge_dismiss', [ $this->nudge, 'handle_dismiss' ] ), + 'handle_dismiss must be registered on the wp_ajax_srfm_editor_nudge_dismiss hook.' + ); + } + + /** + * A user lacking the required capability should receive a 403 error and not update the meta. + */ + public function test_handle_dismiss_rejects_user_without_capability() { + wp_set_current_user( $this->subscriber_id ); + $_POST['nonce'] = wp_create_nonce( Editor_Nudge::NONCE_ACTION ); + $_POST['post_id'] = $this->post_id; + + ob_start(); + try { + $this->nudge->handle_dismiss(); + } catch ( \WPDieException $e ) { + $output = ob_get_clean(); + $data = json_decode( $output, true ); + $this->assertIsArray( $data ); + $this->assertFalse( $data['success'] ); + $this->assertEmpty( + get_post_meta( $this->post_id, Editor_Nudge::DISMISS_META_KEY, true ), + 'Dismiss meta must not be written when capability check fails.' + ); + return; + } + ob_end_clean(); + $this->fail( 'Expected WPDieException for user without required capability.' ); + } + + /** + * A capable user with a valid nonce should persist the dismissed flag + * to the targeted post's meta as the current Unix timestamp. + */ + public function test_handle_dismiss_persists_post_meta_on_success() { + wp_set_current_user( $this->admin_id ); + $_POST['nonce'] = wp_create_nonce( Editor_Nudge::NONCE_ACTION ); + $_POST['post_id'] = $this->post_id; + + $before = time(); + + ob_start(); + try { + $this->nudge->handle_dismiss(); + } catch ( \WPDieException $e ) { + $output = ob_get_clean(); + $data = json_decode( $output, true ); + $this->assertIsArray( $data ); + $this->assertTrue( $data['success'] ); + + $stored = (int) get_post_meta( $this->post_id, Editor_Nudge::DISMISS_META_KEY, true ); + $this->assertGreaterThanOrEqual( + $before, + $stored, + 'Dismiss meta should be set to a fresh Unix timestamp.' + ); + $this->assertLessThanOrEqual( + time() + 1, + $stored, + 'Dismiss meta timestamp must not be in the future.' + ); + $this->assertTrue( $this->nudge->is_dismissal_active( $this->post_id ) ); + + // Other posts must remain untouched — per-post isolation. + $this->assertEmpty( + get_post_meta( $this->other_post_id, Editor_Nudge::DISMISS_META_KEY, true ), + 'Dismissing on one post must not write meta on any other post.' + ); + return; + } + ob_end_clean(); + $this->fail( 'Expected WPDieException after successful dismiss.' ); + } + + /** + * A capable user with an invalid/missing nonce must be rejected and + * the post meta must not be written. + */ + public function test_handle_dismiss_rejects_invalid_nonce() { + wp_set_current_user( $this->admin_id ); + $_POST['nonce'] = 'definitely-not-a-valid-nonce'; + $_POST['post_id'] = $this->post_id; + + ob_start(); + try { + $this->nudge->handle_dismiss(); + } catch ( \WPDieException $e ) { + $output = ob_get_clean(); + $data = json_decode( $output, true ); + $this->assertIsArray( $data ); + $this->assertFalse( $data['success'] ); + $this->assertEmpty( + get_post_meta( $this->post_id, Editor_Nudge::DISMISS_META_KEY, true ), + 'Dismiss meta must not be written when the nonce check fails.' + ); + return; + } + ob_end_clean(); + $this->fail( 'Expected WPDieException for invalid nonce.' ); + } + + /** + * The nudge never targets the SureForms form CPT, so a dismiss request + * pointed at one must be rejected before any meta is written — even + * when capability and nonce both pass. + */ + public function test_handle_dismiss_rejects_sureforms_form_post_type() { + wp_set_current_user( $this->admin_id ); + + $form_id = self::factory()->post->create( + [ + 'post_type' => SRFM_FORMS_POST_TYPE, + 'post_title' => 'Contact Us Form', + ] + ); + + $_POST['nonce'] = wp_create_nonce( Editor_Nudge::NONCE_ACTION ); + $_POST['post_id'] = $form_id; + + ob_start(); + try { + $this->nudge->handle_dismiss(); + } catch ( \WPDieException $e ) { + $output = ob_get_clean(); + $data = json_decode( $output, true ); + $this->assertIsArray( $data ); + $this->assertFalse( $data['success'] ); + $this->assertEmpty( + get_post_meta( $form_id, Editor_Nudge::DISMISS_META_KEY, true ), + 'Dismiss meta must not be written for the SureForms form CPT.' + ); + wp_delete_post( $form_id, true ); + return; + } + ob_end_clean(); + wp_delete_post( $form_id, true ); + $this->fail( 'Expected WPDieException for SureForms form post type.' ); + } + + /** + * Even with `manage_options`, the dismiss handler must enforce + * `edit_post` per-post — a user who lacks edit access to a specific + * post must not be able to write dismissal meta against it. + * + * Simulated by filtering `map_meta_cap` to deny `edit_post` on the + * targeted post, since stock administrators normally have it. + */ + public function test_handle_dismiss_rejects_user_without_edit_post_capability() { + wp_set_current_user( $this->admin_id ); + $_POST['nonce'] = wp_create_nonce( Editor_Nudge::NONCE_ACTION ); + $_POST['post_id'] = $this->post_id; + + $target_post_id = $this->post_id; + $deny_edit_post = static function ( $caps, $cap, $user_id, $args ) use ( $target_post_id ) { + if ( 'edit_post' === $cap && isset( $args[0] ) && (int) $args[0] === (int) $target_post_id ) { + return [ 'do_not_allow' ]; + } + return $caps; + }; + + add_filter( 'map_meta_cap', $deny_edit_post, 10, 4 ); + + ob_start(); + try { + $this->nudge->handle_dismiss(); + } catch ( \WPDieException $e ) { + remove_filter( 'map_meta_cap', $deny_edit_post, 10 ); + $output = ob_get_clean(); + $data = json_decode( $output, true ); + $this->assertIsArray( $data ); + $this->assertFalse( $data['success'] ); + $this->assertEmpty( + get_post_meta( $this->post_id, Editor_Nudge::DISMISS_META_KEY, true ), + 'Dismiss meta must not be written when edit_post is denied for the post.' + ); + return; + } + remove_filter( 'map_meta_cap', $deny_edit_post, 10 ); + ob_end_clean(); + $this->fail( 'Expected WPDieException for user without edit_post on the targeted post.' ); + } + + /** + * A capable user with a valid nonce but a missing or invalid post_id + * must be rejected without writing any meta — guards against stray + * dismiss requests targeting the wrong post. + */ + public function test_handle_dismiss_rejects_missing_post_id() { + wp_set_current_user( $this->admin_id ); + $_POST['nonce'] = wp_create_nonce( Editor_Nudge::NONCE_ACTION ); + unset( $_POST['post_id'] ); + + ob_start(); + try { + $this->nudge->handle_dismiss(); + } catch ( \WPDieException $e ) { + $output = ob_get_clean(); + $data = json_decode( $output, true ); + $this->assertIsArray( $data ); + $this->assertFalse( $data['success'] ); + $this->assertEmpty( + get_post_meta( $this->post_id, Editor_Nudge::DISMISS_META_KEY, true ), + 'Dismiss meta must not be written when post_id is missing.' + ); + return; + } + ob_end_clean(); + $this->fail( 'Expected WPDieException for missing post_id.' ); + } +} diff --git a/tests/unit/inc/ai-form-builder/test-ai-helper.php b/tests/unit/inc/ai-form-builder/test-ai-helper.php index 96b84ee81..61a281be3 100644 --- a/tests/unit/inc/ai-form-builder/test-ai-helper.php +++ b/tests/unit/inc/ai-form-builder/test-ai-helper.php @@ -21,4 +21,261 @@ public function test_get_error_message() { $result = AI_Helper::get_error_message( $error ); $this->assertIsString( $result ); } + + /** + * is_pro_license_active should return an empty string when the pro + * licensing class is unavailable. + */ + public function test_is_pro_license_active_returns_empty_when_pro_missing() { + if ( class_exists( 'SRFM_Pro\\Admin\\Licensing' ) ) { + $this->markTestSkipped( 'SureForms Pro is loaded in this environment; the no-pro branch cannot be exercised.' ); + } + + $this->assertSame( '', AI_Helper::is_pro_license_active() ); + } + + /** + * Invoke a protected static method on AI_Helper via reflection. + * + * @param string $method Method name. + * @param array $args Arguments. + * @return mixed + */ + protected function invoke_protected( $method, array $args ) { + $ref = new ReflectionMethod( AI_Helper::class, $method ); + $ref->setAccessible( true ); + return $ref->invokeArgs( null, $args ); + } + + /** + * decode_json_response should return decoded array on well-formed JSON. + */ + public function test_decode_json_response_valid_json() { + $result = $this->invoke_protected( + 'decode_json_response', + [ '{"form":{"formTitle":"Test"}}', 200, 'generate/form' ] + ); + $this->assertIsArray( $result ); + $this->assertArrayHasKey( 'form', $result ); + $this->assertSame( 'Test', $result['form']['formTitle'] ); + } + + /** + * decode_json_response should return the error array when body is empty. + */ + public function test_decode_json_response_empty_body() { + $result = $this->invoke_protected( + 'decode_json_response', + [ '', 200, 'generate/form' ] + ); + $this->assertIsArray( $result ); + $this->assertArrayHasKey( 'error', $result ); + } + + /** + * decode_json_response should return the error array when JSON is malformed. + */ + public function test_decode_json_response_invalid_json() { + $result = $this->invoke_protected( + 'decode_json_response', + [ '{ not valid json', 500, 'generate/form' ] + ); + $this->assertIsArray( $result ); + $this->assertArrayHasKey( 'error', $result ); + } + + /** + * decode_json_response should return the error array when JSON is valid but not an array. + */ + public function test_decode_json_response_non_array_json() { + $result = $this->invoke_protected( + 'decode_json_response', + [ '"just a string"', 200, 'generate/form' ] + ); + $this->assertIsArray( $result ); + $this->assertArrayHasKey( 'error', $result ); + } + + /** + * decode_json_response should honour the supplied fallback message. + */ + public function test_decode_json_response_uses_custom_fallback() { + $result = $this->invoke_protected( + 'decode_json_response', + [ '', 200, 'usage', 'Custom fallback' ] + ); + $this->assertSame( 'Custom fallback', $result['error'] ); + } + + /** + * log_ai_response_failure should short-circuit when WP_DEBUG is disabled. + * No return value — just verifying the call does not error. + */ + public function test_log_ai_response_failure_noop_without_wp_debug() { + if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) { + $this->markTestSkipped( 'WP_DEBUG is enabled; noop path is not exercised in this environment.' ); + } + + $this->invoke_protected( + 'log_ai_response_failure', + [ 'generate/form', 500, 'invalid_json', 'body' ] + ); + $this->assertTrue( true ); + } + + /** + * log_ai_response_failure should accept a non-string body without error. + */ + public function test_log_ai_response_failure_handles_non_string_body() { + $this->invoke_protected( + 'log_ai_response_failure', + [ 'generate/form', 500, 'invalid_json', null ] + ); + $this->assertTrue( true ); + } + + /** + * get_chat_completions_response should return the error-message array + * when wp_remote_post is short-circuited with a WP_Error via filter. + */ + public function test_get_chat_completions_response_returns_error_on_http_failure() { + $filter = static function () { + return new \WP_Error( 'http_request_failed', 'Network unreachable' ); + }; + add_filter( 'pre_http_request', $filter ); + + $result = AI_Helper::get_chat_completions_response( [ 'query' => 'Contact form' ] ); + + remove_filter( 'pre_http_request', $filter ); + + $this->assertIsArray( $result ); + } + + /** + * get_chat_completions_response should pass valid JSON through decode_json_response. + */ + public function test_get_chat_completions_response_decodes_valid_response() { + $payload = wp_json_encode( [ 'form' => [ 'formTitle' => 'Ping' ] ] ); + $filter = static function () use ( $payload ) { + return [ + 'response' => [ 'code' => 200 ], + 'body' => $payload, + 'headers' => [], + ]; + }; + add_filter( 'pre_http_request', $filter ); + + $result = AI_Helper::get_chat_completions_response( [ 'query' => 'Contact form' ] ); + + remove_filter( 'pre_http_request', $filter ); + + $this->assertIsArray( $result ); + $this->assertArrayHasKey( 'form', $result ); + } + + /** + * get_usage_response should return an error array when the HTTP call fails. + */ + public function test_get_usage_response_returns_error_on_http_failure() { + $filter = static function () { + return new \WP_Error( 'http_request_failed', 'Network unreachable' ); + }; + add_filter( 'pre_http_request', $filter ); + + $result = AI_Helper::get_usage_response(); + + remove_filter( 'pre_http_request', $filter ); + + $this->assertIsArray( $result ); + } + + /** + * get_usage_response should return the decoded payload on a 200 with valid JSON. + */ + public function test_get_usage_response_decodes_valid_payload() { + $payload = wp_json_encode( [ 'remaining' => 10, 'type' => 'registered' ] ); + $filter = static function () use ( $payload ) { + return [ + 'response' => [ 'code' => 200 ], + 'body' => $payload, + 'headers' => [], + ]; + }; + add_filter( 'pre_http_request', $filter ); + + $result = AI_Helper::get_usage_response(); + + remove_filter( 'pre_http_request', $filter ); + + $this->assertIsArray( $result ); + $this->assertSame( 10, $result['remaining'] ); + } + + /** + * sanitize_ai_error_message coerces non-strings to an empty string. + */ + public function test_sanitize_ai_error_message_returns_empty_for_non_string_input() { + $this->assertSame( '', AI_Helper::sanitize_ai_error_message( null ) ); + $this->assertSame( '', AI_Helper::sanitize_ai_error_message( [ 'message' => 'x' ] ) ); + $this->assertSame( '', AI_Helper::sanitize_ai_error_message( 0 ) ); + $this->assertSame( '', AI_Helper::sanitize_ai_error_message( '' ) ); + $this->assertSame( '', AI_Helper::sanitize_ai_error_message( " \n\t " ) ); + } + + /** + * sanitize_ai_error_message passes through messages without sensitive tokens. + */ + public function test_sanitize_ai_error_message_passes_through_clean_messages() { + $message = 'Rate limit exceeded. Please retry in a few seconds.'; + $this->assertSame( $message, AI_Helper::sanitize_ai_error_message( $message ) ); + } + + /** + * sanitize_ai_error_message strips URLs, OpenAI-shape IDs, request IDs, + * API keys, Bearer tokens, and gpt model names. Whitespace is collapsed. + * + * The function does not mutate spaces inside parentheses or other + * structural punctuation — only outer whitespace and separator-class + * punctuation is trimmed — so test expectations preserve those gaps. + */ + public function test_sanitize_ai_error_message_strips_known_infra_patterns() { + $cases = [ + 'see https://api.openai.com/v1/error for details' => 'see for details', + 'You have hit org-ABCDEF123456 quota' => 'You have hit quota', + 'failed for user-zyxwvut0987654 today' => 'failed for today', + 'rejected for req_abcDEF12345 reason' => 'rejected for reason', + 'request id: abcDEF12345 was logged' => 'was logged', + 'auth failed (key sk-abcdef0123456789ABCDEF) retry' => 'auth failed (key ) retry', + 'token Bearer abc123.def456-XYZ rejected' => 'token rejected', + 'model gpt-4o-mini-2024-07-18 unavailable' => 'model unavailable', + ]; + foreach ( $cases as $input => $expected ) { + $this->assertSame( + $expected, + AI_Helper::sanitize_ai_error_message( $input ), + sprintf( 'Failed sanitizing: %s', $input ) + ); + } + } + + /** + * sanitize_ai_error_message returns an empty string when stripping consumes + * the entire message, so callers fall back to a canonical translated message. + */ + public function test_sanitize_ai_error_message_returns_empty_when_only_infra_remains() { + $this->assertSame( '', AI_Helper::sanitize_ai_error_message( 'https://example.com' ) ); + $this->assertSame( '', AI_Helper::sanitize_ai_error_message( 'org-AAAAAA1111' ) ); + } + + /** + * Empty endpoint argument means we should not log; the public API still + * returns a sanitized message. + */ + public function test_sanitize_ai_error_message_does_not_log_when_endpoint_empty() { + // Pre-condition: WP_DEBUG state should not influence the return value + // when no endpoint is supplied. Just exercise the path without asserting + // log output (PHPUnit can't easily inspect error_log destinations here). + $result = AI_Helper::sanitize_ai_error_message( 'plain message' ); + $this->assertSame( 'plain message', $result ); + } } diff --git a/tests/unit/inc/ai-form-builder/test-field-mapping.php b/tests/unit/inc/ai-form-builder/test-field-mapping.php index b7e691f48..fa19f2b8a 100644 --- a/tests/unit/inc/ai-form-builder/test-field-mapping.php +++ b/tests/unit/inc/ai-form-builder/test-field-mapping.php @@ -15,7 +15,8 @@ public function test_generate_gutenberg_fields_empty_request() { $request->set_param( 'form_data', [] ); $result = Field_Mapping::generate_gutenberg_fields_from_questions( $request ); - $this->assertEquals( '', $result ); + $this->assertInstanceOf( WP_Error::class, $result ); + $this->assertSame( 'srfm_ai_mapping_missing_form_data', $result->get_error_code() ); } /** @@ -71,4 +72,96 @@ public function test_generate_gutenberg_fields_with_help_text() { $this->assertStringContainsString( 'wp:srfm/email', $result ); $this->assertStringContainsString( 'Enter your email address', $result ); } + + /** + * Test that form_data set to a non-array value returns the + * srfm_ai_mapping_invalid_form_data error code. + */ + public function test_invalid_form_data_returns_wp_error() { + $request = new WP_REST_Request(); + $request->set_param( 'form_data', 'not-an-array' ); + + $result = Field_Mapping::generate_gutenberg_fields_from_questions( $request ); + $this->assertInstanceOf( WP_Error::class, $result ); + $this->assertSame( 'srfm_ai_mapping_invalid_form_data', $result->get_error_code() ); + } + + /** + * Test that a missing or empty form key returns the + * srfm_ai_mapping_missing_form error code. + */ + public function test_missing_form_returns_wp_error() { + $request = new WP_REST_Request(); + $request->set_param( + 'form_data', + [ + // 'form' key intentionally absent. + 'meta' => [ 'something' => 'else' ], + ] + ); + + $result = Field_Mapping::generate_gutenberg_fields_from_questions( $request ); + $this->assertInstanceOf( WP_Error::class, $result ); + $this->assertSame( 'srfm_ai_mapping_missing_form', $result->get_error_code() ); + } + + /** + * Test that an empty or missing formFields array returns the + * srfm_ai_mapping_missing_form_fields error code. + */ + public function test_missing_form_fields_returns_wp_error() { + $request = new WP_REST_Request(); + $request->set_param( + 'form_data', + [ + 'form' => [ + 'formTitle' => 'Untitled', + 'formFields' => [], + ], + ] + ); + + $result = Field_Mapping::generate_gutenberg_fields_from_questions( $request ); + $this->assertInstanceOf( WP_Error::class, $result ); + $this->assertSame( 'srfm_ai_mapping_missing_form_fields', $result->get_error_code() ); + } + + /** + * Test that a malformed individual field returns the + * srfm_ai_mapping_invalid_field error code. + */ + public function test_invalid_field_returns_wp_error() { + $request = new WP_REST_Request(); + $request->set_param( + 'form_data', + [ + 'form' => [ + 'formFields' => [ + // Non-array entry breaks the per-field invariant. + 'not-a-field-array', + ], + ], + ] + ); + + $result = Field_Mapping::generate_gutenberg_fields_from_questions( $request ); + $this->assertInstanceOf( WP_Error::class, $result ); + $this->assertSame( 'srfm_ai_mapping_invalid_field', $result->get_error_code() ); + } + + /** + * Test that the WP_Error returned for missing form data carries the + * documented HTTP status (400) so the REST layer surfaces it. + */ + public function test_wp_error_carries_400_status() { + $request = new WP_REST_Request(); + $request->set_param( 'form_data', [] ); + + $result = Field_Mapping::generate_gutenberg_fields_from_questions( $request ); + $this->assertInstanceOf( WP_Error::class, $result ); + $data = $result->get_error_data(); + $this->assertIsArray( $data ); + $this->assertArrayHasKey( 'status', $data ); + $this->assertSame( 400, $data['status'] ); + } } diff --git a/tests/unit/inc/payments/test-front-end.php b/tests/unit/inc/payments/test-front-end.php index 318d58156..18fc0735c 100644 --- a/tests/unit/inc/payments/test-front-end.php +++ b/tests/unit/inc/payments/test-front-end.php @@ -352,6 +352,41 @@ public function test_create_subscription_intent_rejects_without_token() { $this->fail( 'Expected WPDieException for missing token in create_subscription_intent.' ); } + // --- verify_stripe_subscription_intent_and_save --- + + public function test_verify_stripe_subscription_intent_and_save_empty_subscription_id() { + $result = $this->front_end->verify_stripe_subscription_intent_and_save( + [ 'subscriptionId' => '', 'customerId' => 'cus_1', 'setupIntent' => 'seti_1' ], + 'block-1', + [ 'form-id' => 1 ] + ); + $this->assertIsArray( $result ); + $this->assertArrayHasKey( 'error', $result ); + } + + public function test_verify_stripe_subscription_intent_and_save_missing_customer_id() { + // With a valid-looking subscriptionId but no stored payment intent metadata, + // verification fails before the customer_id branch — still returns an error array. + $result = $this->front_end->verify_stripe_subscription_intent_and_save( + [ 'subscriptionId' => 'sub_nonexistent', 'customerId' => '', 'setupIntent' => 'seti_nonexistent' ], + 'block-1', + [ 'form-id' => 1 ] + ); + $this->assertIsArray( $result ); + $this->assertArrayHasKey( 'error', $result ); + } + + public function test_verify_stripe_subscription_intent_and_save_invalid_subscription_id_type() { + // Non-string subscriptionId is rejected. + $result = $this->front_end->verify_stripe_subscription_intent_and_save( + [ 'subscriptionId' => 12345, 'customerId' => 'cus_1', 'setupIntent' => 'seti_1' ], + 'block-1', + [ 'form-id' => 1 ] + ); + $this->assertIsArray( $result ); + $this->assertArrayHasKey( 'error', $result ); + } + private function call_private_method( $object, $method_name, $parameters = [] ) { $reflection = new \ReflectionClass( get_class( $object ) ); $method = $reflection->getMethod( $method_name ); diff --git a/tests/unit/inc/payments/test-payment-helper.php b/tests/unit/inc/payments/test-payment-helper.php index 2100f3247..6bd6634b4 100644 --- a/tests/unit/inc/payments/test-payment-helper.php +++ b/tests/unit/inc/payments/test-payment-helper.php @@ -411,6 +411,53 @@ public function test_get_form_submitted_value_by_slug_and_block_name_not_found() $this->assertNull( $result ); } + // --- validate_payment_amount --- + + public function test_validate_payment_amount_returns_invalid_for_nonexistent_form() { + $result = Payment_Helper::validate_payment_amount( 1000, 'usd', 999999999, 'block-1' ); + $this->assertIsArray( $result ); + $this->assertArrayHasKey( 'valid', $result ); + $this->assertFalse( $result['valid'] ); + $this->assertArrayHasKey( 'message', $result ); + $this->assertNotEmpty( $result['message'] ); + } + + public function test_validate_payment_amount_accepts_active_type_parameter() { + // Signature accepts $active_type for "both" mode resolution; missing form + // still produces an invalid result, not a fatal error. + $result = Payment_Helper::validate_payment_amount( 1000, 'usd', 0, 'block-1', 'subscription' ); + $this->assertIsArray( $result ); + $this->assertFalse( $result['valid'] ); + } + + // --- verify_payment_intent --- + + public function test_verify_payment_intent_rejects_empty_block_id() { + $result = Payment_Helper::verify_payment_intent( '', 'pi_test', [ 'form-id' => 1 ] ); + $this->assertIsArray( $result ); + $this->assertFalse( $result['valid'] ); + $this->assertNotEmpty( $result['message'] ); + } + + public function test_verify_payment_intent_rejects_empty_payment_intent_id() { + $result = Payment_Helper::verify_payment_intent( 'block-1', '', [ 'form-id' => 1 ] ); + $this->assertIsArray( $result ); + $this->assertFalse( $result['valid'] ); + } + + public function test_verify_payment_intent_rejects_missing_form_id() { + $result = Payment_Helper::verify_payment_intent( 'block-1', 'pi_test', [] ); + $this->assertIsArray( $result ); + $this->assertFalse( $result['valid'] ); + } + + public function test_verify_payment_intent_fails_without_stored_metadata() { + // No transient stored for this block+intent, so verification fails. + $result = Payment_Helper::verify_payment_intent( 'block-nonexistent', 'pi_nonexistent', [ 'form-id' => 1 ], 'one-time' ); + $this->assertIsArray( $result ); + $this->assertFalse( $result['valid'] ); + } + private function call_private_method( $object, $method_name, $parameters = [] ) { $reflection = new \ReflectionClass( Payment_Helper::class ); $method = $reflection->getMethod( $method_name ); diff --git a/tests/unit/inc/test-create-new-form.php b/tests/unit/inc/test-create-new-form.php index 31d83622c..789896b13 100644 --- a/tests/unit/inc/test-create-new-form.php +++ b/tests/unit/inc/test-create-new-form.php @@ -37,4 +37,53 @@ public function test_get_default_meta_keys_values() { $this->assertFalse( $result['_srfm_use_label_as_placeholder'] ); $this->assertFalse( $result['_srfm_is_inline_button'] ); } + + /** + * create_form should return a 500 WP_REST_Response when wp_insert_post fails. + * + * Forces wp_insert_post to fail via the `wp_insert_post_empty_content` + * filter and verifies the response carries a user-visible message rather + * than silently returning a WP_Error object or an incorrect post ID. + */ + public function test_create_form_returns_error_response_on_insert_failure() { + $user_id = wp_insert_user( + [ + 'user_login' => 'srfm_test_admin_' . uniqid(), + 'user_pass' => 'password', + 'user_email' => 'srfm_test_' . uniqid() . '@example.com', + 'role' => 'administrator', + ] + ); + $this->assertNotInstanceOf( 'WP_Error', $user_id ); + wp_set_current_user( $user_id ); + + $force_error = static function () { + return true; + }; + add_filter( 'wp_insert_post_empty_content', $force_error ); + + $request = new WP_REST_Request( 'POST' ); + $request->set_header( 'content-type', 'text/html' ); + $request->set_header( 'X-WP-Nonce', wp_create_nonce( 'wp_rest' ) ); + $request->set_body( + wp_json_encode( + [ + 'template_name' => 'AI Test Form', + 'form_data' => '

hi

', + 'template_metas' => [], + ] + ) + ); + + $response = Create_New_Form::create_form( $request ); + + remove_filter( 'wp_insert_post_empty_content', $force_error ); + wp_delete_user( $user_id ); + + $this->assertInstanceOf( 'WP_REST_Response', $response ); + $data = $response->get_data(); + $this->assertIsArray( $data ); + $this->assertArrayHasKey( 'message', $data ); + $this->assertSame( 500, $response->get_status() ); + } } diff --git a/tests/unit/modules/gutenberg/dist/blocks/advanced-heading/test-class-advanced-heading.php b/tests/unit/modules/gutenberg/dist/blocks/advanced-heading/test-class-advanced-heading.php new file mode 100644 index 000000000..fb90d13f4 --- /dev/null +++ b/tests/unit/modules/gutenberg/dist/blocks/advanced-heading/test-class-advanced-heading.php @@ -0,0 +1,72 @@ + + */ + protected function base_attributes() { + return [ + 'block_id' => 'test-block', + 'headingTitle' => 'Hello', + 'headingTitleToggle' => true, + 'headingDescToggle' => false, + 'headingDescPosition' => 'below-heading', + 'separatorStyle' => 'none', + 'separatorPosition' => 'below-heading', + ]; + } + + /** + * Render the block and assert it produced a string. + * + * @param array $attrs Block attributes. + * @return string + */ + protected function render( array $attrs ) { + $output = Advanced_Heading::get_instance()->render_html( $attrs ); + $this->assertIsString( $output ); + return (string) $output; + } + + public function test_render_html(): void { + // Malicious headingTag must be rejected and fall back to the default `h2`. + $attrs = $this->base_attributes(); + $attrs['headingTag'] = 'script>alert(1)render( $attrs ); + + $this->assertStringContainsString( '

assertStringNotContainsString( 'alert(1)', $output ); + $this->assertStringNotContainsString( 'render( $attrs ); + $this->assertStringContainsString( '

base_attributes(); + $attrs['headingWrapper'] = 'div onmouseover=alert(1)'; + $output = $this->render( $attrs ); + $this->assertStringNotContainsString( 'onmouseover', $output ); + $this->assertMatchesRegularExpression( '/
]*data-block-id="test-block"/', $output ); + + // Allowlisted headingWrapper `header` passes through. + $attrs['headingWrapper'] = 'header'; + $output = $this->render( $attrs ); + $this->assertMatchesRegularExpression( '/
]*data-block-id="test-block"/', $output ); + $this->assertStringContainsString( '
', $output ); + } +} diff --git a/tests/unit/modules/gutenberg/dist/blocks/image/test-class-spec-image.php b/tests/unit/modules/gutenberg/dist/blocks/image/test-class-spec-image.php new file mode 100644 index 000000000..8bd2591c0 --- /dev/null +++ b/tests/unit/modules/gutenberg/dist/blocks/image/test-class-spec-image.php @@ -0,0 +1,91 @@ + + */ + protected function base_attributes() { + return [ + 'block_id' => 'img-block', + 'layout' => 'default', + 'url' => 'https://example.com/image.jpg', + 'urlTablet' => '', + 'urlMobile' => '', + 'alt' => 'alt text', + 'enableCaption' => false, + 'caption' => '', + 'align' => '', + 'id' => 0, + 'href' => '', + 'rel' => '', + 'linkClass' => '', + 'linkTarget' => '', + 'title' => '', + 'width' => 200, + 'height' => 150, + 'naturalWidth' => 200, + 'naturalHeight' => 150, + 'disableLazyLoad' => false, + 'heading' => 'Caption Heading', + 'headingId' => '', + 'overlayContentPosition' => 'center center', + 'separatorStyle' => 'none', + 'separatorPosition' => 'after_title', + 'imageHoverEffect' => 'static', + ]; + } + + /** + * Render the block and assert it produced a string. + * + * @param array $attrs Block attributes. + * @return string + */ + protected function render( array $attrs ) { + $output = Advanced_Image::get_instance()->render_html( $attrs ); + $this->assertIsString( $output ); + return (string) $output; + } + + public function test_render_html(): void { + // Malicious headingTag must be rejected and fall back to the default `h2`. + $attrs = $this->base_attributes(); + $attrs['headingTag'] = 'h1 onmouseover=alert(1)'; + $output = $this->render( $attrs ); + + $this->assertStringNotContainsString( 'onmouseover', $output ); + $this->assertStringNotContainsString( 'alert(1)', $output ); + $this->assertStringContainsString( '

', $output ); + + // Allowlisted headingTag passes through. + $attrs['headingTag'] = 'h4'; + $output = $this->render( $attrs ); + $this->assertStringContainsString( '

', $output ); + $this->assertStringContainsString( '

', $output ); + + // Disallowed but harmless tag (`p`) also falls back to `h2`. + $attrs['headingTag'] = 'p'; + $output = $this->render( $attrs ); + $this->assertStringContainsString( '

', $output ); + + // headingId is escaped and emitted as an id attribute. + $attrs = $this->base_attributes(); + $attrs['headingTag'] = 'h2'; + $attrs['headingId'] = 'my-heading'; + $output = $this->render( $attrs ); + $this->assertStringContainsString( 'id="my-heading"', $output ); + } +} diff --git a/webpack.config.js b/webpack.config.js index b43b388fd..ca5c6f063 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -5,6 +5,32 @@ const path = require( 'path' ); const CopyPlugin = require( 'copy-webpack-plugin' ); const webpack = require( 'webpack' ); +const sassDeprecations = [ + 'legacy-js-api', + 'import', + 'global-builtin', +]; + +// Silence Sass deprecation warnings and Babel compact note in default rules. +defaultConfig.module.rules.forEach( ( item ) => { + if ( item.use && Array.isArray( item.use ) ) { + item.use = item.use.map( ( loader ) => { + if ( + typeof loader === 'object' && + loader.loader && + loader.loader.includes( 'sass-loader' ) + ) { + loader.options = loader.options || {}; + loader.options.sassOptions = + loader.options.sassOptions || {}; + loader.options.sassOptions.silenceDeprecations = + sassDeprecations; + } + return loader; + } ); + } +} ); + const wp_rules = defaultConfig.module.rules.filter( function ( item ) { if ( String( item.test ) === String( /\.jsx?$/ ) ) { return true; @@ -19,6 +45,12 @@ const wp_rules = defaultConfig.module.rules.filter( function ( item ) { module.exports = { ...defaultConfig, + cache: { + type: 'filesystem', + }, + performance: { + hints: false, + }, optimization: { usedExports: true, }, @@ -59,6 +91,10 @@ module.exports = { quizEmptyState: path.resolve( __dirname, 'src/admin/QuizEmptyState.js' ), surveyEmptyState: path.resolve( __dirname, 'src/admin/SurveyEmptyState.js' ), blocks: path.resolve( __dirname, 'src/blocks/blocks.js' ), + editorNudge: path.resolve( + __dirname, + 'src/admin/editor-nudge/index.js' + ), entries: path.resolve( __dirname, 'src/admin/entries/index.js' ), payments: path.resolve( __dirname, 'src/admin/payment/index.js' ), forms: path.resolve( __dirname, 'src/admin/forms/index.js' ), @@ -99,7 +135,14 @@ module.exports = { }, }, 'css-loader', - 'sass-loader', + { + loader: 'sass-loader', + options: { + sassOptions: { + silenceDeprecations: sassDeprecations, + }, + }, + }, ], }, ],